diff --git a/.gitignore b/.gitignore
index 2c1ceae12..acdd5c610 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,9 +7,11 @@
.piolibdeps
.clang_complete
.gcc-flags.json
+.cache
sonoff/user_config_override.h
build
firmware.map
+firmware.asm
## Visual Studio Code specific ######
.vscode
diff --git a/.travis.yml b/.travis.yml
index 8e950a42e..3f4121386 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,14 +1,48 @@
language: python
python:
- - '2.7'
+ - '3.7'
sudo: false
-cache:
- directories:
- - "~/.platformio"
install:
- pip install -U platformio
+ - platformio upgrade
+ - platformio update
+
+cache:
+ directories:
+ - .cache
+ - $HOME/.platformio
+
+env:
+ - ENV=sonoff
+ - ENV=sonoff-minimal
+ - ENV=sonoff-basic
+ - ENV=sonoff-knx
+ - ENV=sonoff-sensors
+ - ENV=sonoff-display
+ - ENV=sonoff-ir
+ - ENV=sonoff-BG
+ - ENV=sonoff-BR
+ - ENV=sonoff-CN
+ - ENV=sonoff-CZ
+ - ENV=sonoff-DE
+ - ENV=sonoff-ES
+ - ENV=sonoff-FR
+ - ENV=sonoff-GR
+ - ENV=sonoff-HE
+ - ENV=sonoff-HU
+ - ENV=sonoff-IT
+ - ENV=sonoff-KO
+ - ENV=sonoff-NL
+ - ENV=sonoff-PL
+ - ENV=sonoff-PT
+ - ENV=sonoff-RU
+ - ENV=sonoff-SE
+ - ENV=sonoff-SK
+ - ENV=sonoff-TR
+ - ENV=sonoff-TW
+ - ENV=sonoff-UK
script:
- - platformio run
+ - platformio run -e $ENV
before_deploy:
- for file in .pioenvs/*/firmware.bin; do cp $file ${file%/*}.bin; done
diff --git a/README.md b/README.md
index 63c82e3db..57249de6c 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.
[](https://github.com/arendst/Sonoff-Tasmota/blob/master/LICENSE.txt)
[](https://discord.gg/Ks2Kzd4)
-If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute!
+If you like **Sonoff-Tasmota**, give it a star, or fork it, and contribute!
[](https://github.com/arendst/Sonoff-Tasmota/stargazers)
[](https://github.com/arendst/Sonoff-Tasmota/network)
@@ -25,12 +25,16 @@ In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/r
See [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_changelog.ino) for detailed change information.
-The development codebase is checked hourly for changes and if new commits have been merged and compile successfuly they will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). It is important to note that these are based on the current development codebase and it is not recommended to flash it to devices used in production or which are hard to reach in the event that you need to manually flash the device if OTA failed. The last compiled commit number is also posted on the same page along with the current build status (if a firmware rebuild is in progress).
+Unless your Tasmota powered device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits unexpected behaviour for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved as some bugs in previous releases or development builds may already have been resolved.
+
+The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant (excluding non-English languages) will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA updates too). The last compiled commit number is also indicated on the same page. It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with all the available configuration options permitted.
+
+Note that there is a chance, as with any upgrade, that the device may not function as expected. You must always account for the possibility that you may need to flash the device via the serial programming interface if the OTA upgrade fails. Even with the master release, you should always attempt to test the device or a similar prototype before upgrading a device which is in production or is hard to reach. And, as always, make a backup of the device configuration before beginning any firmware update.
## Disclaimer
:warning: **DANGER OF ELECTROCUTION** :warning:
-A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth risk to yourself, your family, and your home if you don't know exactly what you are doing. Never try to flash a Sonoff device while it is connected to MAINS AC.
+An ESP82xx Wi-Fi device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth risk to yourself, your family, and your home if you don't know exactly what you are doing. Never try to flash a device using the serial programming interface while it is connected to MAINS AC.
We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site.
@@ -43,14 +47,12 @@ Download one of the released binaries from https://github.com/arendst/Sonoff-Tas
## Important User Compilation Information
If you want to compile Sonoff-Tasmota yourself keep in mind the following:
-- Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Theo's-Tasmota-Tips) for background information.
-- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later version of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisites](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisites).
+- Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Flashing) for background information.
+- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later versions of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisites](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisites).
- To make compile time changes to Sonoff-Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config_override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file.
-## Version Information
-- Sonoff-Tasmota provides all (Sonoff) modules in one file and starts with module Sonoff Basic.
-- Once uploaded, select [Module](https://github.com/arendst/Sonoff-Tasmota/wiki/Modules) using the configuration webpage, the commands ```Modules``` and ```Module``` or configure the [Template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates) for your device
-- After reboot select config menu again or use commands ```GPIOs``` and ```GPIO``` to change GPIO with desired sensor.
+## Configuration Information
+Please refer to the Installation and configuration articles in the [wiki](https://github.com/arendst/Sonoff-Tasmota/wiki).
## Migration Information
See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates:
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index d7084c559..89efea9d5 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -10,18 +10,16 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade
3. Migrate to **Sonoff-Tasmota 5.14**
4. Migrate to **Sonoff-Tasmota 6.x**
+## Supported Core versions
+This release will be supported from ESP8266/Arduino library Core version **pre-2.6.0** due to reported security and stability issues on previous Core version.
+
+Although it might still compile on previous Core versions all support will be removed starting in the next Release.
+
## Support of TLS
-TLS support for core 2.3.0 is removed.
+To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT
-TLS is supported on core 2.4.2 and up. To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT
-
-## Core version 2.3.0 vs 2.4.2 vs 2.5.2
-This release is based on ESP8266/Arduino library core 2.3.0 as some people encountered wifi related issues on core 2.4.2 and 2.5.2. For others core 2.4.2 or 2.5.2 is working just fine. All version are available from http://thehackbox.org/tasmota/release/
-
-## Change in default initial configuration tool
-Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**.
-
-To save memory space all other binaries support **WifiManager only**.
+## Initial configuration tools
+For initial configuration this release supports Webserver based **WifiManager** or **Serial** based command interface only. Support for **WPS** and **SmartConfig** has been removed.
## Supported Modules
The following hardware modules are supported.
@@ -98,74 +96,109 @@ Module | Description
68 WAGA CHCZ02MB | WAGA life CHCZ02MB Wifi Smart Switch with Energy Monitoring
69 SYF05 | Sunyesmart SYF05 RGBWW Wifi Led Bulb
70 Sonoff L1 | Sonoff L1 light strip
+71 Sonoff iFan03 | Sonoff iFan03 Wifi Smart Ceiling Fan with Light
+72 EXS Dimmer | EXS Wifi Dimmer v4
## Provided Binary Downloads
-The following binary downloads have been compiled with ESP8266/Arduino library core version **2.3.0**.
+The following binary downloads have been compiled with ESP8266/Arduino library core version **pre-2.6.0**.
-- **sonoff.bin** = The Sonoff version without Wps and SmartConfig configuration but adds more sensors. **RECOMMENDED RELEASE BINARY**
-- **sonoff-basic.bin** = The Basic version without Wps and SmartConfig configuration and most sensors.
-- **sonoff-classic.bin** = The Classic version allows initial installation using either WifiManager, Wps or SmartConfig.
-- **sonoff-BG.bin** to **sonoff-TW.bin** = The Sonoff version without Wps and SmartConfig configuration in different languages.
-- **sonoff-knx.bin** = The Knx version without Wps and SmartConfig configuration and some other features but adds KNX support.
-- **sonoff-sensors.bin** = The Sensors version without Wps and SmartConfig configuration but adds even more useful sensors.
-- **sonoff-display.bin** = The Display version without Wps and SmartConfig configuration and Energy Monitoring but adds display support.
+- **sonoff.bin** = The Sonoff version with sensors. **RECOMMENDED RELEASE BINARY**
+- **sonoff-BG.bin** to **sonoff-TW.bin** = The Sonoff version in different languages.
+- **sonoff-basic.bin** = The Basic version without most sensors.
+- **sonoff-knx.bin** = The Knx version without some features but adds KNX support.
+- **sonoff-sensors.bin** = The Sensors version adds more useful sensors.
+- **sonoff-ir** = The InfraRed Receiver and transmitter version allowing all available protocols provided by library IRremoteESP8266 but without most other features.
+- **sonoff-display.bin** = The Display version without Energy Monitoring but adds display support.
- **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**.
-Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/release/020402/
-
-Core version **2.5.2** binaries can be found at http://thehackbox.org/tasmota/release/020502/
-
## Available Features and Sensors
-| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks
-|-----------------------|---------|-------|---------|--------|------|---------|---------|--------
+| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks
+|-----------------------|---------|-------|--------|-----|---------|----|---------|--------
| MY_LANGUAGE en-GB | x | x | x | x | x | x | x |
-| USE_WPS | - | - | x | - | - | - | - | WPS
-| USE_SMARTCONFIG | - | - | x | - | - | - | - | SmartConfig
| USE_ARDUINO_OTA | - | - | - | - | - | - | - |
| USE_DOMOTICZ | - | - | x | x | x | x | - |
-| USE_HOME_ASSISTANT | - | - | - | x | x | x | - |
+| USE_HOME_ASSISTANT | - | - | x | x | x | x | - |
| USE_MQTT_TLS | - | - | - | - | - | - | - |
| USE_MQTT_TLS_CA_CERT | - | - | - | - | - | - | - |
| USE_MQTT_AWS_IOT | - | - | - | - | - | - | - |
-| USE_KNX | - | - | - | - | x | - | - |
-| USE_WEBSERVER | x | x | x | x | x | x | x | WifiManager
-| USE_EMULATION_HUE | - | x | x | x | - | x | - |
-| USE_EMULATION_WEMO | - | x | x | x | - | x | - |
-| USE_DISCOVERY | - | - | x | x | x | x | x |
-| WEBSERVER_ADVERTISE | - | - | x | x | x | x | x |
-| MQTT_HOST_DISCOVERY | - | - | x | x | x | x | x |
-| USE_TIMERS | - | x | - | x | x | x | x |
-| USE_TIMERS_WEB | - | x | - | x | x | x | x |
-| USE_SUNRISE | - | x | - | x | x | x | x |
-| USE_RULES | - | x | - | x | x | x | x |
+| USE_KNX | - | - | - | x | - | - | - |
+| USE_WEBSERVER | x | x | x | x | x | x | x |
+| USE_JAVASCRIPT_ES6 | - | - | - | - | - | - | - |
+| USE_WEBSEND_RESPONSE | - | - | - | - | - | - | - |
+| USE_EMULATION_HUE | - | x | x | - | x | - | - |
+| USE_EMULATION_WEMO | - | x | x | - | x | - | - |
+| USE_DISCOVERY | - | - | x | x | - | - | x |
+| WEBSERVER_ADVERTISE | - | - | x | x | - | - | x |
+| MQTT_HOST_DISCOVERY | - | - | x | x | - | - | x |
+| USE_TIMERS | - | x | x | x | x | x | x |
+| USE_TIMERS_WEB | - | x | x | x | x | x | x |
+| USE_SUNRISE | - | x | x | x | x | x | x |
+| USE_RULES | - | x | x | x | x | x | x |
| USE_SCRIPT | - | - | - | - | - | - | - |
| USE_EXPRESSION | - | - | - | - | - | - | - |
+| SUPPORT_IF_STATEMENT | - | - | - | - | - | - | - |
| | | | | | | | |
-| USE_ADC_VCC | x | x | x | - | - | - | - |
-| USE_COUNTER | - | - | - | x | x | x | x |
-| USE_DS18B20 | - | - | - | - | - | - | - | Single sensor
-| USE_DS18x20 | - | - | x | x | x | x | x | Multiple sensors
-| USE_DS18x20_LEGACY | - | - | - | - | - | - | - | Multiple sensors
+| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks
+| ROTARY_V1 | - | - | - | - | - | - | - |
+| USE_SONOFF_RF | - | - | x | x | x | - | - |
+| USE_RF_FLASH | - | - | x | x | x | - | - |
+| USE_SONOFF_SC | - | - | x | - | x | - | - |
+| USE_TUYA_MCU | - | x | x | x | x | - | x |
+| USE_ARMTRONIX_DIMMERS | - | - | x | x | - | - | - |
+| USE_PS_16_DZ | - | - | x | x | x | - | - |
+| USE_SONOFF_IFAN | - | - | x | x | x | - | - |
+| USE_BUZZER | - | - | x | x | x | - | - |
+| USE_ARILUX_RF | - | - | x | x | x | - | - |
+| USE_SHUTTER | - | - | - | - | - | - | - |
+| USE_DEEPSLEEP | - | - | - | - | - | - | - |
+| USE_EXS_DIMMER | - | - | - | - | - | - | - |
+| | | | | | | | |
+| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks
+| USE_LIGHT | - | x | x | x | x | x | x |
+| USE_WS2812 | - | - | x | x | x | - | x |
+| USE_WS2812_DMA | - | - | - | - | - | - | - |
+| USE_MY92X1 | - | - | x | x | x | - | x |
+| USE_SM16716 | - | - | x | x | x | - | x |
+| USE_SM2135 | - | - | x | x | x | - | x |
+| USE_SONOFF_L1 | - | - | x | x | x | - | x |
+| | | | | | | | |
+| USE_ENERGY_SENSOR | - | x | x | x | x | - | - |
+| USE_PZEM004T | - | - | x | x | x | - | - |
+| USE_PZEM_AC | - | - | x | x | x | - | - |
+| USE_PZEM_DC | - | - | x | x | x | - | - |
+| USE_MCP39F501 | - | x | x | x | x | - | - |
+| USE_SDM120 | - | - | - | - | x | - | - |
+| USE_SDM630 | - | - | - | - | x | - | - |
+| USE_DDS2382 | - | - | - | - | x | - | - |
+| USE_DDSU666 | - | - | - | - | x | - | - |
+| USE_SOLAX_X1 | - | - | - | - | - | - | - |
+| | | | | | | | |
+| USE_ADC_VCC | x | x | - | - | - | - | - |
+| USE_COUNTER | - | - | x | x | x | x | x |
+| USE_DS18x20 | - | - | x | x | x | - | x |
| USE_DHT | - | - | x | x | x | x | x |
+| USE_MAX31855 | - | - | - | - | x | - | - |
+| USE_MAX31865 | - | - | - | - | - | - | - |
| | | | | | | | |
-| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks
-| USE_I2C | - | - | - | x | x | x | x |
-| USE_SHT | - | - | - | x | x | x | x |
-| USE_HTU | - | - | - | x | x | x | x |
-| USE_BMP | - | - | - | x | x | x | x |
-| USE_BME680 | - | - | - | - | - | x | - |
-| USE_BH1750 | - | - | - | x | x | x | x |
-| USE_VEML6070 | - | - | - | - | - | x | - |
-| USE_ADS1115 | - | - | - | - | - | x | - |
+| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks
+| USE_I2C | - | - | x | x | x | - | x |
+| USE_SHT | - | - | x | x | x | - | x |
+| USE_HTU | - | - | x | x | x | - | x |
+| USE_BMP | - | - | x | x | x | - | x |
+| USE_BME680 | - | - | - | - | x | - | - |
+| USE_BH1750 | - | - | x | x | x | - | x |
+| USE_VEML6070 | - | - | - | - | x | - | - |
+| USE_ADS1115 | - | - | - | - | x | - | - |
| USE_ADS1115_I2CDEV | - | - | - | - | - | - | - |
-| USE_INA219 | - | - | - | - | - | x | - |
-| USE_SHT3X | - | - | - | x | x | x | x |
-| USE_TSL2561 | - | - | - | - | - | x | - |
-| USE_MGS | - | - | - | - | - | x | - |
-| USE_SGP30 | - | - | - | x | x | x | x |
+| USE_INA219 | - | - | - | - | x | - | - |
+| USE_INA226 | - | - | - | - | - | - | - |
+| USE_SHT3X | - | - | x | x | x | - | x |
+| USE_TSL2561 | - | - | - | - | x | - | - |
+| USE_MGS | - | - | - | - | x | - | - |
+| USE_SGP30 | - | - | x | x | x | - | x |
| USE_SI1145 | - | - | - | - | - | - | - |
-| USE_LM75AD | - | - | - | x | x | x | x |
+| USE_LM75AD | - | - | x | x | x | - | x |
| USE_APDS9960 | - | - | - | - | - | - | - |
| USE_MCP230xx | - | - | - | - | - | - | - |
| USE_PCA9685 | - | - | - | - | - | - | - |
@@ -175,129 +208,54 @@ Core version **2.5.2** binaries can be found at http://thehackbox.org/tasmota/re
| USE_DS3231 | - | - | - | - | - | - | - |
| USE_MGC3130 | - | - | - | - | - | - | - |
| USE_MAX44009 | - | - | - | - | - | - | - |
-| USE_SCD30 | - | - | - | - | - | x | - |
+| USE_SCD30 | - | - | - | - | x | - | - |
| USE_SPS30 | - | - | - | - | - | - | - |
-| USE_ADE7953 | - | - | - | x | x | x | x |
+| USE_ADE7953 | - | - | x | x | x | - | x |
| USE_VL53L0X | - | - | - | - | - | - | - |
| USE_MLX90614 | - | - | - | - | - | - | - |
+| USE_CHIRP | - | - | - | - | - | - | - |
+| USE_PAJ7620 | - | - | - | - | - | - | - |
+| USE_PCF8574 | - | - | - | - | - | - | - |
| | | | | | | | |
-| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks
+| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks
| USE_SPI | - | - | - | - | - | - | x |
-| USE_MHZ19 | - | - | - | x | x | x | x |
-| USE_SENSEAIR | - | - | - | x | x | x | x |
-| USE_PMS5003 | - | - | - | x | x | x | x |
-| USE_NOVA_SDS | - | - | - | x | x | x | x |
-| USE_ENERGY_SENSOR | - | x | x | x | x | x | - |
-| USE_PZEM004T | - | - | - | x | x | x | - |
-| USE_PZEM_AC | - | - | - | x | x | x | - |
-| USE_PZEM_DC | - | - | - | x | x | x | - |
-| USE_MCP39F501 | - | x | - | x | x | x | - |
-| USE_SERIAL_BRIDGE | - | - | - | x | x | x | x |
-| USE_SDM120 | - | - | - | - | - | x | - |
-| USE_SDM630 | - | - | - | - | - | x | - |
-| USE_MP3_PLAYER | - | - | - | - | - | x | - |
-| USE_TUYA_DIMMER | - | x | - | x | x | x | x |
-| USE_ARMTRONIX_DIMMERS | - | x | - | x | x | x | x |
-| USE_PS_16_DZ | - | x | - | x | x | x | x |
+| USE_MHZ19 | - | - | x | x | x | - | x |
+| USE_SENSEAIR | - | - | x | x | x | - | x |
+| USE_PMS5003 | - | - | x | x | x | - | x |
+| USE_NOVA_SDS | - | - | x | x | x | - | x |
+| USE_SERIAL_BRIDGE | - | - | x | x | x | - | x |
+| USE_MP3_PLAYER | - | - | - | - | x | - | - |
| USE_AZ7798 | - | - | - | - | - | - | - |
-| USE_PN532_HSU | - | - | - | - | - | x | - |
-| USE_IR_REMOTE | - | - | - | x | x | x | x |
-| USE_IR_HVAC | - | - | - | - | - | x | - |
-| USE_IR_RECEIVE | - | - | - | x | x | x | x |
-| USE_WS2812 | - | - | x | x | x | x | x |
-| USE_WS2812_DMA | - | - | - | - | - | - | - |
-| USE_ARILUX_RF | - | - | - | x | x | x | - |
-| USE_SR04 | - | - | - | x | x | x | x |
-| USE_TM1638 | - | - | - | - | - | x | - |
-| USE_HX711 | - | - | - | x | x | x | x |
-| USE_RF_FLASH | - | - | - | x | x | x | - |
-| USE_TX20_WIND_SENSOR | - | - | - | x | x | x | x |
-| USE_RC_SWITCH | - | - | - | x | x | x | x |
-| USE_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only
-| USE_SM16716 | - | x | x | x | x | x | x |
-| USE_HRE | - | - | - | - | - | x | - |
+| USE_PN532_HSU | - | - | - | - | x | - | - |
+| USE_ZIGBEE | - | - | - | - | - | - | - | Experimental
+| | | | | | | | |
+| USE_IR_REMOTE | - | - | x | x | x | x | x |
+| USE_IR_HVAC | - | - | - | - | x | x | - |
+| USE_IR_RECEIVE | - | - | x | x | x | x | x |
+| | | | | | | | |
+| USE_SR04 | - | - | x | x | x | - | x |
+| USE_TM1638 | - | - | - | - | x | - | - |
+| USE_HX711 | - | - | x | x | x | - | x |
+| USE_TX20_WIND_SENSOR | - | - | - | - | x | - | - |
+| USE_RC_SWITCH | - | - | - | - | x | - | - |
+| USE_RF_SENSOR | - | - | - | - | x | - | - | AlectoV2 only
+| USE_HRE | - | - | - | - | x | - | - |
+| USE_A4988_STEPPER | - | - | - | - | - | - | - |
+| USE_ARDUINO_SLAVE | - | - | - | - | - | - | - | Experimental
+| | | | | | | | |
+| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks
| USE_DISPLAY | - | - | - | - | - | - | x |
| USE_DISPLAY_LCD | - | - | - | - | - | - | x |
| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x |
| USE_DISPLAY_MATRIX | - | - | - | - | - | - | x |
+| USE_DISPLAY_SH1106 | - | - | - | - | - | - | x |
| USE_DISPLAY_ILI9341 | - | - | - | - | - | - | x |
| USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | Disabled for core 2.3.0
+| USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | x | Disabled for core 2.3.0
+| USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - |
+| USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - |
+| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - |
## Changelog
-Version 6.6.0 20190707
- * Remove support of TLS on core 2.3.0 and extent support on core 2.4.2 and up
- * Remove MQTT uptime message every hour
- * Refactor some defines to const
- * Refactor webserver HTML input, button, textarea, and select name based on id
- * Refactor webserver sensor data collection
- * Refactor TLS based on BearSSL, warning breaking change for fingerprints validation
- * Refactor management of lights, using classes and integers instead of floats
- * Refactor UDP initial message handling from string to char using static memory and add debug info (#5505)
- * Refactor ``IRsend`` and receive for 64-bit support (#5523)
- * Refactor MQTT which might solve issue (#5755)
- * Refactor ``IRSend`` by using heap when more than 199 values need to be send. May need increase of define MQTT_MAX_PACKET_SIZE too (#5950)
- * Refactor double to float in rules, and replaced trigonometric functions from stdlib with smaller versions (#6005)
- * Change pubsubclient MQTT_KEEPALIVE from 10 to 30 seconds for AWS IoT support
- * Change gamma correction as default behavior, ie "Ledtable 1"
- * Change PWM resolution from 8 to 10 bits for low brightness lights
- * Change ``IRSend`` Panasonic protocol to 64-bit (#5523)
- * Change ADC0 to enabled by default in my_user_config.h (#5671)
- * Change define USE_EMULATION by USE_EMULATION_HUE and USE_EMULATION_WEMO (#5826)
- * Change default ``PowerDelta`` from 80% to 0% on new installations (#5858, #5028, #4813, #4130, #4145, #3795, #3778, #3660, #3648)
- * Fix display Bug in KNX webmenu for Physical Address
- * Fix the Unescape() function and the ``SendSerial3`` behaviour
- * Fix webserver multiple Javascript window.onload functionality
- * Fix TasmotaSerial at 9600 bps solving DFPlayer comms (#5528)
- * Fix Configure Timer Web GUI (#5568)
- * Fix Shelly 2.5 I2C address priority issue when VEML6070 code is present by disabling VEML6070 for Shelly 2.5 (#5592)
- * Fix use of ``SerialDelimiter`` value 128 (#5634)
- * Fix Sonoff Pow R2 / S31 invalid energy increments (#5789)
- * Fix core 2.5.x ISR not in IRAM exception (#5837)
- * Fix Philips Hue emulation Alexa issue by using part of MAC address for LightId (#5849)
- * Fix missing white channel for WS2812 (#5869)
- * Fix PZem startup issue (#5875)
- * Fix exception 9 when syslog is enabled and NTP is just synced (#5917)
- * Fix Toggle functionality to button double press when one button and two devices are detected (#5935)
- * Fix command ``Channel`` for dual dimmers (#5940)
- * Fix not restoring white value on power off/power on (#5993)
- * Add command ``AdcParam`` to control ADC0 Temperature and Light formula parameters
- * Add command ``LedMask`` to assign which relay has access to power LED (#5602, #5612)
- * Add extended LED power control using command ``LedPowerX`` where X is 1 to 4. Enabled when "LedLink(i)" is configured too (#5709)
- * Add command ``Sensor20 1..255`` to change Nova Fitness SDS01 working period in minutes (#5452)
- * Add command ``SetOption38 6..255`` to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853)
- * Add command ``SetOption39 1..255`` to control CSE7766 (Pow R2) or HLW8032 (Blitzwolf SHP5) handling of power loads below 6W. Default setting is 128 (#5756)
- * Add command ``SetOption40 0..250`` to disable button functionality if activated for over 0.1 second. Needs SetOption1 1 and SetOption13 0 (#5449)
- * Add command ``SetOption63 0/1`` to disable relay state feedback scan at restart (#5594, #5663)
- * Add command ``SetOption64 0/1`` to switch between "-" or "_" as sensor index separator impacting DS18X20, DHT, BMP and SHT3X sensor names (#5689)
- * Add command ``SetOption65 0/1`` and more Tuya Serial based device support (#5815)
- * Add command ``WebColor`` to change GUI colors on the fly
- * Add support for AWS IoT with TLS 1.2 on core 2.4.2 and up. Full doc here: https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT
- * Add support for Badger HR-E Water Meter (#5539)
- * Add support for Shelly 2.5 Energy and overtemp Monitoring (#5592)
- * Add support for color and colortone for Philips Hue emulation via Alexa (#5600 #4809)
- * Add support for Scripts as replacement for Rules. Default disabled but can be enabled in my_user_config.h (#5689)
- * Add support for up to four LEDs related to four power outputs. Enabled when "LedLink(i)" is configured too (#5709)
- * Add support for Shelly 1PM Template ``{"NAME":"Shelly 1PM","GPIO":[56,0,0,0,82,134,0,0,0,0,0,21,0],"FLAG":2,"BASE":18}`` (#5716)
- * Add support for SPS30 Particle sensor thanks to Gerhard Mutz (#5830)
- * Add support for VL53L0x time of flight sensor. Might interfere with TSL2561 using same I2C address (#5845)
- * Add support for Sonoff L1 thanks to reef-actor (#6002)
- * Add rule Http#Initialized
- * Add rule System#Save executed just before a planned restart
- * Add rule support for single JSON value pair like {"SSerialReceived":"on"} by expanding it to {"SSerialReceived":{"Data":"on"}} allowing for trigger SSerialReceived#Data=on (#5638)
- * Add define USE_COUNTER to my_user_config.h to save space in sonoff-basic.bin and sonoff-minimal.bin
- * Add define USE_DHT to my_user_config.h to save space in sonoff-basic.bin
- * Add defines USE_EMULATION_WEMO and USE_EMULATION_HUE to my_user_config.h to control emulation features at compile time (#5826)
- * Add Toggle functionality to button double press when more devices are detected
- * Add device OverTemp (>73 Celsius) detection to Energy Monitoring devices with temperature sensor powering off all outputs
- * Add Tuya Dimmer 10 second heartbeat serial packet required by some Tuya dimmer secondary MCUs
- * Add all temperature, humidity and pressure for global access
- * Add validation check when loading settings from flash
- * Add HX711 weight restore after controlled restart or after power restore just before executing command Sensor34 7 (#5367, #5786)
- * Add GUI hexadecimal color options in my_user_config.h (#5586)
- * Add alternative ``IRSend`` command syntax ``IRSend raw,,,,,,,`` (#5610)
- * Add user configurable ADC0 to Module and Template configuration compatible with current FLAG options (#5671)
- * Add AriLux RF control GPIO option "ALux IrSel" (159) replacing "Led4i" (59) for full LED control (#5709)
- * Add LED GPIO option "LedLink" (157) and "LedLinki" (158) to select dedicated link status LED (#5709)
- * Add all 5 PWM channels individually adressable with LEDs. (#5741)
- * Add reset of Energy values when connection to sensor is lost for over 4 seconds (#5874, #5881)
- * Add checkbox to GUI password field enabling visibility during password entry only (#5934)
\ No newline at end of file
+Version 6.7.0 20191101
+ * TBS
diff --git a/SUPPORT.md b/SUPPORT.md
index 26c770b80..389c03002 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -22,4 +22,4 @@ If you're looking for support on **Sonoff-Tasmota** there are some options avail
* [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software.
* [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software.
* [Troubleshooting](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Custom.md): As a last resort, you can open new *Troubleshooting* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer.
-* [Issue a question](https://github.com/arendst/Sonoff-Tasmota/issues/new/choose): As a last resort, you can open new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer.
+* [Issue a question](https://github.com/arendst/Sonoff-Tasmota/issues/new/choose): As a last resort, you can open a new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer.
diff --git a/TEMPLATE.md b/TEMPLATE.md
deleted file mode 100644
index 33465a0e9..000000000
--- a/TEMPLATE.md
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-# Template information
-
-Sonoff-Tasmota uses Device or Module information to control peripherals connected to GPIOs. This information is stored in the ``sonoff_template.h`` file as a device specific template. The template contains information about what GPIO should be connected to what peripheral and what GPIO may be configured online using the ``GPIO`` command or GUI Configure Module menu. In addition a device may need specific coding to process the data from these peripherals. The module number as provided by the ``Modules`` command is used to select this coding.
-
-Starting with version 6.4.1.16 Sonoff-Tasmota Modules can be extended by users online using a template. To provide easy processing by Sonoff-Tasmota a user template is written as JSON text and could look like this:
-
-{"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}
-
-The four properties with UPPERCASE property names have the following functionality:
-
-Property name | Property value description
---------------|-------------------------------------------------------------------------------------------------------------------
-NAME | Up to 14 characters for the Module name
-GPIO | Up to 13 decimal numbers from 0 to 255 representing GPIO0 to GPIO5, GPIO09, GPIO10 and GPIO12 to GPIO16
-FLAG | 8 bit mask flag register
-BASE | Module number of a hard-coded device to be used when device specific functionality is needed
-
-The above example, based on the Generic Module does not allow ADC0 input.
-
-## GPIO functionality
-The GPIO functionality numbers are the same is shown by command ``GPIOs``. In addition code 255 is added to select a GPIO as user configurable via the GUI Configure Module menu.
-
-## FLAG functionality
-The FLAG value is an 8-bit mask where each bit controls a features. Add FLAG values to set multiple bits.
-
-FLAG | Mask | Feature description
------|----------|------------------------------
- 1 | xxxxxxx1 | Allowing to use Analog0 (ADC0) as input if define USE_ADC_VCC in ``my_user_config.h`` is disabled
- 2 | xxxxxx1x | Enable GUI pull-up control message
- 4 | xxxxx1xx | Not used
- 8 | xxxx1xxx | Not used
- 16 | xxx1xxxx | Not used
- 32 | xx1xxxxx | Not used
- 64 | x1xxxxxx | Not used
- 128 | 1xxxxxxx | Not used
-
-## BASE functionality
-The following table lists hard-coded device specific functionality. Notice that not all device modules need special handling.
-
-BASE | Module | Description
------|----------------|----------------------------------------------
- 4 | Sonoff Dual | Process relay and button via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps. Process buttons as single press only
- 9 | Sonoff Touch | Invert ledstate 1 functionality
- 10 | Sonoff LED | Set light type to 2 PWM channels disregarding SetOption15. Fix device specific LED instabilities by disabling GPIO04, GPIO5 and GPIO14
- 12 | 4 Channel | See 4
- 13 | Motor C/AC | Force all relays ON at Power On and disable command ``PowerOnState``
- 15 | EXS Relay(s) | Enable pulse latching using even/odd numbered relay pairs
- 18 | Generic | Show Wemos specific pin information in GUI
- 19 | H801 | Change hardware UART Tx from GPIO01 to GPIO02
- 20 | Sonoff SC | Enable and Process data via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps
- 21 | Sonoff BN-SZ | Set light type to 1 PWM channel disregarding SetOption15
- 22 | Sonoff 4CH Pro | Button handling disregarding SetOption13 only allowing single press to enable RF learning while holding the button
- 24 | Sonoff Bridge | Enable and Process data via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps. Process 16 buttons in web GUI. Enable EFM8BB1 firmware upload
- 25 | Sonoff B1 | Set light type to RGBWC using MY92x1
- 26 | AiLight | Set light type to RGBW using MY92x1
- 27 | Sonoff T1 1CH | See 9
- 28 | Sonoff T1 2CH | See 9
- 29 | Sonoff T1 3CH | See 9
- 38 | Sonoff Dual R2 | Process buttons as single press only
- 43 | Sonoff iFan02 | Enable command ``Fanspeed``. Disable Interlock and PulseTime. Tune status information, MQTT data and GUI. Sync with microcontroller. Process Domoticz Fan state
- 47 | Xiaomi Philips | Process Color Temperature using PWM2 and Intensity using PWM1
- 53 | Tuya Dimmer | Enable and Process data via software or hardware serial interface using GPIO 148 and 149 or forced GPIO01 and GPIO03. Change baudrate to 9600 bps. Process all Buttons
- 55 | ARMTR Dimmer | Enable and Process data via software or hardware serial interface using GPIO 148 and 149. Change baudrate to 115200 bps.
- 57 | PS-16-DZ | Enable and Process data via software or hardware serial interface using GPIO 148 and 149. Change baudrate to 19200 bps.
- 61 | YTF IR Bridge | Disable serial interface to stop loopback
- 65 | Mi Desk Lamp | Process rotary and Button1 data specific to this device
-
-## Usage
-A user provided template can be stored in Sonoff-Tasmota using the ``Template`` command. It has the following options.
-
-Command | Payload | Description
----------|----------|---------------------------------------
-Template | | Show current user template
-Template | 0 | Copy active module template to user template
-Template | 1 .. 69 | Copy hard-coded module template to user template
-
-The following command will store a complete template based on the Generic module
-``Template {"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}``
-
-The following command will update the name of a stored template
-``Template {"NAME":"UserModule2"}``
-
-The following command will update the flag of a stored template
-``Template {"FLAG":1}``
-
-The following command will update the base of a stored template to Generic
-``Template {"BASE":0}``
diff --git a/TEMPLATES.md b/TEMPLATES.md
new file mode 100644
index 000000000..2cb5b4773
--- /dev/null
+++ b/TEMPLATES.md
@@ -0,0 +1,613 @@
+
+
+# Templates
+
+Find below the available templates as of October 22nd, 2019. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates)
+
+## Bulb
+```
+A19 RGBW 8W E26 {"NAME":"OOOLED 60W RGB","GPIO":[255,255,255,255,39,40,255,255,37,255,38,255,255],"FLAG":1,"BASE":18}
+Aisirer 9W A19 E26 {"NAME":"AISIRER E26","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18}
+Anoopsyche CW/WW 60W {"NAME":"Anoop-CW-WW","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18}
+Aoycocr A19 {"NAME":"AoycocrA19","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18}
+Arlec GLD112HA {"NAME":"Arlec CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48}
+Arlec GLD122HA {"NAME":"Arlec RGBWW","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+Ausein E14 7W White {"NAME":"Tuya RGBW","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18}
+Avatar 5W E14 {"NAME":"AVATAR","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27}
+BNeta A60 E27 {"NAME":"OM60/RGBW","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18}
+BNeta GU10 RGB {"NAME":"BNeta","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18}
+Bomcosy 7W E27 RGB CW {"NAME":"Generic","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":1,"BASE":18}
+Brilliant 20741 {"NAME":"Brilliant RGB+","GPIO":[255,255,255,255,37,40,255,255,38,0,39,0,0],"FLAG":0,"BASE":18}
+Brilliant HK17653S72 {"NAME":"Brilliant E14 ","GPIO":[255,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18}
+Candle 6W E14/E27 RGBWW {"NAME":"E14_RGBWW_6W","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":20}
+DGM L-WT9W1 {"NAME":"DGM L-WT9W1","GPIO":[0,0,0,0,140,142,0,0,38,37,141,0,0],"FLAG":0,"BASE":18}
+electriQ RGBW B22 {"NAME":"ElectricQ B22","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18}
+EleLight 7W A19 E27 RGBW {"NAME":"EleLight 7wA19","GPIO":[255,255,255,255,140,37,255,255,255,142,141,255,255],"FLAG":0,"BASE":18}
+Esicoo 9W E26 {"NAME":"Esicoo Bulb","GPIO":[0,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27}
+Fcmila 7W RGBW E27 {"NAME":"FCMILA 7W","GPIO":[255,255,255,255,39,40,255,255,37,255,38,255,255],"FLAG":0,"BASE":18}
+Fcmila EQ723 {"NAME":"FCMILA LED E27","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18}
+Fcmila FC-12W {"NAME":"SYF05","GPIO":[255,0,255,0,140,37,0,0,255,255,141,0,255],"FLAG":1,"BASE":69}
+Feit Electric BPA800/RGBW/AG/2 {"NAME":" BPA800/RGBW","GPIO":[255,255,255,255,37,38,255,255,141,142,140,255,255],"FLAG":0,"BASE":48}
+Feit Electric BR30/927CA/AG {"NAME":"Feit BR30 WW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18}
+Feit Electric BR30/950CA/AG {"NAME":"Feit BR30 CW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18}
+Feit Electric OM60/927CA/AG {"NAME":" Feit P_A800_2","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18}
+Feit Electric OM60/RGBW/CA/AG {"NAME":"OM60/RGBW","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18}
+Geeni Lux A21 White {"NAME":"Geeni-1050-WW","GPIO":[0,0,0,0,37,37,0,0,38,0,0,0,0],"FLAG":1,"BASE":18}
+Generic 10W E26/E27 RGBW {"NAME":"10W E27 RGBW","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18}
+Globe CW/WW {"NAME":"Globe CW/WW","GPIO":[0,0,0,0,38,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18}
+Globe RGBW {"NAME":"GlobeRGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18}
+Gosund E27 8W RGBW {"NAME":"Gosund RGB+W","GPIO":[255,255,255,255,40,255,255,255,37,38,39,255,255],"FLAG":0,"BASE":18}
+Jomarto 9W B22 {"NAME":"Jomarto Wifi S","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":1,"BASE":18}
+Kainsy 7W E27 RGBW {"NAME":"KAINSY","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27}
+Kogan SmarterHome⢠White 10W B22 {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,37,40,0,0,41,38,39,0,0],"FLAG":0,"BASE":18}
+Kohree A19 7W {"NAME":"Kohree VHP560","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18}
+LE A19 RGBCT 9W E26 {"NAME":"LE RGBWW 60W","GPIO":[255,0,255,0,140,37,0,0,38,142,141,0,255],"FLAG":1,"BASE":18}
+Legelite E26 {"NAME":"Legelite E26","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+Linganzh LWE3 6W RGBW {"NAME":"Linganzh LWE3 ","GPIO":[255,255,255,255,255,38,255,255,39,255,40,37,255],"FLAG":0,"BASE":18}
+Lohas 5W E12 {"NAME":"LH-5W-ZN01204","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27}
+Lohas 9W E26 RGBW {"NAME":"Lohas RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":18}
+Lohas A19 RGBW E12 {"NAME":"Lohas","GPIO":[17,255,255,255,0,0,0,0,0,143,0,144,0],"FLAG":1,"BASE":26}
+Lohas E14 R50 {"NAME":"Lohas E14 R50","GPIO":[17,255,255,255,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27}
+Lohas ZN031 {"NAME":"Lohas ZN031","GPIO":[255,255,255,255,38,37,255,255,41,39,40,255,255],"FLAG":0,"BASE":18}
+LSC Smart Connect Multicolor Spot GU10 {"NAME":"LSC RGBCW LED","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18}
+LSC Smart Connect Smart Filament LED {"NAME":"LSC-Filam-Big","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18}
+Lumiman E27 Multicolor {"NAME":"Lumiman RGB","GPIO":[255,255,255,255,37,40,255,255,38,41,39,52,255],"FLAG":1,"BASE":18}
+Lumiman LM530 E26 {"NAME":"Lumiman LM530","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":1,"BASE":18}
+Lumiman LM650 {"NAME":"Legelite E26","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+Luminea ZX-2831 E27 CCT {"NAME":"Luminea CCT","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18}
+Luminea ZX-2832 E27 RGBW {"NAME":"Luminea RGBW","GPIO":[255,255,255,255,140,37,255,255,38,142,141,255,255],"FLAG":1,"BASE":18}
+Lyasi PT-BW09 {"NAME":"Lyasi PT-BW09","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27}
+Maxcio YX-L01P-E7 {"NAME":"Maxcio YXL01P","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27}
+Merkury A19 60W {"NAME":"MI-BW902-999W","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18}
+Merkury A21 75W {"NAME":"MI-BW904-999W","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":1,"BASE":69}
+Merkury BR30 65W {"NAME":"MI-BW905-999W","GPIO":[0,0,0,0,37,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18}
+Mirabella Genio CW {"NAME":"GenioBulbCW","GPIO":[0,0,0,0,38,37,0,0,0,40,39,0,0],"FLAG":0,"BASE":18}
+Mirabella Genio Dimmable {"NAME":"GenioBulbCCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18}
+Mirabella Genio RGBW {"NAME":"GenioBulbRGB","GPIO":[255,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":1,"BASE":18}
+Mixigoo 10W E27 RGBW {"NAME":"Mixigoo Bulb","GPIO":[255,255,255,255,41,38,255,255,39,255,37,40,255],"FLAG":0,"BASE":18}
+MOKO YX-L01C-E27 {"NAME":"MOKO","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27}
+Nedis WIFILC10WTE27 {"NAME":"Nedis RGBW","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":1,"BASE":18}
+Nedis WIFILW10WTE27 {"NAME":"WIFILW10WTE27","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18}
+NiteBird TT-WB4 {"NAME":"NiteBird TT-WB","GPIO":[255,255,255,255,40,255,255,255,37,38,39,255,255],"FLAG":0,"BASE":18}
+Novostella 12W RGBCT E27 {"NAME":"Novostella","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+Novostella B22 7W {"NAME":"Novostella B22","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18}
+Oobest RGBW E27 {"NAME":"WifiBulb","GPIO":[0,0,0,0,0,37,0,0,39,40,38,0,0],"FLAG":1,"BASE":18}
+Oobest ZN93028 11W E27 RGB {"NAME":"RGB Bulb 11W","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":1,"BASE":18}
+Reafoo 9W A26 {"NAME":"ReaFooE26","GPIO":[0,0,0,0,41,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18}
+RGBW 7W B22 {"NAME":"SM16716","GPIO":[255,255,255,255,140,37,255,255,255,255,141,255,255],"FLAG":0,"BASE":18}
+RGBW 7W E14 {"NAME":"7W-E14-RGBW-La","GPIO":[255,255,255,255,38,37,255,255,39,255,40,255,255],"FLAG":0,"BASE":18}
+Solimo 12W B22 RGBWW {"NAME":"Solimo RGBWW12","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+Solimo 9W B22 RGBWW {"NAME":"Solimo RGBWW 9","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+Sonoff B1 (R2) {"NAME":"Sonoff B1","GPIO":[17,255,255,255,0,0,0,0,143,0,144,0,0],"FLAG":0,"BASE":26}
+TCP B22 RGBW {"NAME":"TCP Smart RGBW","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18}
+Teckin SB50 {"NAME":"Teckin SB50","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18}
+Teckin SB50 v2 {"NAME":"Teckin SB50","GPIO":[255,255,255,255,37,255,255,255,38,40,39,255,255],"FLAG":0,"BASE":18}
+Teckin SB50 V3 {"NAME":"Teckin SB50v3","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+Teckin SB51 {"NAME":"Teckin SB51","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18}
+Teckin SB53 {"NAME":"Teckin SB53","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+TikLOk 7.5W A19 E26 {"NAME":"TikLOk WW-CW-L","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18}
+Wipro Garnet B22 9W {"NAME":"WiproSmartBulb","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18}
+Woopower RGBW E14 5W {"NAME":"Woopower E14","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27}
+Xiaomi Phillips E14 {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48}
+Xiaomi Phillips E27 {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48}
+XMRJ {"NAME":"XMRJ","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27}
+ZZHXON 6W E14/E27 {"NAME":"E27_RGB_Bulb","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18}
+```
+
+## Bulb Socket
+```
+Elegant Choice E27/E26 {"NAME":"Sm Lghtg Base","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+Slampher {"NAME":"Slampher","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":9}
+SmartBase E0260 {"NAME":"SmartBaseE0260","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+```
+
+## Curtain Switch
+```
+Teepao {"NAME":"Taopao","GPIO":[255,255,255,18,22,19,255,255,255,21,255,255,17],"FLAG":1,"BASE":18}
+WF-CS01 {"NAME":"Tuya Shutter","GPIO":[157,0,54,10,22,19,0,0,17,21,53,23,52],"FLAG":0,"BASE":18}
+```
+
+## DIY Project
+```
+LC-Tech 1Ch and PZEM-004T {"NAME":"HW-655 PZEM","GPIO":[0,63,0,62,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18}
+Luani HVIO {"NAME":"Luani HVIO","GPIO":[0,255,255,255,21,22,0,0,9,10,255,52,0],"FLAG":1,"BASE":35}
+SUPLA inCan by Espablo {"NAME":"Supla Espablo","GPIO":[0,255,4,255,17,21,0,0,255,22,255,0,52],"FLAG":1,"BASE":31}
+```
+
+## Development Board
+```
+Witty Cloud {"NAME":"Witty Cloud","GPIO":[255,255,56,255,17,255,0,0,38,39,255,37,255],"FLAG":1,"BASE":32}
+```
+
+## Dimmer
+```
+Armtronix AC Dimmer One Triac Board {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56}
+Armtronix AC Dimmer Two Triac Board {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56}
+CE Smart Home WF500D {"NAME":"CE-WF500D","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54}
+EVA LOGIK WF31 {"NAME":"WF31 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54}
+EX-Store 2 Kanal RS232 V4 {"NAME":"EXS Dimmer","GPIO":[0,148,0,149,255,255,0,0,255,183,255,0,0],"FLAG":0,"BASE":72}
+Kingart Touch {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255,52,255,255,255],"FLAG":0,"BASE":58}
+Moes DS01 {"NAME":"MOES - DS01","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54}
+Moes QS-WiFi-D01 Dimmer 150W {"NAME":"WiFi-Dimmer","GPIO":[0,148,0,149,0,0,0,0,0,42,37,0,0],"FLAG":0,"BASE":18}
+PS-16-DZ {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255,52,255,255,255],"FLAG":0,"BASE":58}
+Zemismart KS-7011 {"NAME":"KS-7011 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54}
+```
+
+## Environment Monitor
+```
+Sonoff SC {"NAME":"Sonoff SC","GPIO":[17,148,255,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":21}
+```
+
+## Fan Controller
+```
+Sonoff iFan02 {"NAME":"Sonoff iFan02","GPIO":[17,255,0,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":44}
+Sonoff iFan03 {"NAME":"SonoffiFan03","GPIO":[17,148,0,149,0,0,29,161,23,56,22,24,0],"FLAG":0,"BASE":71}
+```
+
+## Humidifier
+```
+Asakuki 500ml {"NAME":"Oil Diffuser","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":0,"BASE":18}
+Maxcio 400ml {"NAME":"MaxcioDiffuser","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54}
+Oil Diffuser 550ML {"NAME":"Oil Diffuser","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":0,"BASE":18}
+```
+
+## IR Bridge
+```
+Alfawise KS1 {"NAME":"KS1","GPIO":[255,71,17,72,17,51,0,0,56,0,8,0,0],"FLAG":1,"BASE":62}
+auvisio S06 {"NAME":"NX-4519-675","GPIO":[255,255,255,255,52,51,255,255,255,255,8,255,255],"FLAG":1,"BASE":18}
+Eachen SANT-IR 01 {"NAME":"Eachen IR","GPIO":[0,0,0,0,56,51,255,255,255,17,8,0,0],"FLAG":0,"BASE":18}
+Geeklink {"NAME":"GL IR Blaster","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62}
+Mirabella Genio HKWL-IR02W {"NAME":"Genio IR TxRx","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62}
+STITCH by Monoprice 35753 {"NAME":"Stitch 35753","GPIO":[0,0,0,0,52,51,0,0,0,90,8,0,0],"FLAG":0,"BASE":18}
+YTF {"NAME":"YTF IR Bridge","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62}
+```
+
+## LED Controller
+```
+Arilux AL-LC01 {"NAME":"Arilux LC01","GPIO":[17,255,59,255,147,37,0,0,38,39,255,0,0],"FLAG":0,"BASE":37}
+Arilux AL-LC06 {"NAME":"Arilux LC06","GPIO":[17,255,255,255,255,255,255,255,38,39,37,41,40],"FLAG":0,"BASE":18}
+Arilux AL-LC11 {"NAME":"Arilux LC11","GPIO":[17,255,59,255,38,37,0,0,41,40,39,147,0],"FLAG":0,"BASE":38}
+Electrodragon Mosfet Drive {"NAME":"LEDBoard RGBW","GPIO":[255,0,0,0,255,255,0,0,39,38,40,37,52],"FLAG":0,"BASE":18}
+H801 {"NAME":"H801","GPIO":[255,52,255,255,41,57,0,0,39,38,40,37,0],"FLAG":0,"BASE":20}
+LEDEnet {"NAME":"LEDEnet","GPIO":[0,255,56,255,147,0,0,0,38,39,37,40,0],"FLAG":0,"BASE":34}
+Luminea ZX-2844 {"NAME":"Luminea ZX-284","GPIO":[40,255,255,255,0,39,255,255,38,17,37,255,255],"FLAG":0,"BASE":18}
+MagicHome RGB ZJ-WFMN-A V1.1 {"NAME":"MagicHome RGB","GPIO":[0,0,0,0,0,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":34}
+MagicHome RGBW ZJ-WFMN-A V1.1 {"NAME":"MagicHome RGBW","GPIO":[0,0,0,0,51,38,0,0,37,39,0,40,0],"FLAG":0,"BASE":34}
+MagicHome ZJ-ESP-IR-F V1 {"NAME":"ZJ-ESP-IR-F V1","GPIO":[255,255,255,255,51,38,255,255,37,39,255,40,255],"FLAG":0,"BASE":18}
+Nexlux {"NAME":"MagicHome V1.1","GPIO":[0,0,0,0,51,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":34}
+Shelly RGBW2 {"NAME":"RGBW2","GPIO":[255,255,33,255,24,91,255,255,21,17,23,22,255],"FLAG":0,"BASE":18}
+```
+
+## LED Strip
+```
+BlitzWolf BW-LT11 {"NAME":"BW-LT11 Strip","GPIO":[17,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18}
+LSC Smart Connect RGBW {"NAME":"LSC-RGBW-Strip","GPIO":[51,0,0,0,37,0,0,0,38,40,39,0,0],"FLAG":0,"BASE":18}
+Merkury Innovations MI-EW003-999W {"NAME":"MI-EW003-999W ","GPIO":[17,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+Mirabella Genio 3 Metre {"NAME":"MirabellaStrip","GPIO":[17,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18}
+Monster Smart IlluminEssence {"NAME":"MI-EW003-999W ","GPIO":[17,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18}
+Sonoff L1 {"NAME":"SonoffL1","GPIO":[0,148,0,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":70}
+Torchstar {"NAME":"Torchstar","GPIO":[255,255,255,255,52,255,255,255,255,255,255,37,53],"FLAG":1,"BASE":18}
+```
+
+## Light
+```
+Brilliant 20702/06 Garden {"NAME":"Brilliant Gard","GPIO":[0,0,0,0,37,0,255,255,38,0,39,0,0],"FLAG":0,"BASE":18}
+Brilliant Smart WiFi Downlight CCT {"NAME":"SmartCCTDwnLgt","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48}
+Fcmila XDD-48W {"NAME":"XDD-48W","GPIO":[0,0,0,0,37,40,0,0,38,25,39,0,0],"FLAG":0,"BASE":18}
+Mi LED Desk Lamp MJTD01YL {"NAME":"Mi Desk Lamp","GPIO":[0,0,17,0,37,38,0,0,150,151,0,0,0],"FLAG":0,"BASE":66}
+Mirabella Genio Dimmable CCT Downlight {"NAME":"GenioDLightCCT","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":48}
+Mirabella Genio Dimmable RGBCCT Downlight {"NAME":"GenioDLightRGB","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18}
+Sonoff BN-SZ01 {"NAME":"Sonoff BN-SZ","GPIO":[0,0,0,0,0,0,0,0,37,56,0,0,0],"FLAG":0,"BASE":22}
+Spotlight 9cm RGB+W 7W {"NAME":"Spotlight RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27}
+Utorch PZE-911 {"NAME":"Utorch PZE-911","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":1}
+Utorch UT40 {"NAME":"Utorch UT40","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":1}
+Wipro Next 20W Smart LED Batten {"NAME":"WIPROBatten","GPIO":[255,255,255,255,255,37,255,255,255,47,255,255,255],"FLAG":1,"BASE":18}
+Zemismart 14W RGB-CCT {"NAME":"ZemiDownLight6","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18}
+Zemismart 4" 10W RGBW {"NAME":"ZemiDownLight","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27}
+```
+
+## Outdoor Plug
+```
+Acenx SOP04-US Dual {"NAME":"SOP04-US Dual","GPIO":[255,255,255,255,56,57,255,255,21,17,22,255,255],"FLAG":0,"BASE":18}
+Albohes PC-1606 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39}
+ECF-SOP03 {"NAME":"Outdoor3Outlet","GPIO":[0,0,0,23,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18}
+Feit Electric Dual {"NAME":"Prime Smart ou","GPIO":[255,255,255,255,157,56,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+Geeni GN-OW101-101 {"NAME":"Geeni Outdoor","GPIO":[17,0,0,0,0,57,0,0,0,52,21,0,0],"FLAG":0,"BASE":18}
+LEPOWER {"NAME":"LEPOWER Outdoo","GPIO":[255,255,255,255,56,57,255,255,21,17,22,255,255],"FLAG":0,"BASE":18}
+Oittm Outdoor {"NAME":"Oittm Outdoor","GPIO":[17,0,0,0,0,0,0,0,0,0,56,21,255],"FLAG":0,"BASE":18}
+SK03 {"NAME":"SK03 Outdoor","GPIO":[17,0,0,0,133,132,0,0,131,57,56,21,0],"FLAG":0,"BASE":57}
+Top-Max PS-1602 {"NAME":"PS-1602","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29}
+```
+
+## Plug
+```
+3Stone Mini {"NAME":"3Stone Smart P","GPIO":[0,17,0,0,0,0,0,0,0,57,21,0,0],"FLAG":0,"BASE":18}
+Acashna HS108 {"NAME":"HS108","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18}
+Aisirer UK1 {"NAME":"AISIRER","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":1,"BASE":18}
+Albohes PS-1602 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39}
+Aldi Medion Life+ S85225 {"NAME":"Medion","GPIO":[0,0,0,17,134,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":52}
+Alexfirst TV-ASP801EU {"NAME":"Alexfirst","GPIO":[17,0,0,0,54,56,0,0,21,0,0,0,0],"FLAG":0,"BASE":18}
+Alfawise PE1004T {"NAME":"PE1004T","GPIO":[255,255,255,255,56,57,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+Amysen YX-WS01 {"NAME":"Amyse YX WS01","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18}
+ANBES ABS-CZ004 {"NAME":"ANBES ABS-CZ00","GPIO":[0,0,0,0,21,133,0,0,131,17,132,22,18],"FLAG":0,"BASE":18}
+Anoopsyche AWP07L {"NAME":"Anoopsyche AWP","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18}
+Anoopsyche JH-G01B1 {"NAME":"JH-G01B1","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41}
+Anoopsyche UK1D {"NAME":"UK1D","GPIO":[0,17,0,0,133,132,0,0,130,52,21,0,0],"FLAG":0,"BASE":6}
+Aoycocr EU5-16A {"NAME":"Aoycocr","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17}
+Aoycocr Smart Plug {"NAME":"Aoycocr Smart ","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18}
+Arlec Grid Connect PC189HA {"NAME":"Arlec","GPIO":[0,0,0,0,123,0,0,0,21,56,17,0,0],"FLAG":0,"BASE":18}
+Arlec Twin PC288HA {"NAME":"Arlec Twin","GPIO":[0,17,0,22,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18}
+Aukey SH-PA1 {"NAME":"AUKEY SH-PA1","GPIO":[0,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18}
+Avatar 10A {"NAME":"AWP07L","GPIO":[56,255,255,255,255,134,255,255,130,17,132,21,255],"FLAG":1,"BASE":18}
+Avatar AWP07L 10A {"NAME":"Avatar AWP07L","GPIO":[56,255,255,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Avatto JH-G01E {"NAME":"AVATTO JH-G01E","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41}
+AWP02L-N {"NAME":"AWP02L-N","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18}
+AWP04L {"NAME":"AWP04L","GPIO":[57,255,255,131,255,134,0,0,21,17,132,56,255],"FLAG":0,"BASE":18}
+AWP07L {"NAME":"AISIRER AWP07L","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18}
+AWP08L {"NAME":"AWP08L","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18}
+AzpenHome Smart {"NAME":"Socket2Me","GPIO":[52,255,255,255,22,255,0,0,21,255,17,255,255],"FLAG":0,"BASE":18}
+Bestek MRJ1011 {"NAME":"BestekMRJ1011","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1}
+Bilikay SP10 {"NAME":"Bilikay SP10","GPIO":[255,37,255,17,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18}
+Blitzwolf BW-SHP2 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Blitzwolf BW-SHP3 {"NAME":"Blitzwolf SHP3","GPIO":[56,0,57,0,22,134,0,0,131,18,132,21,17],"FLAG":0,"BASE":45}
+Blitzwolf BW-SHP3 alt {"NAME":"Blitzwolf SHP3","GPIO":[18,56,0,131,134,132,0,0,17,0,22,21,0],"FLAG":0,"BASE":18}
+Blitzwolf BW-SHP4 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Blitzwolf BW-SHP5 {"NAME":"SHP5","GPIO":[57,145,56,146,0,22,0,0,0,0,21,0,17],"FLAG":0,"BASE":18}
+Blitzwolf BW-SHP6 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Blitzwolf BW-SHP8 {"NAME":"SHP8","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64}
+BN-LINK BNC-60/U133TJ-2P {"NAME":"BNC-60/U133TJ","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":18}
+Brilliant USB Charger {"NAME":"Brilliant","GPIO":[0,0,0,0,0,21,0,0,0,52,90,0,0],"FLAG":0,"BASE":18}
+BSD15 {"NAME":"TuyaPlugBSD15","GPIO":[255,255,255,255,255,255,255,255,21,17,56,255,255],"FLAG":1,"BASE":18}
+BSD25 {"NAME":"Tuya Wifi Plug","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+BSD29 {"NAME":"BSD29","GPIO":[0,0,0,131,134,132,0,0,21,17,56,0,0],"FLAG":0,"BASE":52}
+BSD33 {"NAME":"Generic","GPIO":[255,255,255,131,134,132,255,255,21,17,56,255,255],"FLAG":0,"BASE":18}
+BSD34 {"NAME":"BSD34 Plug","GPIO":[255,255,255,255,255,255,255,255,21,17,56,255,255],"FLAG":0,"BASE":18}
+CE Smart Home - LA-WF3 {"NAME":"CE LA-WF3","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+Conico SM-PW70 {"NAME":"Conico SM-PW70","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":1,"BASE":18}
+Coosa {"NAME":"COOSA","GPIO":[0,0,0,0,57,52,0,0,21,17,255,0,0],"FLAG":0,"BASE":1}
+Coosa SP1 {"NAME":"COOSA SP1","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+CrazyLynX WiFi {"NAME":"CrazyLynX","GPIO":[255,255,255,255,57,56,255,255,21,17,255,255,255],"FLAG":1,"BASE":18}
+CYYLTF BIFANS J23 {"NAME":"CYYLTD BIFANS J23","GPIO":[56,0,0,0,0,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18}
+Delock 11826 {"NAME":"Delock 11826","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1}
+Digoo DG-SP01 {"NAME":"DG-SP01","GPIO":[255,17,255,21,56,37,255,255,38,39,40,255,255],"FLAG":0,"BASE":18}
+Digoo NX-SP202 {"NAME":"Generic_SP202","GPIO":[52,0,0,131,91,134,0,0,22,17,132,21,0],"FLAG":0,"BASE":63}
+DILISENS SP201 {"NAME":"Dilisens SP201","GPIO":[0,0,131,0,133,132,52,21,18,22,17,0,0],"FLAG":0,"BASE":18}
+DWFeng AWP02L-N {"NAME":"AWP02L-N","GPIO":[255,255,56,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18}
+ECO Plugs CT-065W {"NAME":"ECO/CT-065W","GPIO":[255,255,255,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18}
+EFUN SH331W {"NAME":"Efun-Plug","GPIO":[56,0,158,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18}
+EletecPro 2 {"NAME":"EletecPro-2","GPIO":[255,255,255,255,17,255,255,255,53,52,21,255,255],"FLAG":1,"BASE":18}
+ENJOWI SP111-EU-W {"NAME":"Enjowi SP111-E","GPIO":[17,56,0,0,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55}
+Epicka {"NAME":"Epicka","GPIO":[255,255,255,255,57,56,255,255,21,17,255,255,255],"FLAG":1,"BASE":18}
+Esicoo YX-WS01 {"NAME":"Esicoo Plug","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18}
+Estink C178 {"NAME":"Estink C178","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+ESW01-US {"NAME":"ESW01-US","GPIO":[0,0,0,0,21,56,0,0,0,0,9,0,0],"FLAG":1,"BASE":18}
+ET RGB {"NAME":"RGB Smart Plug","GPIO":[37,0,39,0,38,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+EVA LOGIK NWF001 {"NAME":"EVA LOGIK Plug","GPIO":[255,17,255,255,255,255,255,255,255,52,21,255,255],"FLAG":0,"BASE":18}
+EVO-Smart JH-G01U {"NAME":"EVO JH-G01U","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":0,"BASE":18}
+FK-PW901U {"NAME":"FK-PW901U","GPIO":[56,255,255,255,255,23,255,255,21,17,24,22,255],"FLAG":0,"BASE":18}
+FLHS-ZN04 {"NAME":"FLHS-ZN04","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Fontastic SH01 {"NAME":"Fontastic","GPIO":[255,0,255,0,56,0,255,255,21,17,0,0,0],"FLAG":1,"BASE":18}
+FrankEver FLHS-ZN04 {"NAME":"Israel plug","GPIO":[57,0,56,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":45}
+GDTech W-US001 {"NAME":"GDTech W-US001","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18}
+GDTech W-US003 {"NAME":"W-US003","GPIO":[0,17,255,255,255,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18}
+Geeni Charge {"NAME":"Geeni Charge","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+Geeni Glo {"NAME":"Geeni Glo","GPIO":[0,0,0,0,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18}
+Geeni Spot {"NAME":"Geeni Spot","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+Geeni Switch Duo {"NAME":"Geeni Duo","GPIO":[0,0,0,0,18,22,0,0,17,52,21,0,53],"FLAG":0,"BASE":18}
+Globe Smart {"NAME":"GlobeSmartPlug","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18}
+Gosund SP1 {"NAME":"Gosund SP1 v23","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55}
+Gosund SP111 {"NAME":"Gosund SP111","GPIO":[56,0,57,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18}
+Gosund SP112 {"NAME":"SHP5","GPIO":[56,145,57,146,255,22,0,0,255,255,21,255,18],"FLAG":0,"BASE":18}
+Gosund WP1-1 {"NAME":"Gosund WP1-1","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Gosund WP211 {"NAME":"Gosund wp211","GPIO":[0,0,0,0,21,0,0,0,0,17,0,22,18],"FLAG":0,"BASE":18}
+Gosund WP212 {"NAME":"Gosund_WP212","GPIO":[17,0,0,0,18,0,0,0,21,0,22,0,0],"FLAG":0,"BASE":18}
+Gosund WP3 {"NAME":"Gosund WP3","GPIO":[0,0,0,0,17,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18}
+Gosund WP5 {"NAME":"Gosund-WP5","GPIO":[255,255,255,255,17,255,255,255,53,52,21,255,255],"FLAG":1,"BASE":18}
+Gosund WP6 {"NAME":"Gosund WP6","GPIO":[0,0,0,17,0,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18}
+Grefic TE101 {"NAME":"Grefic TE101","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1}
+Gyman SM-PW701U {"NAME":"Gyman","GPIO":[255,255,157,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+Hauppauge SL-1642 {"NAME":"SL-1642","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+HiHome WPP-16T {"NAME":"HiHome WPP-16T","GPIO":[17,56,255,255,134,132,255,255,18,255,22,130,21],"FLAG":1,"BASE":18}
+hiwild W-US002 {"NAME":"W-US002","GPIO":[0,17,0,0,0,0,0,0,0,52,21,0,158],"FLAG":0,"BASE":18}
+Houzetek AWP07L {"NAME":"AWP07L","GPIO":[56,255,255,130,255,134,255,255,0,17,132,21,255],"FLAG":0,"BASE":18}
+HuaFan QinLu {"NAME":"Huafan SS","GPIO":[56,0,0,57,17,29,0,0,132,130,133,0,0],"FLAG":0,"BASE":24}
+Hyleton 313 {"NAME":"Hyleton 313","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18}
+Hyleton 317 {"NAME":"hyleton-317","GPIO":[56,0,57,0,58,0,0,0,0,90,0,21,0],"FLAG":0,"BASE":18}
+Innens BSD29 {"NAME":"BSD29","GPIO":[0,0,56,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":52}
+iSwitch {"NAME":"Smart Plug XSA","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18}
+Jeeo TF-SH330 {"NAME":"Jeeo TF-SH330","GPIO":[56,255,255,255,255,255,255,255,255,17,255,21,255],"FLAG":1,"BASE":18}
+Jinvoo SM-PW701U {"NAME":"SM-PW702","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+Jinvoo SM-PW762U {"NAME":"SM-PW762U","GPIO":[0,0,0,0,158,56,0,0,21,17,22,0,0],"FLAG":0,"BASE":18}
+Jules V (Upgrade Version) {"NAME":"Jules-V_UV","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18}
+Jules.V NX-SM300 {"NAME":"NX-SM300","GPIO":[52,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":6}
+Kimire S12 {"NAME":"Kimire S12","GPIO":[255,255,255,17,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18}
+King-Link C128 {"NAME":"King-Link C128","GPIO":[0,0,55,0,22,53,0,0,23,52,17,21,54],"FLAG":0,"BASE":18}
+KMC 4 30608 {"NAME":"KMC 4 Outlet","GPIO":[0,56,0,0,133,132,0,0,130,22,23,21,17],"FLAG":0,"BASE":36}
+KMC 70011 {"NAME":"KMC 70011","GPIO":[17,0,0,0,133,132,0,0,130,56,21,0,0],"FLAG":0,"BASE":36}
+Kogan SmarterHome⢠Energy Meter {"NAME":"Kogan Smart Sw","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18}
+Koogeek KLSP1 {"NAME":"Koogeek-KLSP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18}
+Koogeek KLUP1 {"NAME":"Koogeek-KLUP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18}
+LA-WF3 {"NAME":"CE Smart Plug","GPIO":[255,255,255,255,56,57,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+Laduo YX-DE01 {"NAME":"YX-DE01","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18}
+LESHP KS-501 {"NAME":"LESHP KS-501","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1}
+LINGANZH 16A {"NAME":"Linganzh Smart","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18}
+Lonsonho 10A Type E {"NAME":"Lonsonho10ALed","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+Lonsonho RGB {"NAME":"RGB Smart Plug","GPIO":[37,0,38,0,0,39,0,0,0,17,0,21,0],"FLAG":0,"BASE":45}
+LSC Smart Connect {"NAME":"LSC Smart Plug","GPIO":[255,255,255,255,56,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18}
+Luminea ZX-2820-675 {"NAME":"ZX2820-675","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Luminea ZX-2820-919 {"NAME":"Luminea ZX2820","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":65}
+Martin Jerry {"NAME":"MJ V01","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+Martin Jerry XS-SSA01 {"NAME":"MJ_XS-SSA01","GPIO":[0,0,0,0,0,0,0,0,56,17,0,21,0],"FLAG":0,"BASE":18}
+Maxcio W-DE004 {"NAME":"Maxcio W-DE004","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18}
+Maxcio W-UK007 {"NAME":"Maxcio","GPIO":[0,17,0,0,0,0,255,255,0,56,21,0,0],"FLAG":0,"BASE":18}
+Maxcio W-UK007S {"NAME":"Maxcio","GPIO":[56,0,255,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Maxcio W-US002S {"NAME":"W-US002S","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Maxcio W-US003 {"NAME":"W-US003","GPIO":[255,17,255,255,255,255,255,255,255,22,21,255,255],"FLAG":0,"BASE":18}
+Maxcio YX-DE02 {"NAME":"Generic","GPIO":[255,17,255,21,56,37,255,255,38,39,40,255,255],"FLAG":1,"BASE":18}
+Merisny P2 {"NAME":"Generic","GPIO":[0,0,52,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18}
+Merkury 70011 MIC-WW102 {"NAME":"MIC-WW102","GPIO":[17,0,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":36}
+Merkury Innovations {"NAME":"Merkury Switch","GPIO":[255,255,255,255,53,56,255,255,21,17,255,255,255],"FLAG":1,"BASE":18}
+Merkury MI-OW101-101W {"NAME":"Merkury Switch","GPIO":[17,255,255,255,255,56,255,255,255,255,21,255,255],"FLAG":1,"BASE":18}
+Mirabella Genio {"NAME":"Genio 1","GPIO":[0,0,56,0,0,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1}
+Nanxin NX-SM200 16A {"NAME":"NX-SM200","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18}
+NEO Coolcam 16A {"NAME":"Neo Coolcam 16","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49}
+Obi Stecker {"NAME":"OBI Socket","GPIO":[255,255,0,255,52,21,0,0,54,255,17,0,255],"FLAG":1,"BASE":51}
+Obi Stecker 2 {"NAME":"OBI Socket 2","GPIO":[0,0,0,0,21,17,0,0,56,53,0,0,0],"FLAG":0,"BASE":61}
+Obi Stecker IP44 {"NAME":"OBI Socket 2","GPIO":[0,0,0,0,21,17,0,0,56,53,0,0,0],"FLAG":0,"BASE":61}
+Oittm Smart {"NAME":"Oittm","GPIO":[0,0,0,0,21,56,0,0,17,0,0,0,0],"FLAG":0,"BASE":1}
+Oukitel P1 {"NAME":"Oukitel P1Dual","GPIO":[52,255,255,255,255,255,255,255,22,17,255,21,255],"FLAG":0,"BASE":18}
+Oukitel X6P {"NAME":"OUKITEL X6P","GPIO":[255,255,57,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18}
+OxaOxe NX-SM200 {"NAME":"NX-SM200","GPIO":[17,0,0,0,133,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":18}
+Oxaoxe NX-SM800 {"NAME":"NX-SM800","GPIO":[0,0,0,131,0,134,0,0,21,17,132,0,0],"FLAG":0,"BASE":45}
+OxaOxe NX-SP202 {"NAME":"oxaoxe-dual","GPIO":[18,0,0,0,134,132,0,0,131,56,21,22,17],"FLAG":0,"BASE":18}
+OxaOxe NX-SP202 v2 {"NAME":"oxaoxe-dold","GPIO":[56,0,0,131,17,134,0,0,21,18,132,22,0],"FLAG":0,"BASE":18}
+Panamalar NX-SM200 16A {"NAME":"NX-SM200","GPIO":[0,0,0,0,56,134,0,0,131,17,132,21,0],"FLAG":1,"BASE":18}
+Powertech {"NAME":"Jaycar","GPIO":[56,0,0,0,0,0,0,0,0,9,0,21,0],"FLAG":0,"BASE":6}
+Powrui AW-08 {"NAME":"POWRUI AW-08","GPIO":[0,0,0,0,9,21,0,0,0,52,57,0,0],"FLAG":1,"BASE":18}
+Prime CCRCWFII113PK {"NAME":"Prime","GPIO":[0,0,0,0,57,56,0,0,21,122,0,0,0],"FLAG":0,"BASE":18}
+RGB Light {"NAME":"RGB Light","GPIO":[37,0,38,0,0,39,0,0,0,90,0,21,0],"FLAG":0,"BASE":18}
+RSH-WS007 {"NAME":"RSH-WS007","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18}
+Shelly Plug S {"NAME":"Shelly Plug S","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":2,"BASE":45}
+Slitinto NX-SM110 {"NAME":"Slitinto SM110","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Slitinto NX-SM112 {"NAME":"NX-SM112","GPIO":[158,0,0,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":45}
+Slitinto NX-SP202 {"NAME":"Slitinto SP202","GPIO":[17,0,0,0,134,132,0,0,131,52,22,21,91],"FLAG":0,"BASE":64}
+SM-PW702 {"NAME":"SM-PW702","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+SmartDGM PP-W162 {"NAME":"SmartDGM Plug","GPIO":[0,0,0,17,134,132,0,0,131,52,21,0,0],"FLAG":0,"BASE":18}
+Sonoff S20 {"NAME":"Sonoff S20","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":8}
+Sonoff S22 TH {"NAME":"Sonoff S22","GPIO":[17,255,0,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":4}
+Sonoff S26 {"NAME":"Sonoff S26","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":8}
+Sonoff S31 {"NAME":"Sonoff S31","GPIO":[17,145,0,146,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":41}
+SP201 Dual {"NAME":"SP-201","GPIO":[31,0,0,131,17,134,0,0,21,18,132,22,0],"FLAG":0,"BASE":45}
+SS01 {"NAME":"Smart Plug SS0","GPIO":[255,255,255,255,255,255,255,255,21,17,255,255,255],"FLAG":1,"BASE":18}
+STITCH by Monoprice 27937 {"NAME":"Stitch 27937","GPIO":[17,0,56,0,133,132,0,0,131,0,21,0,57],"FLAG":0,"BASE":18}
+STITCH by Monoprice 35511 {"NAME":"Stitch 35511","GPIO":[56,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18}
+SuperNight Dual {"NAME":"SuperNight Dua","GPIO":[255,17,255,21,132,133,255,255,22,130,58,255,255],"FLAG":1,"BASE":18}
+SWA1 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18}
+SWA1 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18}
+SWA11 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18}
+SWA9 {"NAME":"SWA9","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18}
+TanTan WP3 {"NAME":"TanTan WP3","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18}
+Teckin SP10 {"NAME":"Teckin SP10","GPIO":[255,255,56,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18}
+Teckin SP20 {"NAME":"TECKIN SP20","GPIO":[56,255,57,255,21,134,0,0,131,17,132,0,0],"FLAG":0,"BASE":45}
+Teckin SP21 {"NAME":"Teckin SP21","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":45}
+Teckin SP22 {"NAME":"Teckin","GPIO":[0,17,0,57,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":52}
+Teckin SP23 {"NAME":"Teckin SP23","GPIO":[56,255,57,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45}
+Teckin SP25 {"NAME":"Teckin SP25","GPIO":[56,255,255,255,255,255,255,255,22,17,255,21,255],"FLAG":1,"BASE":18}
+Teckin SP27 {"NAME":"Teckin SP27","GPIO":[56,255,255,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18}
+Tflag NX-SM100 {"NAME":"NX-SM100","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18}
+THRUMM XS-A11 {"NAME":"THRUMM XS-A11 ","GPIO":[255,17,255,255,255,255,255,255,255,56,29,255,255],"FLAG":0,"BASE":18}
+Timethinker TK04 {"NAME":"TimethinkerEU","GPIO":[255,255,255,255,17,255,0,0,255,52,21,255,0],"FLAG":0,"BASE":18}
+TimeThinker WS2 {"NAME":"TimeThinkerWS2","GPIO":[0,0,0,0,17,0,0,0,0,52,21,0,0],"FLAG":0,"BASE":18}
+TomaxUSA HKWL-SO07W {"NAME":"HKWL-SO07W","GPIO":[17,255,255,255,255,255,255,255,255,255,21,255,56],"FLAG":0,"BASE":18}
+WAGA life CHCZ02MB {"NAME":"WAGA CHCZ02MB","GPIO":[57,0,0,131,0,134,0,0,21,17,132,56,0],"FLAG":0,"BASE":68}
+WAZA 10A {"NAME":"WAZA","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":1,"BASE":18}
+WAZA JH-G01B {"NAME":"Teckin SP27","GPIO":[255,255,255,255,53,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+WAZA JH-G01E {"NAME":"Waza JH-G01E","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18}
+WiOn 50055 {"NAME":"WiOn","GPIO":[255,0,52,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17}
+WL-SC01 {"NAME":"WL-SC01","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":1}
+Woox R4026 {"NAME":"WOOX R4026","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18}
+XS-SSA01 {"NAME":"XS-SSA01","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18}
+XS-SSA01 Alternate {"NAME":"XS-SSA01","GPIO":[255,17,255,255,255,255,255,255,56,255,255,21,255],"FLAG":0,"BASE":18}
+XS-SSA05 {"NAME":"XS-SSA05","GPIO":[30,255,255,131,255,133,255,255,21,17,132,31,255],"FLAG":1,"BASE":18}
+XS-SSA06 {"NAME":"RGB Light","GPIO":[37,0,38,0,0,39,0,0,0,90,0,21,0],"FLAG":0,"BASE":18}
+Yelomin JH-G01E {"NAME":"Yelomin","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":18}
+YERON US101 {"NAME":"YERON_US101","GPIO":[255,255,255,17,133,132,255,255,131,56,21,255,255],"FLAG":0,"BASE":18}
+YT-E003 {"NAME":"YT-E003-SP202","GPIO":[17,0,0,0,134,132,0,0,131,52,22,21,91],"FLAG":0,"BASE":64}
+YX-WS02 {"NAME":"Amysen YX-WS02","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18}
+ZBR-001 {"NAME":"ZBR-001","GPIO":[17,255,255,255,133,132,255,255,130,56,21,255,57],"FLAG":1,"BASE":18}
+ZooZee {"NAME":"ZooZee","GPIO":[57,255,56,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18}
+ZooZee SA102 {"NAME":"ZooZee","GPIO":[57,255,56,255,21,133,255,255,131,17,132,255,255],"FLAG":0,"BASE":18}
+ZooZee SE131 {"NAME":"ZooZee SE131","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17}
+ZSP-001 {"NAME":"ZSP-001","GPIO":[17,255,255,255,133,132,255,255,130,57,21,255,56],"FLAG":1,"BASE":18}
+```
+
+## Power Strip
+```
+3Stone (2019 Model) {"NAME":"3Stone-2019","GPIO":[0,0,56,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18}
+ACENX 3AC+3USB {"NAME":"ACENX 3-Outlet","GPIO":[56,55,54,53,0,21,0,0,23,24,22,0,17],"FLAG":0,"BASE":18}
+Annhome 3AC + 2USB {"NAME":"1200W WiFi SPS","GPIO":[32,0,0,0,57,52,0,0,21,17,22,23,33],"FLAG":0,"BASE":18}
+AOFO 3AC+4USB {"NAME":"AOFO","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18}
+AOFO 4AC+4USB {"NAME":"AOFO4AC4USB","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18}
+CE Garden Power Stake {"NAME":"CE Power Stake","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+CE Smart Home LTS-6A-W5 {"NAME":"CE Power Strip","GPIO":[52,0,0,0,22,21,0,0,24,23,25,26,17],"FLAG":0,"BASE":18}
+CRST LTS-4G-W {"NAME":"CRST LTS-4G-W","GPIO":[0,0,0,0,24,0,255,255,22,23,21,0,0],"FLAG":0,"BASE":18}
+Digoo DG-PS01 {"NAME":"Digoo DG-PS01","GPIO":[0,56,0,17,23,22,0,0,0,24,21,0,0],"FLAG":1,"BASE":18}
+Geekbes 4AC+4USB {"NAME":"Geekbes 4xStri","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18}
+Geeni GN-SW003 {"NAME":"Geeni GNCSW003","GPIO":[52,0,0,0,22,21,0,0,24,25,23,26,17],"FLAG":0,"BASE":18}
+Hyleton 330 {"NAME":"Hyleton-330","GPIO":[57,0,0,56,29,17,0,0,31,30,32,0,25],"FLAG":0,"BASE":18}
+Hyleton 331 {"NAME":"HLT-331","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,58],"FLAG":0,"BASE":18}
+Hyleton 336 {"NAME":"HLT-336","GPIO":[52,0,0,57,29,17,0,0,31,30,0,0,32],"FLAG":0,"BASE":18}
+KMC 5 {"NAME":"KMC 5-Outlet","GPIO":[56,0,0,0,25,9,0,0,22,21,23,0,24],"FLAG":0,"BASE":18}
+Koogeek KLOE4 {"NAME":"Koogeek KLOE4","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18}
+LeFun SK2 {"NAME":"LeFun SK2","GPIO":[0,0,0,17,22,21,0,0,23,24,25,0,0],"FLAG":0,"BASE":18}
+Meross MSS425 {"NAME":"Meross MSS425","GPIO":[33,0,0,0,56,0,0,0,21,17,22,23,32],"FLAG":0,"BASE":18}
+Monoprice 34082 {"NAME":"Stitch 34082","GPIO":[255,255,255,255,21,20,255,255,23,22,24,255,255],"FLAG":0,"BASE":18}
+Nedis WIFIP310FWT {"NAME":"Nedis WIFIP310","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18}
+Powrui AW-39 {"NAME":"Porui AW-39","GPIO":[56,0,0,0,21,255,0,0,23,24,22,0,9],"FLAG":0,"BASE":18}
+S2199EU {"NAME":"S2199EU","GPIO":[0,17,0,52,23,25,0,0,21,24,22,0,0],"FLAG":1,"BASE":18}
+SM-S0301 {"NAME":"SM-SO301","GPIO":[56,0,0,0,30,17,0,0,32,31,33,0,21],"FLAG":0,"BASE":18}
+SM-S0301 {"NAME":"SM-SO301","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,25],"FLAG":0,"BASE":18}
+SWB1 {"NAME":"SWB1","GPIO":[52,0,0,0,0,24,0,0,21,17,22,23,0],"FLAG":0,"BASE":18}
+Teckin SS30 {"NAME":"Teckin SS30","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,58],"FLAG":0,"BASE":18}
+Tellur TLL331031 {"NAME":"Tellur","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18}
+TESSAN A4L-BK {"NAME":"TESSAN A4L-BK","GPIO":[0,0,0,24,23,0,255,255,21,0,22,0,0],"FLAG":0,"BASE":18}
+Viflykoo 3AC+4USB {"NAME":"Viflykoo 3xStr","GPIO":[0,0,53,0,0,23,0,0,21,56,17,24,22],"FLAG":1,"BASE":18}
+Woox R4028 {"NAME":"Woox R4028","GPIO":[0,56,0,17,23,22,0,0,0,24,21,0,0],"FLAG":1,"BASE":18}
+Xenon SM-S0301 {"NAME":"SM-SO301","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,25],"FLAG":0,"BASE":18}
+XS-A25 {"NAME":"XS-A25","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18}
+XSA26-EU {"NAME":"XSA26-EU","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18}
+Yagala {"NAME":"Yagala","GPIO":[0,0,0,17,22,24,0,0,23,25,21,0,0],"FLAG":0,"BASE":18}
+Yagala SWB3 {"NAME":"YAGALA SWB3","GPIO":[0,0,53,0,0,23,0,0,21,0,22,24,0],"FLAG":1,"BASE":18}
+Yagala SWB3 v2 {"NAME":"YAGALA SWB3","GPIO":[157,0,53,0,0,23,0,0,21,17,22,0,0],"FLAG":0,"BASE":18}
+Yuanguo 4AC + 2 USB {"NAME":"YUANGUO","GPIO":[0,20,0,24,19,18,0,0,17,22,21,23,0],"FLAG":0,"BASE":1}
+Zeoota PS022 {"NAME":"ZEOOTA 3x plus","GPIO":[0,57,0,56,22,21,0,0,17,23,24,0,0],"FLAG":1,"BASE":18}
+ZLD-44EU-W {"NAME":"ZLD-44EU-W","GPIO":[17,255,255,255,22,21,18,19,23,24,25,0,0],"FLAG":0,"BASE":23}
+ZLD-44USA-W {"NAME":"ZLD-44USA-W","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18}
+ZLD64-EU-W {"NAME":"ZLD64-EU-W","GPIO":[0,56,0,17,22,21,0,0,0,0,23,0,0],"FLAG":0,"BASE":18}
+```
+
+## RF Bridge
+```
+Sonoff RF Bridge 433 {"NAME":"Sonoff Bridge","GPIO":[17,148,255,149,255,255,0,0,255,56,255,0,0],"FLAG":0,"BASE":25}
+```
+
+## Relay
+```
+1 Channel Inching/Self-Locking {"NAME":"1 Channel","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":12}
+Blitzwolf BW-SS1 {"NAME":"BW-SS1","GPIO":[255,255,255,255,157,21,0,0,255,17,255,255,0],"FLAG":0,"BASE":18}
+Canwing CW-001 {"NAME":"Canwing CW-001","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1}
+EACHEN ST-DC2 {"NAME":"Garage Control","GPIO":[11,0,0,0,23,22,18,0,21,52,12,24,0],"FLAG":1,"BASE":18}
+Electrodragon Board SPDT {"NAME":"ED Relay Board","GPIO":[255,255,255,255,255,255,255,255,21,22,255,255,52],"FLAG":1,"BASE":18}
+Electrodragon ESP8266 {"NAME":"ElectroDragon","GPIO":[18,255,17,255,255,255,0,0,22,21,255,255,52],"FLAG":1,"BASE":15}
+eMylo SS-8839-03 {"NAME":"eMylo","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":1,"BASE":18}
+eMylo XL9251WI {"NAME":"XL9251WI","GPIO":[255,255,255,255,56,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18}
+eMylo YSA111A1N-FBA {"NAME":"Emylo","GPIO":[255,255,255,255,52,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18}
+ESP-01 Relay V4.0 {"NAME":"ESP01v4","GPIO":[29,52,0,255,255,255,255,255,255,255,255,255,255],"FLAG":0,"BASE":18}
+EX Store 2 Kanal V5 {"NAME":"EXS Relay V5","GPIO":[255,255,255,255,255,255,0,0,21,22,31,52,32],"FLAG":0,"BASE":16}
+Geekcreit 2 Channel {"NAME":"Geekcreit 2ch","GPIO":[17,0,0,0,0,22,18,0,21,52,0,0,0],"FLAG":1,"BASE":18}
+Gocomma Wi-Fi Smart Switch {"NAME":"GoCommaSmartSw","GPIO":[17,255,255,255,21,255,255,255,255,56,255,255,255],"FLAG":0,"BASE":18}
+LC Technology 4CH {"NAME":"LC-Tech_4CH ","GPIO":[52,255,17,255,255,255,255,255,21,22,23,24,255],"FLAG":0,"BASE":18}
+LinkNode R4 {"NAME":"LinkNode R4","GPIO":[0,0,0,0,0,0,0,0,21,22,23,0,24],"FLAG":0,"BASE":18}
+LinkNode R8 {"NAME":"LinkNode R8","GPIO":[0,0,0,0,25,26,0,28,23,24,22,27,21],"FLAG":0,"BASE":18}
+MHCOZY {"NAME":"Portail","GPIO":[9,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":1,"BASE":18}
+Moeshouse 2 way 2 gang MS-104B {"NAME":"moeshouse2gang","GPIO":[0,0,17,0,160,0,0,0,43,42,21,22,0],"FLAG":0,"BASE":18}
+Nova Digital Basic 1 MS101 {"NAME":"NovaDigBasic1","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+QS-WIFI-S03 {"NAME":"Generic","GPIO":[17,255,255,255,255,0,0,0,82,21,0,0,0],"FLAG":0,"BASE":1}
+Shelly 1 {"NAME":"Shelly 1","GPIO":[0,0,0,0,21,82,0,0,0,0,0,0,0],"FLAG":0,"BASE":46}
+Shelly 1PM {"NAME":"Shelly 1PM","GPIO":[56,0,0,0,82,134,0,0,0,0,0,21,0],"FLAG":2,"BASE":18}
+Shelly 2 {"NAME":"Shelly 2","GPIO":[0,135,0,136,21,22,0,0,9,0,10,137,0],"FLAG":0,"BASE":47}
+Shelly 2.5 {"NAME":"Shelly 2.5","GPIO":[56,255,17,255,21,83,0,0,6,82,5,22,156],"FLAG":2,"BASE":18}
+SmartHome Smart Breaker {"NAME":"SmartHome Swit","GPIO":[255,255,255,255,21,255,255,255,17,57,255,56,255],"FLAG":0,"BASE":18}
+Sonoff 4CH (R2) {"NAME":"Sonoff 4CH","GPIO":[17,255,255,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":7}
+Sonoff 4CH Pro (R2) {"NAME":"Sonoff 4CH Pro","GPIO":[17,255,255,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":23}
+Sonoff 5V Inching/Selflock Module RE5V1C {"NAME":"Sonoff RE5V1C","GPIO":[17,255,255,255,255,255,0,0,21,56,0,0,0],"FLAG":0,"BASE":18}
+Sonoff Basic {"NAME":"Sonoff Basic","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":1}
+Sonoff Basic R3 {"NAME":"Basic R3","GPIO":[17,255,0,255,255,0,255,255,21,56,255,0,255],"FLAG":0,"BASE":1}
+Sonoff Dual {"NAME":"Sonoff Dual","GPIO":[0,148,0,149,255,0,0,0,0,56,255,0,0],"FLAG":0,"BASE":5}
+Sonoff Dual R2 {"NAME":"Sonoff Dual R2","GPIO":[255,255,0,255,0,22,255,17,21,56,0,0,0],"FLAG":0,"BASE":39}
+Sonoff Mini {"NAME":"Sonoff Mini","GPIO":[17,0,0,0,9,0,0,0,21,56,0,0,255],"FLAG":0,"BASE":1}
+Sonoff Pow {"NAME":"Sonoff Pow","GPIO":[17,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":6}
+Sonoff Pow R2 {"NAME":"Sonoff Pow R2","GPIO":[17,145,0,146,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":43}
+Sonoff RF {"NAME":"Sonoff RF","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":2}
+Sonoff SV {"NAME":"Sonoff SV","GPIO":[17,255,0,255,255,255,0,0,21,56,255,0,0],"FLAG":1,"BASE":3}
+Sonoff TH10/TH16 {"NAME":"Sonoff TH","GPIO":[17,255,0,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":4}
+Tuya Kinetic Switch {"NAME":"Kinetic Switch","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+Wemos Module 10A {"NAME":"WeMos Relay","GPIO":[17,255,52,255,21,255,255,255,255,255,255,255,255],"FLAG":0,"BASE":18}
+WL-SW01_10 {"NAME":"WL-SW01_10","GPIO":[17,149,0,148,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1}
+Yunshan 10A 7-30VDC {"NAME":"Yunshan Relay","GPIO":[0,255,56,255,21,17,0,0,0,0,0,0,0],"FLAG":0,"BASE":33}
+Zemismart ERC309 Kinetic {"NAME":"Kinetic Switch","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54}
+```
+
+## Switch
+```
+3A Smart Home HGZB-043 {"NAME":"3A Smart Home ","GPIO":[52,0,55,18,22,19,0,0,17,21,54,23,53],"FLAG":0,"BASE":18}
+Deta 6912HA {"NAME":"DETA 2G Switch","GPIO":[0,0,0,0,157,0,0,0,91,21,22,0,90],"FLAG":0,"BASE":18}
+DS-102 1 Gang {"NAME":"DS-102 1 Gang","GPIO":[57,0,0,17,0,0,0,0,0,21,56,0,0],"FLAG":1,"BASE":18}
+DS-102 2 Gang {"NAME":"DS-102 2 Gang","GPIO":[56,58,0,17,22,18,0,0,0,21,57,255,0],"FLAG":0,"BASE":18}
+DS-102 3 Gang {"NAME":"DS-102 3 Gang","GPIO":[158,58,0,18,22,19,0,0,17,21,57,23,56],"FLAG":0,"BASE":18}
+Enjowi WF-SK301 {"NAME":"Tuya 3 Channel","GPIO":[0,0,0,0,23,18,0,0,17,21,19,22,157],"FLAG":0,"BASE":18}
+Etekcity 3-way {"NAME":"Etekcity 3Way","GPIO":[255,255,0,255,23,29,0,0,82,22,10,0,0],"FLAG":0,"BASE":18}
+EtekCity ESWL01 {"NAME":"EtekCityESWL01","GPIO":[255,255,255,255,52,53,255,255,255,21,122,255,255],"FLAG":1,"BASE":18}
+Gosund KS-602S {"NAME":"Gosund KS-602S","GPIO":[17,56,0,0,0,0,0,0,0,0,21,0,158],"FLAG":0,"BASE":18}
+Jinvoo SM-SW101-1 {"NAME":"SM-SW101-1","GPIO":[52,0,0,18,0,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18}
+Jinvoo SM-SW101-2 {"NAME":"SM-SW101-2","GPIO":[52,0,0,18,22,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18}
+Jinvoo SM-SW101-3 {"NAME":"Jinvoo Wall Sw","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18}
+Jinvoo SM-SW101-C Curtain {"NAME":"Jinvoo Curtain","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18}
+KMC 70008 {"NAME":"KMC 70008","GPIO":[17,255,255,0,0,255,255,255,0,56,21,255,255],"FLAG":0,"BASE":18}
+KOAANW DS302 {"NAME":"DS302","GPIO":[0,0,0,19,23,18,0,0,17,21,0,22,52],"FLAG":1,"BASE":18}
+KS-601 2-way {"NAME":"2way Switch","GPIO":[255,255,158,255,255,83,255,255,22,21,255,82,255],"FLAG":0,"BASE":18}
+Kuled K36 {"NAME":"KULED-B","GPIO":[9,255,255,255,255,255,21,52,29,56,255,255,255],"FLAG":0,"BASE":18}
+Kuled KS602S {"NAME":"KULED","GPIO":[9,255,255,255,255,255,255,255,21,56,255,255,255],"FLAG":0,"BASE":18}
+KYGNE CD-301 {"NAME":"KYGNE Touch","GPIO":[0,0,0,0,52,53,0,0,21,17,0,0,0],"FLAG":0,"BASE":10}
+Lonsonho SK3-01 {"NAME":"Tuya 1 Channel","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,52],"FLAG":0,"BASE":18}
+Lonsonho SK3-02 {"NAME":"Tuya 2 Channel","GPIO":[0,0,0,0,22,0,0,0,17,21,18,0,52],"FLAG":0,"BASE":18}
+Luminea LHC-101.on {"NAME":"LHC-101.on","GPIO":[157,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18}
+Luminea LHC-102.on {"NAME":"LHC-102.on","GPIO":[157,0,53,0,0,18,0,0,17,21,0,22,52],"FLAG":0,"BASE":18}
+LX-WIFI-00M 4 Gang {"NAME":"LX-WIFI-00M","GPIO":[17,25,255,255,23,22,18,19,21,0,20,24,0],"FLAG":0,"BASE":7}
+LYASI B07PYMG3WD {"NAME":"LYASI Touch Sw","GPIO":[0,0,0,0,56,52,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+Martin Jerry 15A {"NAME":"MJ Switch","GPIO":[255,255,255,255,57,56,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+Martin Jerry 3 Way {"NAME":"MJ 3Way Switch","GPIO":[255,255,255,255,52,53,0,0,21,9,157,255,0],"FLAG":0,"BASE":18}
+Merkury MI-WW107-199W {"NAME":"MI-WW107-199W","GPIO":[52,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18}
+Minitiger 1 Gang {"NAME":"minitiger 1 Gang","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28}
+Minitiger 2 Gang {"NAME":"minitiger 2 Gang","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":28}
+Moes 1 Gang Touch {"NAME":"B07C8FJY3G","GPIO":[54,0,0,17,21,0,0,0,0,0,52,0,55],"FLAG":0,"BASE":18}
+Moes 2 Gang Touch {"NAME":"B07BLZFQZZ ","GPIO":[52,0,53,0,0,18,0,0,17,21,0,22,54],"FLAG":0,"BASE":18}
+Moes 2 Gang Touch {"NAME":"Tuya Moes 2 Ch","GPIO":[25,255,24,0,0,18,0,0,17,21,0,22,23],"FLAG":0,"BASE":18}
+Moes 3 Gang Touch {"NAME":"Tuya Moes 3 Ch","GPIO":[27,255,26,18,22,19,0,0,17,21,25,23,24],"FLAG":0,"BASE":18}
+Moes 3-Way {"NAME":"Moes 3-Way","GPIO":[255,255,255,255,21,57,0,0,30,10,9,255,255],"FLAG":0,"BASE":18}
+Moko {"NAME":"Moko Switch","GPIO":[0,0,0,17,21,134,0,0,0,0,0,0,0],"FLAG":0,"BASE":59}
+Nexete DS-123 {"NAME":"DS-123","GPIO":[157,57,255,17,21,18,0,0,255,22,56,255,255],"FLAG":0,"BASE":18}
+Sainko 1-Way {"NAME":"SAINKO 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28}
+SANA {"NAME":"SW02-03","GPIO":[56,255,255,19,23,18,255,255,17,21,255,22,255],"FLAG":0,"BASE":18}
+SANA SASW-03 {"NAME":"SANA SASW-03","GPIO":[54,0,0,19,23,18,0,0,17,21,0,22,0],"FLAG":0,"BASE":18}
+Sesoo SK3-04 {"NAME":"Tuya 4 Channel","GPIO":[52,255,255,19,23,17,0,0,20,24,22,21,18],"FLAG":0,"BASE":18}
+Sesoo WIFI-US-SK3-04 {"NAME":"WIFI-US-SK3-04","GPIO":[255,255,255,19,23,17,0,0,20,24,22,21,18],"FLAG":0,"BASE":18}
+SmartPlex 3 Gang {"NAME":"Tuya 3 Channel","GPIO":[255,255,255,255,21,18,0,0,19,23,17,22,255],"FLAG":0,"BASE":18}
+Sonoff T1 EU 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28}
+Sonoff T1 EU 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29}
+Sonoff T1 UK 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28}
+Sonoff T1 UK 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29}
+Sonoff T1 UK 3 Gang {"NAME":"Sonoff T1 3CH","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30}
+Sonoff T1 US 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28}
+Sonoff T1 US 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29}
+Sonoff T1 US 3 Gang {"NAME":"Sonoff T1 3CH","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30}
+Sonoff Touch EU {"NAME":"Sonoff Touch","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":10}
+Sonoff Touch US {"NAME":"Sonoff Touch","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":10}
+SS118-01K1 {"NAME":"SS118-01K1","GPIO":[255,255,255,17,21,255,255,255,255,255,56,255,255],"FLAG":0,"BASE":18}
+STITCH by Monoprice 35557 {"NAME":"Tuya WF15S ","GPIO":[255,255,0,0,255,255,0,0,255,108,255,107,0],"FLAG":0,"BASE":54}
+Teepao Smart-Rollladen-Schalter {"NAME":"Teepao","GPIO":[158,58,23,18,22,19,0,0,56,21,57,0,17],"FLAG":0,"BASE":18}
+Tonbux AMZ180648-2 {"NAME":"Tonbux","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":1}
+Touch 2 Gang {"NAME":"tuya_2_gang","GPIO":[52,0,0,0,18,0,0,0,17,21,255,22,29],"FLAG":0,"BASE":18}
+TreatLife SS01S {"NAME":"TL SS01S Swtch","GPIO":[0,0,0,0,52,158,0,0,21,17,0,0,0],"FLAG":0,"BASE":18}
+WS-US-03 {"NAME":"WS-US-03","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30}
+Xenon SM-SW102-2 {"NAME":"SM SW102","GPIO":[255,255,255,18,22,255,255,255,17,21,255,255,255],"FLAG":0,"BASE":18}
+Youngzuth SW02 2-way {"NAME":"SW02 2W","GPIO":[52,255,255,9,21,255,255,255,10,22,255,255,255],"FLAG":0,"BASE":18}
+Zemismart KS-611 3 Gang {"NAME":"Zemismart 3 Ga","GPIO":[0,0,56,0,19,18,0,0,22,21,23,0,17],"FLAG":0,"BASE":18}
+Zemismart KS-811 1 gang {"NAME":"KS-811 Single","GPIO":[17,255,255,255,255,255,255,255,21,56,255,255,255],"FLAG":0,"BASE":18}
+Zemismart KS-811 2 Gang {"NAME":"KS-811 Dual","GPIO":[255,255,52,255,255,18,255,255,22,21,255,255,17],"FLAG":0,"BASE":18}
+Zemismart KS-811 3 Gang {"NAME":"KS-811 Triple","GPIO":[255,255,56,255,19,18,255,255,22,21,23,255,17],"FLAG":0,"BASE":18}
+Zemismart WF-BS01 {"NAME":"WF-BS01","GPIO":[53,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18}
+Zemismart ZM-L02E {"NAME":"ZSmart ZM-L02E","GPIO":[255,255,255,255,255,17,255,255,18,21,22,255,255],"FLAG":0,"BASE":18}
+```
+
+## Valve
+```
+Hoenyzy DN20 3/4 {"NAME":"Unbranded TYWE3S DN20 WIFI Valve","GPIO":[0,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18}
+Jinvoo SM-PW713 {"NAME":"Jinvoo Valve","GPIO":[0,0,0,0,21,52,0,0,17,53,0,0,0],"FLAG":1,"BASE":18}
+TopKitchen Irrigation Timer {"NAME":"HoseController","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":1,"BASE":18}
+```
+
+## Wall Outlet
+```
+Bestten LO-2-W2 {"NAME":"BESTTEN LO-2-W","GPIO":[17,0,0,0,57,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1}
+Charging Essentials WiFi Smart {"NAME":"CESmart-Wall","GPIO":[255,255,255,255,255,17,255,255,21,255,255,255,255],"FLAG":0,"BASE":18}
+Kesen KS-604 {"NAME":"KS-604","GPIO":[255,255,52,255,255,18,255,255,22,21,255,255,17],"FLAG":0,"BASE":18}
+Kesen KS-604S {"NAME":"KS-604S","GPIO":[255,255,31,255,255,18,255,255,22,21,255,255,17],"FLAG":1,"BASE":18}
+MakeGood MG-AUWF01 {"NAME":"MG-AUWF01","GPIO":[56,10,157,59,134,132,255,255,131,22,57,21,9],"FLAG":0,"BASE":18}
+MoesHouse Smart Socket {"NAME":"Smart Socket","GPIO":[255,255,255,255,52,53,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+Smanergy KA10 {"NAME":"KA10","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64}
+Sonoff S55 {"NAME":"Sonoff S55","GPIO":[17,255,0,255,255,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1}
+Topgreener TGWF15RM {"NAME":"TGWF15RM","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55}
+Vigica VGSPK00815 {"NAME":"VIGICA outlet","GPIO":[17,255,255,255,255,22,18,255,21,255,255,255,255],"FLAG":1,"BASE":18}
+WWK-UN-W Glass Panel {"NAME":"tuya wall sock","GPIO":[255,255,255,255,52,53,255,255,21,17,255,255,255],"FLAG":0,"BASE":18}
+```
\ No newline at end of file
diff --git a/arduino/version pre-2.6.0/boards.txt b/arduino/version pre-2.6.0/boards.txt
new file mode 100644
index 000000000..401ff23ea
--- /dev/null
+++ b/arduino/version pre-2.6.0/boards.txt
@@ -0,0 +1,6448 @@
+#
+# Do not create pull-requests for this file only, CI will not accept them.
+# You *must* edit/modify/run boards.txt.py to regenerate boards.txt.
+# All modified files after running with option "--allgen" must be included in the pull-request.
+#
+
+menu.BoardModel=Model
+menu.baud=Upload Speed
+
+menu.UploadTool=Upload Using
+
+menu.xtal=CPU Frequency
+menu.CrystalFreq=Crystal Frequency
+menu.eesz=Flash Size
+menu.FlashMode=Flash Mode
+menu.FlashFreq=Flash Frequency
+menu.ResetMethod=Reset Method
+menu.ESPModule=Module
+menu.dbg=Debug port
+menu.lvl=Debug Level
+menu.ip=lwIP Variant
+menu.vt=VTables
+menu.exception=Exceptions
+menu.led=Builtin Led
+menu.wipe=Erase Flash
+menu.sdk=Espressif FW
+menu.ssl=SSL Support
+
+##############################################################
+generic.name=Generic ESP8266 Module
+generic.build.board=ESP8266_GENERIC
+generic.upload.tool=esptool
+generic.upload.maximum_data_size=81920
+generic.upload.wait_for_upload_port=true
+generic.upload.erase_cmd=version
+generic.serial.disableDTR=true
+generic.serial.disableRTS=true
+generic.build.mcu=esp8266
+generic.build.core=esp8266
+generic.build.variant=generic
+generic.build.spiffs_pagesize=256
+generic.build.debug_port=
+generic.build.debug_level=
+
+generic.menu.UploadTool.esptool=Serial
+generic.menu.UploadTool.esptool.upload.tool=esptool
+generic.menu.UploadTool.esptool.upload.verbose=-vv
+generic.menu.UploadTool.espupload=OTA_upload
+generic.menu.UploadTool.espupload.upload.tool=espupload
+
+generic.menu.xtal.80=80 MHz
+generic.menu.xtal.80.build.f_cpu=80000000L
+generic.menu.xtal.160=160 MHz
+generic.menu.xtal.160.build.f_cpu=160000000L
+generic.menu.vt.flash=Flash
+generic.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+generic.menu.vt.heap=Heap
+generic.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+generic.menu.vt.iram=IRAM
+generic.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+generic.menu.exception.legacy=Legacy (new can return nullptr)
+generic.menu.exception.legacy.build.exception_flags=-fno-exceptions
+generic.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+generic.menu.exception.disabled=Disabled (new can abort)
+generic.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+generic.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+generic.menu.exception.enabled=Enabled
+generic.menu.exception.enabled.build.exception_flags=-fexceptions
+generic.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+generic.menu.ssl.all=All SSL ciphers (most compatible)
+generic.menu.ssl.all.build.sslflags=
+generic.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+generic.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+generic.menu.ResetMethod.ck=ck
+generic.menu.ResetMethod.ck.upload.resetmethod=ck
+generic.menu.ResetMethod.nodemcu=nodemcu
+generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu
+generic.menu.ResetMethod.none=none
+generic.menu.ResetMethod.none.upload.resetmethod=none
+generic.menu.ResetMethod.dtrset=dtrset
+generic.menu.ResetMethod.dtrset.upload.resetmethod=dtrset
+generic.menu.CrystalFreq.26=26 MHz
+generic.menu.CrystalFreq.40=40 MHz
+generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266
+generic.menu.FlashFreq.40=40MHz
+generic.menu.FlashFreq.40.build.flash_freq=40
+generic.menu.FlashFreq.80=80MHz
+generic.menu.FlashFreq.80.build.flash_freq=80
+generic.menu.FlashFreq.20=20MHz
+generic.menu.FlashFreq.20.build.flash_freq=20
+generic.menu.FlashFreq.26=26MHz
+generic.menu.FlashFreq.26.build.flash_freq=26
+generic.menu.FlashMode.dout=DOUT (compatible)
+generic.menu.FlashMode.dout.build.flash_mode=dout
+generic.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT
+generic.menu.FlashMode.dio=DIO
+generic.menu.FlashMode.dio.build.flash_mode=dio
+generic.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO
+generic.menu.FlashMode.qout=QOUT
+generic.menu.FlashMode.qout.build.flash_mode=qout
+generic.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT
+generic.menu.FlashMode.qio=QIO (fast)
+generic.menu.FlashMode.qio.build.flash_mode=qio
+generic.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO
+generic.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB)
+generic.menu.eesz.1M64.build.flash_size=1M
+generic.menu.eesz.1M64.build.flash_size_bytes=0x100000
+generic.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld
+generic.menu.eesz.1M64.build.spiffs_pagesize=256
+generic.menu.eesz.1M64.upload.maximum_size=958448
+generic.menu.eesz.1M64.build.rfcal_addr=0xFC000
+generic.menu.eesz.1M64.build.spiffs_start=0xEB000
+generic.menu.eesz.1M64.build.spiffs_end=0xFB000
+generic.menu.eesz.1M64.build.spiffs_blocksize=4096
+generic.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB)
+generic.menu.eesz.1M128.build.flash_size=1M
+generic.menu.eesz.1M128.build.flash_size_bytes=0x100000
+generic.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld
+generic.menu.eesz.1M128.build.spiffs_pagesize=256
+generic.menu.eesz.1M128.upload.maximum_size=892912
+generic.menu.eesz.1M128.build.rfcal_addr=0xFC000
+generic.menu.eesz.1M128.build.spiffs_start=0xDB000
+generic.menu.eesz.1M128.build.spiffs_end=0xFB000
+generic.menu.eesz.1M128.build.spiffs_blocksize=4096
+generic.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB)
+generic.menu.eesz.1M144.build.flash_size=1M
+generic.menu.eesz.1M144.build.flash_size_bytes=0x100000
+generic.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld
+generic.menu.eesz.1M144.build.spiffs_pagesize=256
+generic.menu.eesz.1M144.upload.maximum_size=876528
+generic.menu.eesz.1M144.build.rfcal_addr=0xFC000
+generic.menu.eesz.1M144.build.spiffs_start=0xD7000
+generic.menu.eesz.1M144.build.spiffs_end=0xFB000
+generic.menu.eesz.1M144.build.spiffs_blocksize=4096
+generic.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB)
+generic.menu.eesz.1M160.build.flash_size=1M
+generic.menu.eesz.1M160.build.flash_size_bytes=0x100000
+generic.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld
+generic.menu.eesz.1M160.build.spiffs_pagesize=256
+generic.menu.eesz.1M160.upload.maximum_size=860144
+generic.menu.eesz.1M160.build.rfcal_addr=0xFC000
+generic.menu.eesz.1M160.build.spiffs_start=0xD3000
+generic.menu.eesz.1M160.build.spiffs_end=0xFB000
+generic.menu.eesz.1M160.build.spiffs_blocksize=4096
+generic.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB)
+generic.menu.eesz.1M192.build.flash_size=1M
+generic.menu.eesz.1M192.build.flash_size_bytes=0x100000
+generic.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld
+generic.menu.eesz.1M192.build.spiffs_pagesize=256
+generic.menu.eesz.1M192.upload.maximum_size=827376
+generic.menu.eesz.1M192.build.rfcal_addr=0xFC000
+generic.menu.eesz.1M192.build.spiffs_start=0xCB000
+generic.menu.eesz.1M192.build.spiffs_end=0xFB000
+generic.menu.eesz.1M192.build.spiffs_blocksize=4096
+generic.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB)
+generic.menu.eesz.1M256.build.flash_size=1M
+generic.menu.eesz.1M256.build.flash_size_bytes=0x100000
+generic.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld
+generic.menu.eesz.1M256.build.spiffs_pagesize=256
+generic.menu.eesz.1M256.upload.maximum_size=761840
+generic.menu.eesz.1M256.build.rfcal_addr=0xFC000
+generic.menu.eesz.1M256.build.spiffs_start=0xBB000
+generic.menu.eesz.1M256.build.spiffs_end=0xFB000
+generic.menu.eesz.1M256.build.spiffs_blocksize=4096
+generic.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB)
+generic.menu.eesz.1M512.build.flash_size=1M
+generic.menu.eesz.1M512.build.flash_size_bytes=0x100000
+generic.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld
+generic.menu.eesz.1M512.build.spiffs_pagesize=256
+generic.menu.eesz.1M512.upload.maximum_size=499696
+generic.menu.eesz.1M512.build.rfcal_addr=0xFC000
+generic.menu.eesz.1M512.build.spiffs_start=0x7B000
+generic.menu.eesz.1M512.build.spiffs_end=0xFB000
+generic.menu.eesz.1M512.build.spiffs_blocksize=8192
+generic.menu.eesz.1M=1MB (FS:none OTA:~502KB)
+generic.menu.eesz.1M.build.flash_size=1M
+generic.menu.eesz.1M.build.flash_size_bytes=0x100000
+generic.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld
+generic.menu.eesz.1M.build.spiffs_pagesize=256
+generic.menu.eesz.1M.upload.maximum_size=1023984
+generic.menu.eesz.1M.build.rfcal_addr=0xFC000
+generic.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB)
+generic.menu.eesz.2M64.build.flash_size=2M
+generic.menu.eesz.2M64.build.flash_size_bytes=0x200000
+generic.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld
+generic.menu.eesz.2M64.build.spiffs_pagesize=256
+generic.menu.eesz.2M64.upload.maximum_size=1044464
+generic.menu.eesz.2M64.build.rfcal_addr=0x1FC000
+generic.menu.eesz.2M64.build.spiffs_start=0x1F0000
+generic.menu.eesz.2M64.build.spiffs_end=0x1FB000
+generic.menu.eesz.2M64.build.spiffs_blocksize=4096
+generic.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB)
+generic.menu.eesz.2M128.build.flash_size=2M
+generic.menu.eesz.2M128.build.flash_size_bytes=0x200000
+generic.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld
+generic.menu.eesz.2M128.build.spiffs_pagesize=256
+generic.menu.eesz.2M128.upload.maximum_size=1044464
+generic.menu.eesz.2M128.build.rfcal_addr=0x1FC000
+generic.menu.eesz.2M128.build.spiffs_start=0x1E0000
+generic.menu.eesz.2M128.build.spiffs_end=0x1FB000
+generic.menu.eesz.2M128.build.spiffs_blocksize=4096
+generic.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB)
+generic.menu.eesz.2M256.build.flash_size=2M
+generic.menu.eesz.2M256.build.flash_size_bytes=0x200000
+generic.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld
+generic.menu.eesz.2M256.build.spiffs_pagesize=256
+generic.menu.eesz.2M256.upload.maximum_size=1044464
+generic.menu.eesz.2M256.build.rfcal_addr=0x1FC000
+generic.menu.eesz.2M256.build.spiffs_start=0x1C0000
+generic.menu.eesz.2M256.build.spiffs_end=0x1FB000
+generic.menu.eesz.2M256.build.spiffs_blocksize=4096
+generic.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB)
+generic.menu.eesz.2M512.build.flash_size=2M
+generic.menu.eesz.2M512.build.flash_size_bytes=0x200000
+generic.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld
+generic.menu.eesz.2M512.build.spiffs_pagesize=256
+generic.menu.eesz.2M512.upload.maximum_size=1044464
+generic.menu.eesz.2M512.build.rfcal_addr=0x1FC000
+generic.menu.eesz.2M512.build.spiffs_start=0x180000
+generic.menu.eesz.2M512.build.spiffs_end=0x1FA000
+generic.menu.eesz.2M512.build.spiffs_blocksize=8192
+generic.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB)
+generic.menu.eesz.2M1M.build.flash_size=2M
+generic.menu.eesz.2M1M.build.flash_size_bytes=0x200000
+generic.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld
+generic.menu.eesz.2M1M.build.spiffs_pagesize=256
+generic.menu.eesz.2M1M.upload.maximum_size=1044464
+generic.menu.eesz.2M1M.build.rfcal_addr=0x1FC000
+generic.menu.eesz.2M1M.build.spiffs_start=0x100000
+generic.menu.eesz.2M1M.build.spiffs_end=0x1FA000
+generic.menu.eesz.2M1M.build.spiffs_blocksize=8192
+generic.menu.eesz.2M=2MB (FS:none OTA:~1019KB)
+generic.menu.eesz.2M.build.flash_size=2M
+generic.menu.eesz.2M.build.flash_size_bytes=0x200000
+generic.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld
+generic.menu.eesz.2M.build.spiffs_pagesize=256
+generic.menu.eesz.2M.upload.maximum_size=1044464
+generic.menu.eesz.2M.build.rfcal_addr=0x1FC000
+generic.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+generic.menu.eesz.4M2M.build.flash_size=4M
+generic.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+generic.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+generic.menu.eesz.4M2M.build.spiffs_pagesize=256
+generic.menu.eesz.4M2M.upload.maximum_size=1044464
+generic.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+generic.menu.eesz.4M2M.build.spiffs_start=0x200000
+generic.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+generic.menu.eesz.4M2M.build.spiffs_blocksize=8192
+generic.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+generic.menu.eesz.4M3M.build.flash_size=4M
+generic.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+generic.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+generic.menu.eesz.4M3M.build.spiffs_pagesize=256
+generic.menu.eesz.4M3M.upload.maximum_size=1044464
+generic.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+generic.menu.eesz.4M3M.build.spiffs_start=0x100000
+generic.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+generic.menu.eesz.4M3M.build.spiffs_blocksize=8192
+generic.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+generic.menu.eesz.4M1M.build.flash_size=4M
+generic.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+generic.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+generic.menu.eesz.4M1M.build.spiffs_pagesize=256
+generic.menu.eesz.4M1M.upload.maximum_size=1044464
+generic.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+generic.menu.eesz.4M1M.build.spiffs_start=0x300000
+generic.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+generic.menu.eesz.4M1M.build.spiffs_blocksize=8192
+generic.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+generic.menu.eesz.4M.build.flash_size=4M
+generic.menu.eesz.4M.build.flash_size_bytes=0x400000
+generic.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+generic.menu.eesz.4M.build.spiffs_pagesize=256
+generic.menu.eesz.4M.upload.maximum_size=1044464
+generic.menu.eesz.4M.build.rfcal_addr=0x3FC000
+generic.menu.eesz.8M6M=8MB (FS:6MB OTA:~1019KB)
+generic.menu.eesz.8M6M.build.flash_size=8M
+generic.menu.eesz.8M6M.build.flash_size_bytes=0x800000
+generic.menu.eesz.8M6M.build.flash_ld=eagle.flash.8m6m.ld
+generic.menu.eesz.8M6M.build.spiffs_pagesize=256
+generic.menu.eesz.8M6M.upload.maximum_size=1044464
+generic.menu.eesz.8M6M.build.rfcal_addr=0x7FC000
+generic.menu.eesz.8M6M.build.spiffs_start=0x200000
+generic.menu.eesz.8M6M.build.spiffs_end=0x7FA000
+generic.menu.eesz.8M6M.build.spiffs_blocksize=8192
+generic.menu.eesz.8M7M=8MB (FS:7MB OTA:~512KB)
+generic.menu.eesz.8M7M.build.flash_size=8M
+generic.menu.eesz.8M7M.build.flash_size_bytes=0x800000
+generic.menu.eesz.8M7M.build.flash_ld=eagle.flash.8m7m.ld
+generic.menu.eesz.8M7M.build.spiffs_pagesize=256
+generic.menu.eesz.8M7M.upload.maximum_size=1044464
+generic.menu.eesz.8M7M.build.rfcal_addr=0x7FC000
+generic.menu.eesz.8M7M.build.spiffs_start=0x100000
+generic.menu.eesz.8M7M.build.spiffs_end=0x7FA000
+generic.menu.eesz.8M7M.build.spiffs_blocksize=8192
+generic.menu.eesz.16M14M=16MB (FS:14MB OTA:~1019KB)
+generic.menu.eesz.16M14M.build.flash_size=16M
+generic.menu.eesz.16M14M.build.flash_size_bytes=0x1000000
+generic.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld
+generic.menu.eesz.16M14M.build.spiffs_pagesize=256
+generic.menu.eesz.16M14M.upload.maximum_size=1044464
+generic.menu.eesz.16M14M.build.rfcal_addr=0xFFC000
+generic.menu.eesz.16M14M.build.spiffs_start=0x200000
+generic.menu.eesz.16M14M.build.spiffs_end=0xFFA000
+generic.menu.eesz.16M14M.build.spiffs_blocksize=8192
+generic.menu.eesz.16M15M=16MB (FS:15MB OTA:~512KB)
+generic.menu.eesz.16M15M.build.flash_size=16M
+generic.menu.eesz.16M15M.build.flash_size_bytes=0x1000000
+generic.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld
+generic.menu.eesz.16M15M.build.spiffs_pagesize=256
+generic.menu.eesz.16M15M.upload.maximum_size=1044464
+generic.menu.eesz.16M15M.build.rfcal_addr=0xFFC000
+generic.menu.eesz.16M15M.build.spiffs_start=0x100000
+generic.menu.eesz.16M15M.build.spiffs_end=0xFFA000
+generic.menu.eesz.16M15M.build.spiffs_blocksize=8192
+generic.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB)
+generic.menu.eesz.512K32.build.flash_size=512K
+generic.menu.eesz.512K32.build.flash_size_bytes=0x80000
+generic.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld
+generic.menu.eesz.512K32.build.spiffs_pagesize=256
+generic.menu.eesz.512K32.upload.maximum_size=466928
+generic.menu.eesz.512K32.build.rfcal_addr=0x7C000
+generic.menu.eesz.512K32.build.spiffs_start=0x73000
+generic.menu.eesz.512K32.build.spiffs_end=0x7B000
+generic.menu.eesz.512K32.build.spiffs_blocksize=4096
+generic.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB)
+generic.menu.eesz.512K64.build.flash_size=512K
+generic.menu.eesz.512K64.build.flash_size_bytes=0x80000
+generic.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld
+generic.menu.eesz.512K64.build.spiffs_pagesize=256
+generic.menu.eesz.512K64.upload.maximum_size=434160
+generic.menu.eesz.512K64.build.rfcal_addr=0x7C000
+generic.menu.eesz.512K64.build.spiffs_start=0x6B000
+generic.menu.eesz.512K64.build.spiffs_end=0x7B000
+generic.menu.eesz.512K64.build.spiffs_blocksize=4096
+generic.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB)
+generic.menu.eesz.512K128.build.flash_size=512K
+generic.menu.eesz.512K128.build.flash_size_bytes=0x80000
+generic.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld
+generic.menu.eesz.512K128.build.spiffs_pagesize=256
+generic.menu.eesz.512K128.upload.maximum_size=368624
+generic.menu.eesz.512K128.build.rfcal_addr=0x7C000
+generic.menu.eesz.512K128.build.spiffs_start=0x5B000
+generic.menu.eesz.512K128.build.spiffs_end=0x7B000
+generic.menu.eesz.512K128.build.spiffs_blocksize=4096
+generic.menu.eesz.512K=512KB (FS:none OTA:~246KB)
+generic.menu.eesz.512K.build.flash_size=512K
+generic.menu.eesz.512K.build.flash_size_bytes=0x80000
+generic.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld
+generic.menu.eesz.512K.build.spiffs_pagesize=256
+generic.menu.eesz.512K.upload.maximum_size=499696
+generic.menu.eesz.512K.build.rfcal_addr=0x7C000
+generic.menu.led.2=2
+generic.menu.led.2.build.led=-DLED_BUILTIN=2
+generic.menu.led.0=0
+generic.menu.led.0.build.led=-DLED_BUILTIN=0
+generic.menu.led.1=1
+generic.menu.led.1.build.led=-DLED_BUILTIN=1
+generic.menu.led.3=3
+generic.menu.led.3.build.led=-DLED_BUILTIN=3
+generic.menu.led.4=4
+generic.menu.led.4.build.led=-DLED_BUILTIN=4
+generic.menu.led.5=5
+generic.menu.led.5.build.led=-DLED_BUILTIN=5
+generic.menu.led.6=6
+generic.menu.led.6.build.led=-DLED_BUILTIN=6
+generic.menu.led.7=7
+generic.menu.led.7.build.led=-DLED_BUILTIN=7
+generic.menu.led.8=8
+generic.menu.led.8.build.led=-DLED_BUILTIN=8
+generic.menu.led.9=9
+generic.menu.led.9.build.led=-DLED_BUILTIN=9
+generic.menu.led.10=10
+generic.menu.led.10.build.led=-DLED_BUILTIN=10
+generic.menu.led.11=11
+generic.menu.led.11.build.led=-DLED_BUILTIN=11
+generic.menu.led.12=12
+generic.menu.led.12.build.led=-DLED_BUILTIN=12
+generic.menu.led.13=13
+generic.menu.led.13.build.led=-DLED_BUILTIN=13
+generic.menu.led.14=14
+generic.menu.led.14.build.led=-DLED_BUILTIN=14
+generic.menu.led.15=15
+generic.menu.led.15.build.led=-DLED_BUILTIN=15
+generic.menu.led.16=16
+generic.menu.led.16.build.led=-DLED_BUILTIN=16
+generic.menu.sdk.nonosdk222_100=nonos-sdk 2.2.1+100 (testing)
+generic.menu.sdk.nonosdk222_100.build.sdk=NONOSDK22y
+generic.menu.sdk.nonosdk221=nonos-sdk 2.2.1 (legacy)
+generic.menu.sdk.nonosdk221.build.sdk=NONOSDK221
+generic.menu.sdk.nonosdk3v0=nonos-sdk pre-3 (known issues)
+generic.menu.sdk.nonosdk3v0.build.sdk=NONOSDK3V0
+generic.menu.ip.lm2f=v2 Lower Memory
+generic.menu.ip.lm2f.build.lwip_include=lwip2/include
+generic.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+generic.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+generic.menu.ip.hb2f=v2 Higher Bandwidth
+generic.menu.ip.hb2f.build.lwip_include=lwip2/include
+generic.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+generic.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+generic.menu.ip.lm2n=v2 Lower Memory (no features)
+generic.menu.ip.lm2n.build.lwip_include=lwip2/include
+generic.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+generic.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+generic.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+generic.menu.ip.hb2n.build.lwip_include=lwip2/include
+generic.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+generic.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+generic.menu.ip.lm6f=v2 IPv6 Lower Memory
+generic.menu.ip.lm6f.build.lwip_include=lwip2/include
+generic.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+generic.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+generic.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+generic.menu.ip.hb6f.build.lwip_include=lwip2/include
+generic.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+generic.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+generic.menu.ip.hb1=v1.4 Higher Bandwidth
+generic.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+generic.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+generic.menu.ip.src=v1.4 Compile from source
+generic.menu.ip.src.build.lwip_lib=-llwip_src
+generic.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+generic.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+generic.menu.dbg.Disabled=Disabled
+generic.menu.dbg.Disabled.build.debug_port=
+generic.menu.dbg.Serial=Serial
+generic.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+generic.menu.dbg.Serial1=Serial1
+generic.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+generic.menu.lvl.None____=None
+generic.menu.lvl.None____.build.debug_level=
+generic.menu.lvl.SSL=SSL
+generic.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+generic.menu.lvl.TLS_MEM=TLS_MEM
+generic.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+generic.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+generic.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+generic.menu.lvl.HTTP_SERVER=HTTP_SERVER
+generic.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+generic.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+generic.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+generic.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+generic.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+generic.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+generic.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+generic.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+generic.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+generic.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+generic.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+generic.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+generic.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+generic.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+generic.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+generic.menu.lvl.CORE=CORE
+generic.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+generic.menu.lvl.WIFI=WIFI
+generic.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+generic.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+generic.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+generic.menu.lvl.UPDATER=UPDATER
+generic.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+generic.menu.lvl.OTA=OTA
+generic.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+generic.menu.lvl.OOM=OOM
+generic.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+generic.menu.lvl.MDNS=MDNS
+generic.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+generic.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+generic.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+generic.menu.wipe.none=Only Sketch
+generic.menu.wipe.none.upload.erase_cmd=version
+generic.menu.wipe.sdk=Sketch + WiFi Settings
+generic.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+generic.menu.wipe.all=All Flash Contents
+generic.menu.wipe.all.upload.erase_cmd=erase_flash
+generic.menu.baud.115200=115200
+generic.menu.baud.115200.upload.speed=115200
+generic.menu.baud.57600=57600
+generic.menu.baud.57600.upload.speed=57600
+generic.menu.baud.230400.linux=230400
+generic.menu.baud.230400.macosx=230400
+generic.menu.baud.230400.upload.speed=230400
+generic.menu.baud.256000.windows=256000
+generic.menu.baud.256000.upload.speed=256000
+generic.menu.baud.460800.linux=460800
+generic.menu.baud.460800.macosx=460800
+generic.menu.baud.460800.upload.speed=460800
+generic.menu.baud.512000.windows=512000
+generic.menu.baud.512000.upload.speed=512000
+generic.menu.baud.921600=921600
+generic.menu.baud.921600.upload.speed=921600
+generic.menu.baud.3000000=3000000
+generic.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+esp8285.name=Generic ESP8285 Module
+esp8285.build.board=ESP8266_ESP01
+esp8285.build.variant=esp8285
+esp8285.upload.tool=esptool
+esp8285.upload.maximum_data_size=81920
+esp8285.upload.wait_for_upload_port=true
+esp8285.upload.erase_cmd=version
+esp8285.serial.disableDTR=true
+esp8285.serial.disableRTS=true
+esp8285.build.mcu=esp8266
+esp8285.build.core=esp8266
+esp8285.build.spiffs_pagesize=256
+esp8285.build.debug_port=
+esp8285.build.debug_level=
+esp8285.menu.xtal.80=80 MHz
+esp8285.menu.xtal.80.build.f_cpu=80000000L
+esp8285.menu.xtal.160=160 MHz
+esp8285.menu.xtal.160.build.f_cpu=160000000L
+esp8285.menu.vt.flash=Flash
+esp8285.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+esp8285.menu.vt.heap=Heap
+esp8285.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+esp8285.menu.vt.iram=IRAM
+esp8285.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+esp8285.menu.exception.legacy=Legacy (new can return nullptr)
+esp8285.menu.exception.legacy.build.exception_flags=-fno-exceptions
+esp8285.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+esp8285.menu.exception.disabled=Disabled (new can abort)
+esp8285.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+esp8285.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+esp8285.menu.exception.enabled=Enabled
+esp8285.menu.exception.enabled.build.exception_flags=-fexceptions
+esp8285.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+esp8285.menu.ssl.all=All SSL ciphers (most compatible)
+esp8285.menu.ssl.all.build.sslflags=
+esp8285.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+esp8285.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+esp8285.menu.ResetMethod.ck=ck
+esp8285.menu.ResetMethod.ck.upload.resetmethod=ck
+esp8285.menu.ResetMethod.nodemcu=nodemcu
+esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu
+esp8285.menu.ResetMethod.none=none
+esp8285.menu.ResetMethod.none.upload.resetmethod=none
+esp8285.menu.ResetMethod.dtrset=dtrset
+esp8285.menu.ResetMethod.dtrset.upload.resetmethod=dtrset
+esp8285.menu.CrystalFreq.26=26 MHz
+esp8285.menu.CrystalFreq.40=40 MHz
+esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266
+esp8285.build.flash_mode=dout
+esp8285.build.flash_flags=-DFLASHMODE_DOUT
+esp8285.build.flash_freq=40
+esp8285.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB)
+esp8285.menu.eesz.1M64.build.flash_size=1M
+esp8285.menu.eesz.1M64.build.flash_size_bytes=0x100000
+esp8285.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld
+esp8285.menu.eesz.1M64.build.spiffs_pagesize=256
+esp8285.menu.eesz.1M64.upload.maximum_size=958448
+esp8285.menu.eesz.1M64.build.rfcal_addr=0xFC000
+esp8285.menu.eesz.1M64.build.spiffs_start=0xEB000
+esp8285.menu.eesz.1M64.build.spiffs_end=0xFB000
+esp8285.menu.eesz.1M64.build.spiffs_blocksize=4096
+esp8285.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB)
+esp8285.menu.eesz.1M128.build.flash_size=1M
+esp8285.menu.eesz.1M128.build.flash_size_bytes=0x100000
+esp8285.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld
+esp8285.menu.eesz.1M128.build.spiffs_pagesize=256
+esp8285.menu.eesz.1M128.upload.maximum_size=892912
+esp8285.menu.eesz.1M128.build.rfcal_addr=0xFC000
+esp8285.menu.eesz.1M128.build.spiffs_start=0xDB000
+esp8285.menu.eesz.1M128.build.spiffs_end=0xFB000
+esp8285.menu.eesz.1M128.build.spiffs_blocksize=4096
+esp8285.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB)
+esp8285.menu.eesz.1M144.build.flash_size=1M
+esp8285.menu.eesz.1M144.build.flash_size_bytes=0x100000
+esp8285.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld
+esp8285.menu.eesz.1M144.build.spiffs_pagesize=256
+esp8285.menu.eesz.1M144.upload.maximum_size=876528
+esp8285.menu.eesz.1M144.build.rfcal_addr=0xFC000
+esp8285.menu.eesz.1M144.build.spiffs_start=0xD7000
+esp8285.menu.eesz.1M144.build.spiffs_end=0xFB000
+esp8285.menu.eesz.1M144.build.spiffs_blocksize=4096
+esp8285.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB)
+esp8285.menu.eesz.1M160.build.flash_size=1M
+esp8285.menu.eesz.1M160.build.flash_size_bytes=0x100000
+esp8285.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld
+esp8285.menu.eesz.1M160.build.spiffs_pagesize=256
+esp8285.menu.eesz.1M160.upload.maximum_size=860144
+esp8285.menu.eesz.1M160.build.rfcal_addr=0xFC000
+esp8285.menu.eesz.1M160.build.spiffs_start=0xD3000
+esp8285.menu.eesz.1M160.build.spiffs_end=0xFB000
+esp8285.menu.eesz.1M160.build.spiffs_blocksize=4096
+esp8285.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB)
+esp8285.menu.eesz.1M192.build.flash_size=1M
+esp8285.menu.eesz.1M192.build.flash_size_bytes=0x100000
+esp8285.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld
+esp8285.menu.eesz.1M192.build.spiffs_pagesize=256
+esp8285.menu.eesz.1M192.upload.maximum_size=827376
+esp8285.menu.eesz.1M192.build.rfcal_addr=0xFC000
+esp8285.menu.eesz.1M192.build.spiffs_start=0xCB000
+esp8285.menu.eesz.1M192.build.spiffs_end=0xFB000
+esp8285.menu.eesz.1M192.build.spiffs_blocksize=4096
+esp8285.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB)
+esp8285.menu.eesz.1M256.build.flash_size=1M
+esp8285.menu.eesz.1M256.build.flash_size_bytes=0x100000
+esp8285.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld
+esp8285.menu.eesz.1M256.build.spiffs_pagesize=256
+esp8285.menu.eesz.1M256.upload.maximum_size=761840
+esp8285.menu.eesz.1M256.build.rfcal_addr=0xFC000
+esp8285.menu.eesz.1M256.build.spiffs_start=0xBB000
+esp8285.menu.eesz.1M256.build.spiffs_end=0xFB000
+esp8285.menu.eesz.1M256.build.spiffs_blocksize=4096
+esp8285.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB)
+esp8285.menu.eesz.1M512.build.flash_size=1M
+esp8285.menu.eesz.1M512.build.flash_size_bytes=0x100000
+esp8285.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld
+esp8285.menu.eesz.1M512.build.spiffs_pagesize=256
+esp8285.menu.eesz.1M512.upload.maximum_size=499696
+esp8285.menu.eesz.1M512.build.rfcal_addr=0xFC000
+esp8285.menu.eesz.1M512.build.spiffs_start=0x7B000
+esp8285.menu.eesz.1M512.build.spiffs_end=0xFB000
+esp8285.menu.eesz.1M512.build.spiffs_blocksize=8192
+esp8285.menu.eesz.1M=1MB (FS:none OTA:~502KB)
+esp8285.menu.eesz.1M.build.flash_size=1M
+esp8285.menu.eesz.1M.build.flash_size_bytes=0x100000
+esp8285.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld
+esp8285.menu.eesz.1M.build.spiffs_pagesize=256
+esp8285.menu.eesz.1M.upload.maximum_size=1023984
+esp8285.menu.eesz.1M.build.rfcal_addr=0xFC000
+esp8285.menu.led.2=2
+esp8285.menu.led.2.build.led=-DLED_BUILTIN=2
+esp8285.menu.led.0=0
+esp8285.menu.led.0.build.led=-DLED_BUILTIN=0
+esp8285.menu.led.1=1
+esp8285.menu.led.1.build.led=-DLED_BUILTIN=1
+esp8285.menu.led.3=3
+esp8285.menu.led.3.build.led=-DLED_BUILTIN=3
+esp8285.menu.led.4=4
+esp8285.menu.led.4.build.led=-DLED_BUILTIN=4
+esp8285.menu.led.5=5
+esp8285.menu.led.5.build.led=-DLED_BUILTIN=5
+esp8285.menu.led.6=6
+esp8285.menu.led.6.build.led=-DLED_BUILTIN=6
+esp8285.menu.led.7=7
+esp8285.menu.led.7.build.led=-DLED_BUILTIN=7
+esp8285.menu.led.8=8
+esp8285.menu.led.8.build.led=-DLED_BUILTIN=8
+esp8285.menu.led.9=9
+esp8285.menu.led.9.build.led=-DLED_BUILTIN=9
+esp8285.menu.led.10=10
+esp8285.menu.led.10.build.led=-DLED_BUILTIN=10
+esp8285.menu.led.11=11
+esp8285.menu.led.11.build.led=-DLED_BUILTIN=11
+esp8285.menu.led.12=12
+esp8285.menu.led.12.build.led=-DLED_BUILTIN=12
+esp8285.menu.led.13=13
+esp8285.menu.led.13.build.led=-DLED_BUILTIN=13
+esp8285.menu.led.14=14
+esp8285.menu.led.14.build.led=-DLED_BUILTIN=14
+esp8285.menu.led.15=15
+esp8285.menu.led.15.build.led=-DLED_BUILTIN=15
+esp8285.menu.led.16=16
+esp8285.menu.led.16.build.led=-DLED_BUILTIN=16
+esp8285.menu.ip.lm2f=v2 Lower Memory
+esp8285.menu.ip.lm2f.build.lwip_include=lwip2/include
+esp8285.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+esp8285.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+esp8285.menu.ip.hb2f=v2 Higher Bandwidth
+esp8285.menu.ip.hb2f.build.lwip_include=lwip2/include
+esp8285.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+esp8285.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+esp8285.menu.ip.lm2n=v2 Lower Memory (no features)
+esp8285.menu.ip.lm2n.build.lwip_include=lwip2/include
+esp8285.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+esp8285.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+esp8285.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+esp8285.menu.ip.hb2n.build.lwip_include=lwip2/include
+esp8285.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+esp8285.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+esp8285.menu.ip.lm6f=v2 IPv6 Lower Memory
+esp8285.menu.ip.lm6f.build.lwip_include=lwip2/include
+esp8285.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+esp8285.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+esp8285.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+esp8285.menu.ip.hb6f.build.lwip_include=lwip2/include
+esp8285.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+esp8285.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+esp8285.menu.ip.hb1=v1.4 Higher Bandwidth
+esp8285.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+esp8285.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+esp8285.menu.ip.src=v1.4 Compile from source
+esp8285.menu.ip.src.build.lwip_lib=-llwip_src
+esp8285.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+esp8285.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+esp8285.menu.dbg.Disabled=Disabled
+esp8285.menu.dbg.Disabled.build.debug_port=
+esp8285.menu.dbg.Serial=Serial
+esp8285.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+esp8285.menu.dbg.Serial1=Serial1
+esp8285.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+esp8285.menu.lvl.None____=None
+esp8285.menu.lvl.None____.build.debug_level=
+esp8285.menu.lvl.SSL=SSL
+esp8285.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+esp8285.menu.lvl.TLS_MEM=TLS_MEM
+esp8285.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+esp8285.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+esp8285.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+esp8285.menu.lvl.HTTP_SERVER=HTTP_SERVER
+esp8285.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+esp8285.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+esp8285.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+esp8285.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+esp8285.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+esp8285.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+esp8285.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+esp8285.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+esp8285.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+esp8285.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+esp8285.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+esp8285.menu.lvl.CORE=CORE
+esp8285.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+esp8285.menu.lvl.WIFI=WIFI
+esp8285.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+esp8285.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+esp8285.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+esp8285.menu.lvl.UPDATER=UPDATER
+esp8285.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+esp8285.menu.lvl.OTA=OTA
+esp8285.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+esp8285.menu.lvl.OOM=OOM
+esp8285.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+esp8285.menu.lvl.MDNS=MDNS
+esp8285.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+esp8285.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+esp8285.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+esp8285.menu.wipe.none=Only Sketch
+esp8285.menu.wipe.none.upload.erase_cmd=version
+esp8285.menu.wipe.sdk=Sketch + WiFi Settings
+esp8285.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+esp8285.menu.wipe.all=All Flash Contents
+esp8285.menu.wipe.all.upload.erase_cmd=erase_flash
+esp8285.menu.baud.115200=115200
+esp8285.menu.baud.115200.upload.speed=115200
+esp8285.menu.baud.57600=57600
+esp8285.menu.baud.57600.upload.speed=57600
+esp8285.menu.baud.230400.linux=230400
+esp8285.menu.baud.230400.macosx=230400
+esp8285.menu.baud.230400.upload.speed=230400
+esp8285.menu.baud.256000.windows=256000
+esp8285.menu.baud.256000.upload.speed=256000
+esp8285.menu.baud.460800.linux=460800
+esp8285.menu.baud.460800.macosx=460800
+esp8285.menu.baud.460800.upload.speed=460800
+esp8285.menu.baud.512000.windows=512000
+esp8285.menu.baud.512000.upload.speed=512000
+esp8285.menu.baud.921600=921600
+esp8285.menu.baud.921600.upload.speed=921600
+esp8285.menu.baud.3000000=3000000
+esp8285.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+espduino.name=ESPDuino (ESP-13 Module)
+espduino.build.board=ESP8266_ESP13
+espduino.build.variant=ESPDuino
+espduino.menu.ResetMethod.v1=ESPduino-V1
+espduino.menu.ResetMethod.v1.upload.resetmethod=ck
+espduino.menu.ResetMethod.v2=ESPduino-V2
+espduino.menu.ResetMethod.v2.upload.resetmethod=nodemcu
+espduino.menu.UploadTool.espota=OTA
+espduino.menu.UploadTool.espota.upload.tool=espota
+espduino.menu.UploadTool.esptool=Serial
+espduino.menu.UploadTool.esptool.upload.tool=esptool
+espduino.menu.UploadTool.esptool.upload.verbose=--trace
+espduino.upload.tool=esptool
+espduino.upload.maximum_data_size=81920
+espduino.upload.wait_for_upload_port=true
+espduino.upload.erase_cmd=version
+espduino.serial.disableDTR=true
+espduino.serial.disableRTS=true
+espduino.build.mcu=esp8266
+espduino.build.core=esp8266
+espduino.build.spiffs_pagesize=256
+espduino.build.debug_port=
+espduino.build.debug_level=
+espduino.menu.xtal.80=80 MHz
+espduino.menu.xtal.80.build.f_cpu=80000000L
+espduino.menu.xtal.160=160 MHz
+espduino.menu.xtal.160.build.f_cpu=160000000L
+espduino.menu.vt.flash=Flash
+espduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+espduino.menu.vt.heap=Heap
+espduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+espduino.menu.vt.iram=IRAM
+espduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+espduino.menu.exception.legacy=Legacy (new can return nullptr)
+espduino.menu.exception.legacy.build.exception_flags=-fno-exceptions
+espduino.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+espduino.menu.exception.disabled=Disabled (new can abort)
+espduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+espduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+espduino.menu.exception.enabled=Enabled
+espduino.menu.exception.enabled.build.exception_flags=-fexceptions
+espduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+espduino.menu.ssl.all=All SSL ciphers (most compatible)
+espduino.menu.ssl.all.build.sslflags=
+espduino.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+espduino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+espduino.build.flash_mode=dio
+espduino.build.flash_flags=-DFLASHMODE_DIO
+espduino.build.flash_freq=40
+espduino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+espduino.menu.eesz.4M2M.build.flash_size=4M
+espduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+espduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+espduino.menu.eesz.4M2M.build.spiffs_pagesize=256
+espduino.menu.eesz.4M2M.upload.maximum_size=1044464
+espduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+espduino.menu.eesz.4M2M.build.spiffs_start=0x200000
+espduino.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+espduino.menu.eesz.4M2M.build.spiffs_blocksize=8192
+espduino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+espduino.menu.eesz.4M3M.build.flash_size=4M
+espduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+espduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+espduino.menu.eesz.4M3M.build.spiffs_pagesize=256
+espduino.menu.eesz.4M3M.upload.maximum_size=1044464
+espduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+espduino.menu.eesz.4M3M.build.spiffs_start=0x100000
+espduino.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+espduino.menu.eesz.4M3M.build.spiffs_blocksize=8192
+espduino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+espduino.menu.eesz.4M1M.build.flash_size=4M
+espduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+espduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+espduino.menu.eesz.4M1M.build.spiffs_pagesize=256
+espduino.menu.eesz.4M1M.upload.maximum_size=1044464
+espduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+espduino.menu.eesz.4M1M.build.spiffs_start=0x300000
+espduino.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+espduino.menu.eesz.4M1M.build.spiffs_blocksize=8192
+espduino.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+espduino.menu.eesz.4M.build.flash_size=4M
+espduino.menu.eesz.4M.build.flash_size_bytes=0x400000
+espduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+espduino.menu.eesz.4M.build.spiffs_pagesize=256
+espduino.menu.eesz.4M.upload.maximum_size=1044464
+espduino.menu.eesz.4M.build.rfcal_addr=0x3FC000
+espduino.menu.ip.lm2f=v2 Lower Memory
+espduino.menu.ip.lm2f.build.lwip_include=lwip2/include
+espduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+espduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espduino.menu.ip.hb2f=v2 Higher Bandwidth
+espduino.menu.ip.hb2f.build.lwip_include=lwip2/include
+espduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+espduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espduino.menu.ip.lm2n=v2 Lower Memory (no features)
+espduino.menu.ip.lm2n.build.lwip_include=lwip2/include
+espduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+espduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espduino.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+espduino.menu.ip.hb2n.build.lwip_include=lwip2/include
+espduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+espduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espduino.menu.ip.lm6f=v2 IPv6 Lower Memory
+espduino.menu.ip.lm6f.build.lwip_include=lwip2/include
+espduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+espduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+espduino.menu.ip.hb6f.build.lwip_include=lwip2/include
+espduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+espduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espduino.menu.ip.hb1=v1.4 Higher Bandwidth
+espduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+espduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+espduino.menu.ip.src=v1.4 Compile from source
+espduino.menu.ip.src.build.lwip_lib=-llwip_src
+espduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+espduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+espduino.menu.dbg.Disabled=Disabled
+espduino.menu.dbg.Disabled.build.debug_port=
+espduino.menu.dbg.Serial=Serial
+espduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+espduino.menu.dbg.Serial1=Serial1
+espduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+espduino.menu.lvl.None____=None
+espduino.menu.lvl.None____.build.debug_level=
+espduino.menu.lvl.SSL=SSL
+espduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+espduino.menu.lvl.TLS_MEM=TLS_MEM
+espduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+espduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+espduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+espduino.menu.lvl.HTTP_SERVER=HTTP_SERVER
+espduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+espduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+espduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+espduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+espduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+espduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+espduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+espduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+espduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+espduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espduino.menu.lvl.CORE=CORE
+espduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+espduino.menu.lvl.WIFI=WIFI
+espduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+espduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+espduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+espduino.menu.lvl.UPDATER=UPDATER
+espduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+espduino.menu.lvl.OTA=OTA
+espduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+espduino.menu.lvl.OOM=OOM
+espduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+espduino.menu.lvl.MDNS=MDNS
+espduino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+espduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+espduino.menu.wipe.none=Only Sketch
+espduino.menu.wipe.none.upload.erase_cmd=version
+espduino.menu.wipe.sdk=Sketch + WiFi Settings
+espduino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+espduino.menu.wipe.all=All Flash Contents
+espduino.menu.wipe.all.upload.erase_cmd=erase_flash
+espduino.menu.baud.115200=115200
+espduino.menu.baud.115200.upload.speed=115200
+espduino.menu.baud.57600=57600
+espduino.menu.baud.57600.upload.speed=57600
+espduino.menu.baud.230400.linux=230400
+espduino.menu.baud.230400.macosx=230400
+espduino.menu.baud.230400.upload.speed=230400
+espduino.menu.baud.256000.windows=256000
+espduino.menu.baud.256000.upload.speed=256000
+espduino.menu.baud.460800.linux=460800
+espduino.menu.baud.460800.macosx=460800
+espduino.menu.baud.460800.upload.speed=460800
+espduino.menu.baud.512000.windows=512000
+espduino.menu.baud.512000.upload.speed=512000
+espduino.menu.baud.921600=921600
+espduino.menu.baud.921600.upload.speed=921600
+espduino.menu.baud.3000000=3000000
+espduino.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+huzzah.name=Adafruit Feather HUZZAH ESP8266
+huzzah.build.board=ESP8266_ESP12
+huzzah.build.variant=adafruit
+huzzah.upload.tool=esptool
+huzzah.upload.maximum_data_size=81920
+huzzah.upload.wait_for_upload_port=true
+huzzah.upload.erase_cmd=version
+huzzah.serial.disableDTR=true
+huzzah.serial.disableRTS=true
+huzzah.build.mcu=esp8266
+huzzah.build.core=esp8266
+huzzah.build.spiffs_pagesize=256
+huzzah.build.debug_port=
+huzzah.build.debug_level=
+huzzah.menu.xtal.80=80 MHz
+huzzah.menu.xtal.80.build.f_cpu=80000000L
+huzzah.menu.xtal.160=160 MHz
+huzzah.menu.xtal.160.build.f_cpu=160000000L
+huzzah.menu.vt.flash=Flash
+huzzah.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+huzzah.menu.vt.heap=Heap
+huzzah.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+huzzah.menu.vt.iram=IRAM
+huzzah.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+huzzah.menu.exception.legacy=Legacy (new can return nullptr)
+huzzah.menu.exception.legacy.build.exception_flags=-fno-exceptions
+huzzah.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+huzzah.menu.exception.disabled=Disabled (new can abort)
+huzzah.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+huzzah.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+huzzah.menu.exception.enabled=Enabled
+huzzah.menu.exception.enabled.build.exception_flags=-fexceptions
+huzzah.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+huzzah.menu.ssl.all=All SSL ciphers (most compatible)
+huzzah.menu.ssl.all.build.sslflags=
+huzzah.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+huzzah.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+huzzah.upload.resetmethod=nodemcu
+huzzah.build.flash_mode=qio
+huzzah.build.flash_flags=-DFLASHMODE_QIO
+huzzah.build.flash_freq=40
+huzzah.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+huzzah.menu.eesz.4M2M.build.flash_size=4M
+huzzah.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+huzzah.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+huzzah.menu.eesz.4M2M.build.spiffs_pagesize=256
+huzzah.menu.eesz.4M2M.upload.maximum_size=1044464
+huzzah.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+huzzah.menu.eesz.4M2M.build.spiffs_start=0x200000
+huzzah.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+huzzah.menu.eesz.4M2M.build.spiffs_blocksize=8192
+huzzah.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+huzzah.menu.eesz.4M3M.build.flash_size=4M
+huzzah.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+huzzah.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+huzzah.menu.eesz.4M3M.build.spiffs_pagesize=256
+huzzah.menu.eesz.4M3M.upload.maximum_size=1044464
+huzzah.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+huzzah.menu.eesz.4M3M.build.spiffs_start=0x100000
+huzzah.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+huzzah.menu.eesz.4M3M.build.spiffs_blocksize=8192
+huzzah.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+huzzah.menu.eesz.4M1M.build.flash_size=4M
+huzzah.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+huzzah.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+huzzah.menu.eesz.4M1M.build.spiffs_pagesize=256
+huzzah.menu.eesz.4M1M.upload.maximum_size=1044464
+huzzah.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+huzzah.menu.eesz.4M1M.build.spiffs_start=0x300000
+huzzah.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+huzzah.menu.eesz.4M1M.build.spiffs_blocksize=8192
+huzzah.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+huzzah.menu.eesz.4M.build.flash_size=4M
+huzzah.menu.eesz.4M.build.flash_size_bytes=0x400000
+huzzah.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+huzzah.menu.eesz.4M.build.spiffs_pagesize=256
+huzzah.menu.eesz.4M.upload.maximum_size=1044464
+huzzah.menu.eesz.4M.build.rfcal_addr=0x3FC000
+huzzah.menu.ip.lm2f=v2 Lower Memory
+huzzah.menu.ip.lm2f.build.lwip_include=lwip2/include
+huzzah.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+huzzah.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+huzzah.menu.ip.hb2f=v2 Higher Bandwidth
+huzzah.menu.ip.hb2f.build.lwip_include=lwip2/include
+huzzah.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+huzzah.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+huzzah.menu.ip.lm2n=v2 Lower Memory (no features)
+huzzah.menu.ip.lm2n.build.lwip_include=lwip2/include
+huzzah.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+huzzah.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+huzzah.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+huzzah.menu.ip.hb2n.build.lwip_include=lwip2/include
+huzzah.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+huzzah.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+huzzah.menu.ip.lm6f=v2 IPv6 Lower Memory
+huzzah.menu.ip.lm6f.build.lwip_include=lwip2/include
+huzzah.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+huzzah.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+huzzah.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+huzzah.menu.ip.hb6f.build.lwip_include=lwip2/include
+huzzah.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+huzzah.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+huzzah.menu.ip.hb1=v1.4 Higher Bandwidth
+huzzah.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+huzzah.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+huzzah.menu.ip.src=v1.4 Compile from source
+huzzah.menu.ip.src.build.lwip_lib=-llwip_src
+huzzah.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+huzzah.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+huzzah.menu.dbg.Disabled=Disabled
+huzzah.menu.dbg.Disabled.build.debug_port=
+huzzah.menu.dbg.Serial=Serial
+huzzah.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+huzzah.menu.dbg.Serial1=Serial1
+huzzah.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+huzzah.menu.lvl.None____=None
+huzzah.menu.lvl.None____.build.debug_level=
+huzzah.menu.lvl.SSL=SSL
+huzzah.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+huzzah.menu.lvl.TLS_MEM=TLS_MEM
+huzzah.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+huzzah.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+huzzah.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+huzzah.menu.lvl.HTTP_SERVER=HTTP_SERVER
+huzzah.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+huzzah.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+huzzah.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+huzzah.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+huzzah.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+huzzah.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+huzzah.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+huzzah.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+huzzah.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+huzzah.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+huzzah.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+huzzah.menu.lvl.CORE=CORE
+huzzah.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+huzzah.menu.lvl.WIFI=WIFI
+huzzah.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+huzzah.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+huzzah.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+huzzah.menu.lvl.UPDATER=UPDATER
+huzzah.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+huzzah.menu.lvl.OTA=OTA
+huzzah.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+huzzah.menu.lvl.OOM=OOM
+huzzah.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+huzzah.menu.lvl.MDNS=MDNS
+huzzah.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+huzzah.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+huzzah.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+huzzah.menu.wipe.none=Only Sketch
+huzzah.menu.wipe.none.upload.erase_cmd=version
+huzzah.menu.wipe.sdk=Sketch + WiFi Settings
+huzzah.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+huzzah.menu.wipe.all=All Flash Contents
+huzzah.menu.wipe.all.upload.erase_cmd=erase_flash
+huzzah.menu.baud.115200=115200
+huzzah.menu.baud.115200.upload.speed=115200
+huzzah.menu.baud.57600=57600
+huzzah.menu.baud.57600.upload.speed=57600
+huzzah.menu.baud.230400.linux=230400
+huzzah.menu.baud.230400.macosx=230400
+huzzah.menu.baud.230400.upload.speed=230400
+huzzah.menu.baud.256000.windows=256000
+huzzah.menu.baud.256000.upload.speed=256000
+huzzah.menu.baud.460800.linux=460800
+huzzah.menu.baud.460800.macosx=460800
+huzzah.menu.baud.460800.upload.speed=460800
+huzzah.menu.baud.512000.windows=512000
+huzzah.menu.baud.512000.upload.speed=512000
+huzzah.menu.baud.921600=921600
+huzzah.menu.baud.921600.upload.speed=921600
+huzzah.menu.baud.3000000=3000000
+huzzah.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+inventone.name=Invent One
+inventone.build.board=ESP8266_GENERIC
+inventone.build.variant=inventone
+inventone.upload.tool=esptool
+inventone.upload.maximum_data_size=81920
+inventone.upload.wait_for_upload_port=true
+inventone.upload.erase_cmd=version
+inventone.serial.disableDTR=true
+inventone.serial.disableRTS=true
+inventone.build.mcu=esp8266
+inventone.build.core=esp8266
+inventone.build.spiffs_pagesize=256
+inventone.build.debug_port=
+inventone.build.debug_level=
+inventone.menu.xtal.80=80 MHz
+inventone.menu.xtal.80.build.f_cpu=80000000L
+inventone.menu.xtal.160=160 MHz
+inventone.menu.xtal.160.build.f_cpu=160000000L
+inventone.menu.vt.flash=Flash
+inventone.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+inventone.menu.vt.heap=Heap
+inventone.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+inventone.menu.vt.iram=IRAM
+inventone.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+inventone.menu.exception.legacy=Legacy (new can return nullptr)
+inventone.menu.exception.legacy.build.exception_flags=-fno-exceptions
+inventone.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+inventone.menu.exception.disabled=Disabled (new can abort)
+inventone.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+inventone.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+inventone.menu.exception.enabled=Enabled
+inventone.menu.exception.enabled.build.exception_flags=-fexceptions
+inventone.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+inventone.menu.ssl.all=All SSL ciphers (most compatible)
+inventone.menu.ssl.all.build.sslflags=
+inventone.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+inventone.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+inventone.upload.resetmethod=nodemcu
+inventone.build.flash_mode=dio
+inventone.build.flash_flags=-DFLASHMODE_DIO
+inventone.build.flash_freq=40
+inventone.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+inventone.menu.eesz.4M2M.build.flash_size=4M
+inventone.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+inventone.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+inventone.menu.eesz.4M2M.build.spiffs_pagesize=256
+inventone.menu.eesz.4M2M.upload.maximum_size=1044464
+inventone.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+inventone.menu.eesz.4M2M.build.spiffs_start=0x200000
+inventone.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+inventone.menu.eesz.4M2M.build.spiffs_blocksize=8192
+inventone.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+inventone.menu.eesz.4M3M.build.flash_size=4M
+inventone.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+inventone.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+inventone.menu.eesz.4M3M.build.spiffs_pagesize=256
+inventone.menu.eesz.4M3M.upload.maximum_size=1044464
+inventone.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+inventone.menu.eesz.4M3M.build.spiffs_start=0x100000
+inventone.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+inventone.menu.eesz.4M3M.build.spiffs_blocksize=8192
+inventone.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+inventone.menu.eesz.4M1M.build.flash_size=4M
+inventone.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+inventone.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+inventone.menu.eesz.4M1M.build.spiffs_pagesize=256
+inventone.menu.eesz.4M1M.upload.maximum_size=1044464
+inventone.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+inventone.menu.eesz.4M1M.build.spiffs_start=0x300000
+inventone.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+inventone.menu.eesz.4M1M.build.spiffs_blocksize=8192
+inventone.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+inventone.menu.eesz.4M.build.flash_size=4M
+inventone.menu.eesz.4M.build.flash_size_bytes=0x400000
+inventone.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+inventone.menu.eesz.4M.build.spiffs_pagesize=256
+inventone.menu.eesz.4M.upload.maximum_size=1044464
+inventone.menu.eesz.4M.build.rfcal_addr=0x3FC000
+inventone.menu.ip.lm2f=v2 Lower Memory
+inventone.menu.ip.lm2f.build.lwip_include=lwip2/include
+inventone.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+inventone.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+inventone.menu.ip.hb2f=v2 Higher Bandwidth
+inventone.menu.ip.hb2f.build.lwip_include=lwip2/include
+inventone.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+inventone.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+inventone.menu.ip.lm2n=v2 Lower Memory (no features)
+inventone.menu.ip.lm2n.build.lwip_include=lwip2/include
+inventone.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+inventone.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+inventone.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+inventone.menu.ip.hb2n.build.lwip_include=lwip2/include
+inventone.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+inventone.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+inventone.menu.ip.lm6f=v2 IPv6 Lower Memory
+inventone.menu.ip.lm6f.build.lwip_include=lwip2/include
+inventone.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+inventone.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+inventone.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+inventone.menu.ip.hb6f.build.lwip_include=lwip2/include
+inventone.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+inventone.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+inventone.menu.ip.hb1=v1.4 Higher Bandwidth
+inventone.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+inventone.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+inventone.menu.ip.src=v1.4 Compile from source
+inventone.menu.ip.src.build.lwip_lib=-llwip_src
+inventone.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+inventone.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+inventone.menu.dbg.Disabled=Disabled
+inventone.menu.dbg.Disabled.build.debug_port=
+inventone.menu.dbg.Serial=Serial
+inventone.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+inventone.menu.dbg.Serial1=Serial1
+inventone.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+inventone.menu.lvl.None____=None
+inventone.menu.lvl.None____.build.debug_level=
+inventone.menu.lvl.SSL=SSL
+inventone.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+inventone.menu.lvl.TLS_MEM=TLS_MEM
+inventone.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+inventone.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+inventone.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+inventone.menu.lvl.HTTP_SERVER=HTTP_SERVER
+inventone.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+inventone.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+inventone.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+inventone.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+inventone.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+inventone.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+inventone.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+inventone.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+inventone.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+inventone.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+inventone.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+inventone.menu.lvl.CORE=CORE
+inventone.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+inventone.menu.lvl.WIFI=WIFI
+inventone.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+inventone.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+inventone.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+inventone.menu.lvl.UPDATER=UPDATER
+inventone.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+inventone.menu.lvl.OTA=OTA
+inventone.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+inventone.menu.lvl.OOM=OOM
+inventone.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+inventone.menu.lvl.MDNS=MDNS
+inventone.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+inventone.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+inventone.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+inventone.menu.wipe.none=Only Sketch
+inventone.menu.wipe.none.upload.erase_cmd=version
+inventone.menu.wipe.sdk=Sketch + WiFi Settings
+inventone.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+inventone.menu.wipe.all=All Flash Contents
+inventone.menu.wipe.all.upload.erase_cmd=erase_flash
+inventone.menu.baud.115200=115200
+inventone.menu.baud.115200.upload.speed=115200
+inventone.menu.baud.57600=57600
+inventone.menu.baud.57600.upload.speed=57600
+inventone.menu.baud.230400.linux=230400
+inventone.menu.baud.230400.macosx=230400
+inventone.menu.baud.230400.upload.speed=230400
+inventone.menu.baud.256000.windows=256000
+inventone.menu.baud.256000.upload.speed=256000
+inventone.menu.baud.460800.linux=460800
+inventone.menu.baud.460800.macosx=460800
+inventone.menu.baud.460800.upload.speed=460800
+inventone.menu.baud.512000.windows=512000
+inventone.menu.baud.512000.upload.speed=512000
+inventone.menu.baud.921600=921600
+inventone.menu.baud.921600.upload.speed=921600
+inventone.menu.baud.3000000=3000000
+inventone.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+cw01.name=XinaBox CW01
+cw01.build.board=ESP8266_GENERIC
+cw01.build.variant=xinabox
+cw01.upload.tool=esptool
+cw01.upload.maximum_data_size=81920
+cw01.upload.wait_for_upload_port=true
+cw01.upload.erase_cmd=version
+cw01.serial.disableDTR=true
+cw01.serial.disableRTS=true
+cw01.build.mcu=esp8266
+cw01.build.core=esp8266
+cw01.build.spiffs_pagesize=256
+cw01.build.debug_port=
+cw01.build.debug_level=
+cw01.menu.xtal.80=80 MHz
+cw01.menu.xtal.80.build.f_cpu=80000000L
+cw01.menu.xtal.160=160 MHz
+cw01.menu.xtal.160.build.f_cpu=160000000L
+cw01.menu.vt.flash=Flash
+cw01.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+cw01.menu.vt.heap=Heap
+cw01.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+cw01.menu.vt.iram=IRAM
+cw01.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+cw01.menu.exception.legacy=Legacy (new can return nullptr)
+cw01.menu.exception.legacy.build.exception_flags=-fno-exceptions
+cw01.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+cw01.menu.exception.disabled=Disabled (new can abort)
+cw01.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+cw01.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+cw01.menu.exception.enabled=Enabled
+cw01.menu.exception.enabled.build.exception_flags=-fexceptions
+cw01.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+cw01.menu.ssl.all=All SSL ciphers (most compatible)
+cw01.menu.ssl.all.build.sslflags=
+cw01.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+cw01.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+cw01.upload.resetmethod=nodemcu
+cw01.menu.CrystalFreq.26=26 MHz
+cw01.menu.CrystalFreq.40=40 MHz
+cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266
+cw01.build.flash_mode=dio
+cw01.build.flash_flags=-DFLASHMODE_DIO
+cw01.build.flash_freq=40
+cw01.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+cw01.menu.eesz.4M2M.build.flash_size=4M
+cw01.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+cw01.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+cw01.menu.eesz.4M2M.build.spiffs_pagesize=256
+cw01.menu.eesz.4M2M.upload.maximum_size=1044464
+cw01.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+cw01.menu.eesz.4M2M.build.spiffs_start=0x200000
+cw01.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+cw01.menu.eesz.4M2M.build.spiffs_blocksize=8192
+cw01.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+cw01.menu.eesz.4M3M.build.flash_size=4M
+cw01.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+cw01.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+cw01.menu.eesz.4M3M.build.spiffs_pagesize=256
+cw01.menu.eesz.4M3M.upload.maximum_size=1044464
+cw01.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+cw01.menu.eesz.4M3M.build.spiffs_start=0x100000
+cw01.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+cw01.menu.eesz.4M3M.build.spiffs_blocksize=8192
+cw01.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+cw01.menu.eesz.4M1M.build.flash_size=4M
+cw01.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+cw01.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+cw01.menu.eesz.4M1M.build.spiffs_pagesize=256
+cw01.menu.eesz.4M1M.upload.maximum_size=1044464
+cw01.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+cw01.menu.eesz.4M1M.build.spiffs_start=0x300000
+cw01.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+cw01.menu.eesz.4M1M.build.spiffs_blocksize=8192
+cw01.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+cw01.menu.eesz.4M.build.flash_size=4M
+cw01.menu.eesz.4M.build.flash_size_bytes=0x400000
+cw01.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+cw01.menu.eesz.4M.build.spiffs_pagesize=256
+cw01.menu.eesz.4M.upload.maximum_size=1044464
+cw01.menu.eesz.4M.build.rfcal_addr=0x3FC000
+cw01.menu.ip.lm2f=v2 Lower Memory
+cw01.menu.ip.lm2f.build.lwip_include=lwip2/include
+cw01.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+cw01.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+cw01.menu.ip.hb2f=v2 Higher Bandwidth
+cw01.menu.ip.hb2f.build.lwip_include=lwip2/include
+cw01.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+cw01.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+cw01.menu.ip.lm2n=v2 Lower Memory (no features)
+cw01.menu.ip.lm2n.build.lwip_include=lwip2/include
+cw01.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+cw01.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+cw01.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+cw01.menu.ip.hb2n.build.lwip_include=lwip2/include
+cw01.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+cw01.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+cw01.menu.ip.lm6f=v2 IPv6 Lower Memory
+cw01.menu.ip.lm6f.build.lwip_include=lwip2/include
+cw01.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+cw01.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+cw01.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+cw01.menu.ip.hb6f.build.lwip_include=lwip2/include
+cw01.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+cw01.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+cw01.menu.ip.hb1=v1.4 Higher Bandwidth
+cw01.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+cw01.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+cw01.menu.ip.src=v1.4 Compile from source
+cw01.menu.ip.src.build.lwip_lib=-llwip_src
+cw01.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+cw01.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+cw01.menu.dbg.Disabled=Disabled
+cw01.menu.dbg.Disabled.build.debug_port=
+cw01.menu.dbg.Serial=Serial
+cw01.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+cw01.menu.dbg.Serial1=Serial1
+cw01.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+cw01.menu.lvl.None____=None
+cw01.menu.lvl.None____.build.debug_level=
+cw01.menu.lvl.SSL=SSL
+cw01.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+cw01.menu.lvl.TLS_MEM=TLS_MEM
+cw01.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+cw01.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+cw01.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+cw01.menu.lvl.HTTP_SERVER=HTTP_SERVER
+cw01.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+cw01.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+cw01.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+cw01.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+cw01.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+cw01.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+cw01.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+cw01.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+cw01.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+cw01.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+cw01.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+cw01.menu.lvl.CORE=CORE
+cw01.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+cw01.menu.lvl.WIFI=WIFI
+cw01.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+cw01.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+cw01.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+cw01.menu.lvl.UPDATER=UPDATER
+cw01.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+cw01.menu.lvl.OTA=OTA
+cw01.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+cw01.menu.lvl.OOM=OOM
+cw01.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+cw01.menu.lvl.MDNS=MDNS
+cw01.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+cw01.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+cw01.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+cw01.menu.wipe.none=Only Sketch
+cw01.menu.wipe.none.upload.erase_cmd=version
+cw01.menu.wipe.sdk=Sketch + WiFi Settings
+cw01.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+cw01.menu.wipe.all=All Flash Contents
+cw01.menu.wipe.all.upload.erase_cmd=erase_flash
+cw01.menu.baud.115200=115200
+cw01.menu.baud.115200.upload.speed=115200
+cw01.menu.baud.57600=57600
+cw01.menu.baud.57600.upload.speed=57600
+cw01.menu.baud.230400.linux=230400
+cw01.menu.baud.230400.macosx=230400
+cw01.menu.baud.230400.upload.speed=230400
+cw01.menu.baud.256000.windows=256000
+cw01.menu.baud.256000.upload.speed=256000
+cw01.menu.baud.460800.linux=460800
+cw01.menu.baud.460800.macosx=460800
+cw01.menu.baud.460800.upload.speed=460800
+cw01.menu.baud.512000.windows=512000
+cw01.menu.baud.512000.upload.speed=512000
+cw01.menu.baud.921600=921600
+cw01.menu.baud.921600.upload.speed=921600
+cw01.menu.baud.3000000=3000000
+cw01.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+espresso_lite_v1.name=ESPresso Lite 1.0
+espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1
+espresso_lite_v1.build.variant=espresso_lite_v1
+espresso_lite_v1.upload.tool=esptool
+espresso_lite_v1.upload.maximum_data_size=81920
+espresso_lite_v1.upload.wait_for_upload_port=true
+espresso_lite_v1.upload.erase_cmd=version
+espresso_lite_v1.serial.disableDTR=true
+espresso_lite_v1.serial.disableRTS=true
+espresso_lite_v1.build.mcu=esp8266
+espresso_lite_v1.build.core=esp8266
+espresso_lite_v1.build.spiffs_pagesize=256
+espresso_lite_v1.build.debug_port=
+espresso_lite_v1.build.debug_level=
+espresso_lite_v1.menu.xtal.80=80 MHz
+espresso_lite_v1.menu.xtal.80.build.f_cpu=80000000L
+espresso_lite_v1.menu.xtal.160=160 MHz
+espresso_lite_v1.menu.xtal.160.build.f_cpu=160000000L
+espresso_lite_v1.menu.vt.flash=Flash
+espresso_lite_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+espresso_lite_v1.menu.vt.heap=Heap
+espresso_lite_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+espresso_lite_v1.menu.vt.iram=IRAM
+espresso_lite_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+espresso_lite_v1.menu.exception.legacy=Legacy (new can return nullptr)
+espresso_lite_v1.menu.exception.legacy.build.exception_flags=-fno-exceptions
+espresso_lite_v1.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+espresso_lite_v1.menu.exception.disabled=Disabled (new can abort)
+espresso_lite_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+espresso_lite_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+espresso_lite_v1.menu.exception.enabled=Enabled
+espresso_lite_v1.menu.exception.enabled.build.exception_flags=-fexceptions
+espresso_lite_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+espresso_lite_v1.menu.ssl.all=All SSL ciphers (most compatible)
+espresso_lite_v1.menu.ssl.all.build.sslflags=
+espresso_lite_v1.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+espresso_lite_v1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+espresso_lite_v1.build.flash_mode=dio
+espresso_lite_v1.build.flash_flags=-DFLASHMODE_DIO
+espresso_lite_v1.build.flash_freq=40
+espresso_lite_v1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+espresso_lite_v1.menu.eesz.4M2M.build.flash_size=4M
+espresso_lite_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+espresso_lite_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+espresso_lite_v1.menu.eesz.4M2M.build.spiffs_pagesize=256
+espresso_lite_v1.menu.eesz.4M2M.upload.maximum_size=1044464
+espresso_lite_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+espresso_lite_v1.menu.eesz.4M2M.build.spiffs_start=0x200000
+espresso_lite_v1.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+espresso_lite_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192
+espresso_lite_v1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+espresso_lite_v1.menu.eesz.4M3M.build.flash_size=4M
+espresso_lite_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+espresso_lite_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+espresso_lite_v1.menu.eesz.4M3M.build.spiffs_pagesize=256
+espresso_lite_v1.menu.eesz.4M3M.upload.maximum_size=1044464
+espresso_lite_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+espresso_lite_v1.menu.eesz.4M3M.build.spiffs_start=0x100000
+espresso_lite_v1.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+espresso_lite_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192
+espresso_lite_v1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+espresso_lite_v1.menu.eesz.4M1M.build.flash_size=4M
+espresso_lite_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+espresso_lite_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+espresso_lite_v1.menu.eesz.4M1M.build.spiffs_pagesize=256
+espresso_lite_v1.menu.eesz.4M1M.upload.maximum_size=1044464
+espresso_lite_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+espresso_lite_v1.menu.eesz.4M1M.build.spiffs_start=0x300000
+espresso_lite_v1.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+espresso_lite_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192
+espresso_lite_v1.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+espresso_lite_v1.menu.eesz.4M.build.flash_size=4M
+espresso_lite_v1.menu.eesz.4M.build.flash_size_bytes=0x400000
+espresso_lite_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+espresso_lite_v1.menu.eesz.4M.build.spiffs_pagesize=256
+espresso_lite_v1.menu.eesz.4M.upload.maximum_size=1044464
+espresso_lite_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000
+espresso_lite_v1.menu.ResetMethod.ck=ck
+espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck
+espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu
+espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu
+espresso_lite_v1.menu.ip.lm2f=v2 Lower Memory
+espresso_lite_v1.menu.ip.lm2f.build.lwip_include=lwip2/include
+espresso_lite_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+espresso_lite_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espresso_lite_v1.menu.ip.hb2f=v2 Higher Bandwidth
+espresso_lite_v1.menu.ip.hb2f.build.lwip_include=lwip2/include
+espresso_lite_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+espresso_lite_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espresso_lite_v1.menu.ip.lm2n=v2 Lower Memory (no features)
+espresso_lite_v1.menu.ip.lm2n.build.lwip_include=lwip2/include
+espresso_lite_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+espresso_lite_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espresso_lite_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+espresso_lite_v1.menu.ip.hb2n.build.lwip_include=lwip2/include
+espresso_lite_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+espresso_lite_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espresso_lite_v1.menu.ip.lm6f=v2 IPv6 Lower Memory
+espresso_lite_v1.menu.ip.lm6f.build.lwip_include=lwip2/include
+espresso_lite_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+espresso_lite_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espresso_lite_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+espresso_lite_v1.menu.ip.hb6f.build.lwip_include=lwip2/include
+espresso_lite_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+espresso_lite_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espresso_lite_v1.menu.ip.hb1=v1.4 Higher Bandwidth
+espresso_lite_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+espresso_lite_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+espresso_lite_v1.menu.ip.src=v1.4 Compile from source
+espresso_lite_v1.menu.ip.src.build.lwip_lib=-llwip_src
+espresso_lite_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+espresso_lite_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+espresso_lite_v1.menu.dbg.Disabled=Disabled
+espresso_lite_v1.menu.dbg.Disabled.build.debug_port=
+espresso_lite_v1.menu.dbg.Serial=Serial
+espresso_lite_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+espresso_lite_v1.menu.dbg.Serial1=Serial1
+espresso_lite_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+espresso_lite_v1.menu.lvl.None____=None
+espresso_lite_v1.menu.lvl.None____.build.debug_level=
+espresso_lite_v1.menu.lvl.SSL=SSL
+espresso_lite_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+espresso_lite_v1.menu.lvl.TLS_MEM=TLS_MEM
+espresso_lite_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+espresso_lite_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+espresso_lite_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+espresso_lite_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER
+espresso_lite_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+espresso_lite_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+espresso_lite_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+espresso_lite_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v1.menu.lvl.CORE=CORE
+espresso_lite_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+espresso_lite_v1.menu.lvl.WIFI=WIFI
+espresso_lite_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+espresso_lite_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+espresso_lite_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+espresso_lite_v1.menu.lvl.UPDATER=UPDATER
+espresso_lite_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+espresso_lite_v1.menu.lvl.OTA=OTA
+espresso_lite_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+espresso_lite_v1.menu.lvl.OOM=OOM
+espresso_lite_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+espresso_lite_v1.menu.lvl.MDNS=MDNS
+espresso_lite_v1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espresso_lite_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+espresso_lite_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+espresso_lite_v1.menu.wipe.none=Only Sketch
+espresso_lite_v1.menu.wipe.none.upload.erase_cmd=version
+espresso_lite_v1.menu.wipe.sdk=Sketch + WiFi Settings
+espresso_lite_v1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+espresso_lite_v1.menu.wipe.all=All Flash Contents
+espresso_lite_v1.menu.wipe.all.upload.erase_cmd=erase_flash
+espresso_lite_v1.menu.baud.115200=115200
+espresso_lite_v1.menu.baud.115200.upload.speed=115200
+espresso_lite_v1.menu.baud.57600=57600
+espresso_lite_v1.menu.baud.57600.upload.speed=57600
+espresso_lite_v1.menu.baud.230400.linux=230400
+espresso_lite_v1.menu.baud.230400.macosx=230400
+espresso_lite_v1.menu.baud.230400.upload.speed=230400
+espresso_lite_v1.menu.baud.256000.windows=256000
+espresso_lite_v1.menu.baud.256000.upload.speed=256000
+espresso_lite_v1.menu.baud.460800.linux=460800
+espresso_lite_v1.menu.baud.460800.macosx=460800
+espresso_lite_v1.menu.baud.460800.upload.speed=460800
+espresso_lite_v1.menu.baud.512000.windows=512000
+espresso_lite_v1.menu.baud.512000.upload.speed=512000
+espresso_lite_v1.menu.baud.921600=921600
+espresso_lite_v1.menu.baud.921600.upload.speed=921600
+espresso_lite_v1.menu.baud.3000000=3000000
+espresso_lite_v1.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+espresso_lite_v2.name=ESPresso Lite 2.0
+espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2
+espresso_lite_v2.build.variant=espresso_lite_v2
+espresso_lite_v2.upload.tool=esptool
+espresso_lite_v2.upload.maximum_data_size=81920
+espresso_lite_v2.upload.wait_for_upload_port=true
+espresso_lite_v2.upload.erase_cmd=version
+espresso_lite_v2.serial.disableDTR=true
+espresso_lite_v2.serial.disableRTS=true
+espresso_lite_v2.build.mcu=esp8266
+espresso_lite_v2.build.core=esp8266
+espresso_lite_v2.build.spiffs_pagesize=256
+espresso_lite_v2.build.debug_port=
+espresso_lite_v2.build.debug_level=
+espresso_lite_v2.menu.xtal.80=80 MHz
+espresso_lite_v2.menu.xtal.80.build.f_cpu=80000000L
+espresso_lite_v2.menu.xtal.160=160 MHz
+espresso_lite_v2.menu.xtal.160.build.f_cpu=160000000L
+espresso_lite_v2.menu.vt.flash=Flash
+espresso_lite_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+espresso_lite_v2.menu.vt.heap=Heap
+espresso_lite_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+espresso_lite_v2.menu.vt.iram=IRAM
+espresso_lite_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+espresso_lite_v2.menu.exception.legacy=Legacy (new can return nullptr)
+espresso_lite_v2.menu.exception.legacy.build.exception_flags=-fno-exceptions
+espresso_lite_v2.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+espresso_lite_v2.menu.exception.disabled=Disabled (new can abort)
+espresso_lite_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+espresso_lite_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+espresso_lite_v2.menu.exception.enabled=Enabled
+espresso_lite_v2.menu.exception.enabled.build.exception_flags=-fexceptions
+espresso_lite_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+espresso_lite_v2.menu.ssl.all=All SSL ciphers (most compatible)
+espresso_lite_v2.menu.ssl.all.build.sslflags=
+espresso_lite_v2.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+espresso_lite_v2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+espresso_lite_v2.build.flash_mode=dio
+espresso_lite_v2.build.flash_flags=-DFLASHMODE_DIO
+espresso_lite_v2.build.flash_freq=40
+espresso_lite_v2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+espresso_lite_v2.menu.eesz.4M2M.build.flash_size=4M
+espresso_lite_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+espresso_lite_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+espresso_lite_v2.menu.eesz.4M2M.build.spiffs_pagesize=256
+espresso_lite_v2.menu.eesz.4M2M.upload.maximum_size=1044464
+espresso_lite_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+espresso_lite_v2.menu.eesz.4M2M.build.spiffs_start=0x200000
+espresso_lite_v2.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+espresso_lite_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192
+espresso_lite_v2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+espresso_lite_v2.menu.eesz.4M3M.build.flash_size=4M
+espresso_lite_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+espresso_lite_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+espresso_lite_v2.menu.eesz.4M3M.build.spiffs_pagesize=256
+espresso_lite_v2.menu.eesz.4M3M.upload.maximum_size=1044464
+espresso_lite_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+espresso_lite_v2.menu.eesz.4M3M.build.spiffs_start=0x100000
+espresso_lite_v2.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+espresso_lite_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192
+espresso_lite_v2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+espresso_lite_v2.menu.eesz.4M1M.build.flash_size=4M
+espresso_lite_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+espresso_lite_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+espresso_lite_v2.menu.eesz.4M1M.build.spiffs_pagesize=256
+espresso_lite_v2.menu.eesz.4M1M.upload.maximum_size=1044464
+espresso_lite_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+espresso_lite_v2.menu.eesz.4M1M.build.spiffs_start=0x300000
+espresso_lite_v2.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+espresso_lite_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192
+espresso_lite_v2.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+espresso_lite_v2.menu.eesz.4M.build.flash_size=4M
+espresso_lite_v2.menu.eesz.4M.build.flash_size_bytes=0x400000
+espresso_lite_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+espresso_lite_v2.menu.eesz.4M.build.spiffs_pagesize=256
+espresso_lite_v2.menu.eesz.4M.upload.maximum_size=1044464
+espresso_lite_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000
+espresso_lite_v2.menu.ResetMethod.ck=ck
+espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck
+espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu
+espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu
+espresso_lite_v2.menu.ip.lm2f=v2 Lower Memory
+espresso_lite_v2.menu.ip.lm2f.build.lwip_include=lwip2/include
+espresso_lite_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+espresso_lite_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espresso_lite_v2.menu.ip.hb2f=v2 Higher Bandwidth
+espresso_lite_v2.menu.ip.hb2f.build.lwip_include=lwip2/include
+espresso_lite_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+espresso_lite_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espresso_lite_v2.menu.ip.lm2n=v2 Lower Memory (no features)
+espresso_lite_v2.menu.ip.lm2n.build.lwip_include=lwip2/include
+espresso_lite_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+espresso_lite_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espresso_lite_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+espresso_lite_v2.menu.ip.hb2n.build.lwip_include=lwip2/include
+espresso_lite_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+espresso_lite_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espresso_lite_v2.menu.ip.lm6f=v2 IPv6 Lower Memory
+espresso_lite_v2.menu.ip.lm6f.build.lwip_include=lwip2/include
+espresso_lite_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+espresso_lite_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espresso_lite_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+espresso_lite_v2.menu.ip.hb6f.build.lwip_include=lwip2/include
+espresso_lite_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+espresso_lite_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espresso_lite_v2.menu.ip.hb1=v1.4 Higher Bandwidth
+espresso_lite_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+espresso_lite_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+espresso_lite_v2.menu.ip.src=v1.4 Compile from source
+espresso_lite_v2.menu.ip.src.build.lwip_lib=-llwip_src
+espresso_lite_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+espresso_lite_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+espresso_lite_v2.menu.dbg.Disabled=Disabled
+espresso_lite_v2.menu.dbg.Disabled.build.debug_port=
+espresso_lite_v2.menu.dbg.Serial=Serial
+espresso_lite_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+espresso_lite_v2.menu.dbg.Serial1=Serial1
+espresso_lite_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+espresso_lite_v2.menu.lvl.None____=None
+espresso_lite_v2.menu.lvl.None____.build.debug_level=
+espresso_lite_v2.menu.lvl.SSL=SSL
+espresso_lite_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+espresso_lite_v2.menu.lvl.TLS_MEM=TLS_MEM
+espresso_lite_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+espresso_lite_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+espresso_lite_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+espresso_lite_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER
+espresso_lite_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+espresso_lite_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+espresso_lite_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+espresso_lite_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espresso_lite_v2.menu.lvl.CORE=CORE
+espresso_lite_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+espresso_lite_v2.menu.lvl.WIFI=WIFI
+espresso_lite_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+espresso_lite_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+espresso_lite_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+espresso_lite_v2.menu.lvl.UPDATER=UPDATER
+espresso_lite_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+espresso_lite_v2.menu.lvl.OTA=OTA
+espresso_lite_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+espresso_lite_v2.menu.lvl.OOM=OOM
+espresso_lite_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+espresso_lite_v2.menu.lvl.MDNS=MDNS
+espresso_lite_v2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espresso_lite_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+espresso_lite_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+espresso_lite_v2.menu.wipe.none=Only Sketch
+espresso_lite_v2.menu.wipe.none.upload.erase_cmd=version
+espresso_lite_v2.menu.wipe.sdk=Sketch + WiFi Settings
+espresso_lite_v2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+espresso_lite_v2.menu.wipe.all=All Flash Contents
+espresso_lite_v2.menu.wipe.all.upload.erase_cmd=erase_flash
+espresso_lite_v2.menu.baud.115200=115200
+espresso_lite_v2.menu.baud.115200.upload.speed=115200
+espresso_lite_v2.menu.baud.57600=57600
+espresso_lite_v2.menu.baud.57600.upload.speed=57600
+espresso_lite_v2.menu.baud.230400.linux=230400
+espresso_lite_v2.menu.baud.230400.macosx=230400
+espresso_lite_v2.menu.baud.230400.upload.speed=230400
+espresso_lite_v2.menu.baud.256000.windows=256000
+espresso_lite_v2.menu.baud.256000.upload.speed=256000
+espresso_lite_v2.menu.baud.460800.linux=460800
+espresso_lite_v2.menu.baud.460800.macosx=460800
+espresso_lite_v2.menu.baud.460800.upload.speed=460800
+espresso_lite_v2.menu.baud.512000.windows=512000
+espresso_lite_v2.menu.baud.512000.upload.speed=512000
+espresso_lite_v2.menu.baud.921600=921600
+espresso_lite_v2.menu.baud.921600.upload.speed=921600
+espresso_lite_v2.menu.baud.3000000=3000000
+espresso_lite_v2.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+phoenix_v1.name=Phoenix 1.0
+phoenix_v1.build.board=ESP8266_PHOENIX_V1
+phoenix_v1.build.variant=phoenix_v1
+phoenix_v1.upload.tool=esptool
+phoenix_v1.upload.maximum_data_size=81920
+phoenix_v1.upload.wait_for_upload_port=true
+phoenix_v1.upload.erase_cmd=version
+phoenix_v1.serial.disableDTR=true
+phoenix_v1.serial.disableRTS=true
+phoenix_v1.build.mcu=esp8266
+phoenix_v1.build.core=esp8266
+phoenix_v1.build.spiffs_pagesize=256
+phoenix_v1.build.debug_port=
+phoenix_v1.build.debug_level=
+phoenix_v1.menu.xtal.80=80 MHz
+phoenix_v1.menu.xtal.80.build.f_cpu=80000000L
+phoenix_v1.menu.xtal.160=160 MHz
+phoenix_v1.menu.xtal.160.build.f_cpu=160000000L
+phoenix_v1.menu.vt.flash=Flash
+phoenix_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+phoenix_v1.menu.vt.heap=Heap
+phoenix_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+phoenix_v1.menu.vt.iram=IRAM
+phoenix_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+phoenix_v1.menu.exception.legacy=Legacy (new can return nullptr)
+phoenix_v1.menu.exception.legacy.build.exception_flags=-fno-exceptions
+phoenix_v1.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+phoenix_v1.menu.exception.disabled=Disabled (new can abort)
+phoenix_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+phoenix_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+phoenix_v1.menu.exception.enabled=Enabled
+phoenix_v1.menu.exception.enabled.build.exception_flags=-fexceptions
+phoenix_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+phoenix_v1.menu.ssl.all=All SSL ciphers (most compatible)
+phoenix_v1.menu.ssl.all.build.sslflags=
+phoenix_v1.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+phoenix_v1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+phoenix_v1.build.flash_mode=dio
+phoenix_v1.build.flash_flags=-DFLASHMODE_DIO
+phoenix_v1.build.flash_freq=40
+phoenix_v1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+phoenix_v1.menu.eesz.4M2M.build.flash_size=4M
+phoenix_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+phoenix_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+phoenix_v1.menu.eesz.4M2M.build.spiffs_pagesize=256
+phoenix_v1.menu.eesz.4M2M.upload.maximum_size=1044464
+phoenix_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+phoenix_v1.menu.eesz.4M2M.build.spiffs_start=0x200000
+phoenix_v1.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+phoenix_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192
+phoenix_v1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+phoenix_v1.menu.eesz.4M3M.build.flash_size=4M
+phoenix_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+phoenix_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+phoenix_v1.menu.eesz.4M3M.build.spiffs_pagesize=256
+phoenix_v1.menu.eesz.4M3M.upload.maximum_size=1044464
+phoenix_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+phoenix_v1.menu.eesz.4M3M.build.spiffs_start=0x100000
+phoenix_v1.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+phoenix_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192
+phoenix_v1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+phoenix_v1.menu.eesz.4M1M.build.flash_size=4M
+phoenix_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+phoenix_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+phoenix_v1.menu.eesz.4M1M.build.spiffs_pagesize=256
+phoenix_v1.menu.eesz.4M1M.upload.maximum_size=1044464
+phoenix_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+phoenix_v1.menu.eesz.4M1M.build.spiffs_start=0x300000
+phoenix_v1.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+phoenix_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192
+phoenix_v1.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+phoenix_v1.menu.eesz.4M.build.flash_size=4M
+phoenix_v1.menu.eesz.4M.build.flash_size_bytes=0x400000
+phoenix_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+phoenix_v1.menu.eesz.4M.build.spiffs_pagesize=256
+phoenix_v1.menu.eesz.4M.upload.maximum_size=1044464
+phoenix_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000
+phoenix_v1.menu.ResetMethod.ck=ck
+phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck
+phoenix_v1.menu.ResetMethod.nodemcu=nodemcu
+phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu
+phoenix_v1.menu.ip.lm2f=v2 Lower Memory
+phoenix_v1.menu.ip.lm2f.build.lwip_include=lwip2/include
+phoenix_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+phoenix_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+phoenix_v1.menu.ip.hb2f=v2 Higher Bandwidth
+phoenix_v1.menu.ip.hb2f.build.lwip_include=lwip2/include
+phoenix_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+phoenix_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+phoenix_v1.menu.ip.lm2n=v2 Lower Memory (no features)
+phoenix_v1.menu.ip.lm2n.build.lwip_include=lwip2/include
+phoenix_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+phoenix_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+phoenix_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+phoenix_v1.menu.ip.hb2n.build.lwip_include=lwip2/include
+phoenix_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+phoenix_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+phoenix_v1.menu.ip.lm6f=v2 IPv6 Lower Memory
+phoenix_v1.menu.ip.lm6f.build.lwip_include=lwip2/include
+phoenix_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+phoenix_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+phoenix_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+phoenix_v1.menu.ip.hb6f.build.lwip_include=lwip2/include
+phoenix_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+phoenix_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+phoenix_v1.menu.ip.hb1=v1.4 Higher Bandwidth
+phoenix_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+phoenix_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+phoenix_v1.menu.ip.src=v1.4 Compile from source
+phoenix_v1.menu.ip.src.build.lwip_lib=-llwip_src
+phoenix_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+phoenix_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+phoenix_v1.menu.dbg.Disabled=Disabled
+phoenix_v1.menu.dbg.Disabled.build.debug_port=
+phoenix_v1.menu.dbg.Serial=Serial
+phoenix_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+phoenix_v1.menu.dbg.Serial1=Serial1
+phoenix_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+phoenix_v1.menu.lvl.None____=None
+phoenix_v1.menu.lvl.None____.build.debug_level=
+phoenix_v1.menu.lvl.SSL=SSL
+phoenix_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+phoenix_v1.menu.lvl.TLS_MEM=TLS_MEM
+phoenix_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+phoenix_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+phoenix_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+phoenix_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER
+phoenix_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+phoenix_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+phoenix_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+phoenix_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+phoenix_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+phoenix_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+phoenix_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+phoenix_v1.menu.lvl.CORE=CORE
+phoenix_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+phoenix_v1.menu.lvl.WIFI=WIFI
+phoenix_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+phoenix_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+phoenix_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+phoenix_v1.menu.lvl.UPDATER=UPDATER
+phoenix_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+phoenix_v1.menu.lvl.OTA=OTA
+phoenix_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+phoenix_v1.menu.lvl.OOM=OOM
+phoenix_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+phoenix_v1.menu.lvl.MDNS=MDNS
+phoenix_v1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+phoenix_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+phoenix_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+phoenix_v1.menu.wipe.none=Only Sketch
+phoenix_v1.menu.wipe.none.upload.erase_cmd=version
+phoenix_v1.menu.wipe.sdk=Sketch + WiFi Settings
+phoenix_v1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+phoenix_v1.menu.wipe.all=All Flash Contents
+phoenix_v1.menu.wipe.all.upload.erase_cmd=erase_flash
+phoenix_v1.menu.baud.115200=115200
+phoenix_v1.menu.baud.115200.upload.speed=115200
+phoenix_v1.menu.baud.57600=57600
+phoenix_v1.menu.baud.57600.upload.speed=57600
+phoenix_v1.menu.baud.230400.linux=230400
+phoenix_v1.menu.baud.230400.macosx=230400
+phoenix_v1.menu.baud.230400.upload.speed=230400
+phoenix_v1.menu.baud.256000.windows=256000
+phoenix_v1.menu.baud.256000.upload.speed=256000
+phoenix_v1.menu.baud.460800.linux=460800
+phoenix_v1.menu.baud.460800.macosx=460800
+phoenix_v1.menu.baud.460800.upload.speed=460800
+phoenix_v1.menu.baud.512000.windows=512000
+phoenix_v1.menu.baud.512000.upload.speed=512000
+phoenix_v1.menu.baud.921600=921600
+phoenix_v1.menu.baud.921600.upload.speed=921600
+phoenix_v1.menu.baud.3000000=3000000
+phoenix_v1.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+phoenix_v2.name=Phoenix 2.0
+phoenix_v2.build.board=ESP8266_PHOENIX_V2
+phoenix_v2.build.variant=phoenix_v2
+phoenix_v2.upload.tool=esptool
+phoenix_v2.upload.maximum_data_size=81920
+phoenix_v2.upload.wait_for_upload_port=true
+phoenix_v2.upload.erase_cmd=version
+phoenix_v2.serial.disableDTR=true
+phoenix_v2.serial.disableRTS=true
+phoenix_v2.build.mcu=esp8266
+phoenix_v2.build.core=esp8266
+phoenix_v2.build.spiffs_pagesize=256
+phoenix_v2.build.debug_port=
+phoenix_v2.build.debug_level=
+phoenix_v2.menu.xtal.80=80 MHz
+phoenix_v2.menu.xtal.80.build.f_cpu=80000000L
+phoenix_v2.menu.xtal.160=160 MHz
+phoenix_v2.menu.xtal.160.build.f_cpu=160000000L
+phoenix_v2.menu.vt.flash=Flash
+phoenix_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+phoenix_v2.menu.vt.heap=Heap
+phoenix_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+phoenix_v2.menu.vt.iram=IRAM
+phoenix_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+phoenix_v2.menu.exception.legacy=Legacy (new can return nullptr)
+phoenix_v2.menu.exception.legacy.build.exception_flags=-fno-exceptions
+phoenix_v2.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+phoenix_v2.menu.exception.disabled=Disabled (new can abort)
+phoenix_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+phoenix_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+phoenix_v2.menu.exception.enabled=Enabled
+phoenix_v2.menu.exception.enabled.build.exception_flags=-fexceptions
+phoenix_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+phoenix_v2.menu.ssl.all=All SSL ciphers (most compatible)
+phoenix_v2.menu.ssl.all.build.sslflags=
+phoenix_v2.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+phoenix_v2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+phoenix_v2.build.flash_mode=dio
+phoenix_v2.build.flash_flags=-DFLASHMODE_DIO
+phoenix_v2.build.flash_freq=40
+phoenix_v2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+phoenix_v2.menu.eesz.4M2M.build.flash_size=4M
+phoenix_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+phoenix_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+phoenix_v2.menu.eesz.4M2M.build.spiffs_pagesize=256
+phoenix_v2.menu.eesz.4M2M.upload.maximum_size=1044464
+phoenix_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+phoenix_v2.menu.eesz.4M2M.build.spiffs_start=0x200000
+phoenix_v2.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+phoenix_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192
+phoenix_v2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+phoenix_v2.menu.eesz.4M3M.build.flash_size=4M
+phoenix_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+phoenix_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+phoenix_v2.menu.eesz.4M3M.build.spiffs_pagesize=256
+phoenix_v2.menu.eesz.4M3M.upload.maximum_size=1044464
+phoenix_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+phoenix_v2.menu.eesz.4M3M.build.spiffs_start=0x100000
+phoenix_v2.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+phoenix_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192
+phoenix_v2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+phoenix_v2.menu.eesz.4M1M.build.flash_size=4M
+phoenix_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+phoenix_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+phoenix_v2.menu.eesz.4M1M.build.spiffs_pagesize=256
+phoenix_v2.menu.eesz.4M1M.upload.maximum_size=1044464
+phoenix_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+phoenix_v2.menu.eesz.4M1M.build.spiffs_start=0x300000
+phoenix_v2.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+phoenix_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192
+phoenix_v2.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+phoenix_v2.menu.eesz.4M.build.flash_size=4M
+phoenix_v2.menu.eesz.4M.build.flash_size_bytes=0x400000
+phoenix_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+phoenix_v2.menu.eesz.4M.build.spiffs_pagesize=256
+phoenix_v2.menu.eesz.4M.upload.maximum_size=1044464
+phoenix_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000
+phoenix_v2.menu.ResetMethod.ck=ck
+phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck
+phoenix_v2.menu.ResetMethod.nodemcu=nodemcu
+phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu
+phoenix_v2.menu.ip.lm2f=v2 Lower Memory
+phoenix_v2.menu.ip.lm2f.build.lwip_include=lwip2/include
+phoenix_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+phoenix_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+phoenix_v2.menu.ip.hb2f=v2 Higher Bandwidth
+phoenix_v2.menu.ip.hb2f.build.lwip_include=lwip2/include
+phoenix_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+phoenix_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+phoenix_v2.menu.ip.lm2n=v2 Lower Memory (no features)
+phoenix_v2.menu.ip.lm2n.build.lwip_include=lwip2/include
+phoenix_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+phoenix_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+phoenix_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+phoenix_v2.menu.ip.hb2n.build.lwip_include=lwip2/include
+phoenix_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+phoenix_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+phoenix_v2.menu.ip.lm6f=v2 IPv6 Lower Memory
+phoenix_v2.menu.ip.lm6f.build.lwip_include=lwip2/include
+phoenix_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+phoenix_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+phoenix_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+phoenix_v2.menu.ip.hb6f.build.lwip_include=lwip2/include
+phoenix_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+phoenix_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+phoenix_v2.menu.ip.hb1=v1.4 Higher Bandwidth
+phoenix_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+phoenix_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+phoenix_v2.menu.ip.src=v1.4 Compile from source
+phoenix_v2.menu.ip.src.build.lwip_lib=-llwip_src
+phoenix_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+phoenix_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+phoenix_v2.menu.dbg.Disabled=Disabled
+phoenix_v2.menu.dbg.Disabled.build.debug_port=
+phoenix_v2.menu.dbg.Serial=Serial
+phoenix_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+phoenix_v2.menu.dbg.Serial1=Serial1
+phoenix_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+phoenix_v2.menu.lvl.None____=None
+phoenix_v2.menu.lvl.None____.build.debug_level=
+phoenix_v2.menu.lvl.SSL=SSL
+phoenix_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+phoenix_v2.menu.lvl.TLS_MEM=TLS_MEM
+phoenix_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+phoenix_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+phoenix_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+phoenix_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER
+phoenix_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+phoenix_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+phoenix_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+phoenix_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+phoenix_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+phoenix_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+phoenix_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+phoenix_v2.menu.lvl.CORE=CORE
+phoenix_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+phoenix_v2.menu.lvl.WIFI=WIFI
+phoenix_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+phoenix_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+phoenix_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+phoenix_v2.menu.lvl.UPDATER=UPDATER
+phoenix_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+phoenix_v2.menu.lvl.OTA=OTA
+phoenix_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+phoenix_v2.menu.lvl.OOM=OOM
+phoenix_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+phoenix_v2.menu.lvl.MDNS=MDNS
+phoenix_v2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+phoenix_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+phoenix_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+phoenix_v2.menu.wipe.none=Only Sketch
+phoenix_v2.menu.wipe.none.upload.erase_cmd=version
+phoenix_v2.menu.wipe.sdk=Sketch + WiFi Settings
+phoenix_v2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+phoenix_v2.menu.wipe.all=All Flash Contents
+phoenix_v2.menu.wipe.all.upload.erase_cmd=erase_flash
+phoenix_v2.menu.baud.115200=115200
+phoenix_v2.menu.baud.115200.upload.speed=115200
+phoenix_v2.menu.baud.57600=57600
+phoenix_v2.menu.baud.57600.upload.speed=57600
+phoenix_v2.menu.baud.230400.linux=230400
+phoenix_v2.menu.baud.230400.macosx=230400
+phoenix_v2.menu.baud.230400.upload.speed=230400
+phoenix_v2.menu.baud.256000.windows=256000
+phoenix_v2.menu.baud.256000.upload.speed=256000
+phoenix_v2.menu.baud.460800.linux=460800
+phoenix_v2.menu.baud.460800.macosx=460800
+phoenix_v2.menu.baud.460800.upload.speed=460800
+phoenix_v2.menu.baud.512000.windows=512000
+phoenix_v2.menu.baud.512000.upload.speed=512000
+phoenix_v2.menu.baud.921600=921600
+phoenix_v2.menu.baud.921600.upload.speed=921600
+phoenix_v2.menu.baud.3000000=3000000
+phoenix_v2.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+nodemcu.name=NodeMCU 0.9 (ESP-12 Module)
+nodemcu.build.board=ESP8266_NODEMCU
+nodemcu.build.variant=nodemcu
+nodemcu.upload.tool=esptool
+nodemcu.upload.maximum_data_size=81920
+nodemcu.upload.wait_for_upload_port=true
+nodemcu.upload.erase_cmd=version
+nodemcu.serial.disableDTR=true
+nodemcu.serial.disableRTS=true
+nodemcu.build.mcu=esp8266
+nodemcu.build.core=esp8266
+nodemcu.build.spiffs_pagesize=256
+nodemcu.build.debug_port=
+nodemcu.build.debug_level=
+nodemcu.menu.xtal.80=80 MHz
+nodemcu.menu.xtal.80.build.f_cpu=80000000L
+nodemcu.menu.xtal.160=160 MHz
+nodemcu.menu.xtal.160.build.f_cpu=160000000L
+nodemcu.menu.vt.flash=Flash
+nodemcu.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+nodemcu.menu.vt.heap=Heap
+nodemcu.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+nodemcu.menu.vt.iram=IRAM
+nodemcu.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+nodemcu.menu.exception.legacy=Legacy (new can return nullptr)
+nodemcu.menu.exception.legacy.build.exception_flags=-fno-exceptions
+nodemcu.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+nodemcu.menu.exception.disabled=Disabled (new can abort)
+nodemcu.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+nodemcu.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+nodemcu.menu.exception.enabled=Enabled
+nodemcu.menu.exception.enabled.build.exception_flags=-fexceptions
+nodemcu.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+nodemcu.menu.ssl.all=All SSL ciphers (most compatible)
+nodemcu.menu.ssl.all.build.sslflags=
+nodemcu.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+nodemcu.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+nodemcu.upload.resetmethod=nodemcu
+nodemcu.build.flash_mode=qio
+nodemcu.build.flash_flags=-DFLASHMODE_QIO
+nodemcu.build.flash_freq=40
+nodemcu.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+nodemcu.menu.eesz.4M2M.build.flash_size=4M
+nodemcu.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+nodemcu.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+nodemcu.menu.eesz.4M2M.build.spiffs_pagesize=256
+nodemcu.menu.eesz.4M2M.upload.maximum_size=1044464
+nodemcu.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+nodemcu.menu.eesz.4M2M.build.spiffs_start=0x200000
+nodemcu.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+nodemcu.menu.eesz.4M2M.build.spiffs_blocksize=8192
+nodemcu.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+nodemcu.menu.eesz.4M3M.build.flash_size=4M
+nodemcu.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+nodemcu.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+nodemcu.menu.eesz.4M3M.build.spiffs_pagesize=256
+nodemcu.menu.eesz.4M3M.upload.maximum_size=1044464
+nodemcu.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+nodemcu.menu.eesz.4M3M.build.spiffs_start=0x100000
+nodemcu.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+nodemcu.menu.eesz.4M3M.build.spiffs_blocksize=8192
+nodemcu.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+nodemcu.menu.eesz.4M1M.build.flash_size=4M
+nodemcu.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+nodemcu.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+nodemcu.menu.eesz.4M1M.build.spiffs_pagesize=256
+nodemcu.menu.eesz.4M1M.upload.maximum_size=1044464
+nodemcu.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+nodemcu.menu.eesz.4M1M.build.spiffs_start=0x300000
+nodemcu.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+nodemcu.menu.eesz.4M1M.build.spiffs_blocksize=8192
+nodemcu.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+nodemcu.menu.eesz.4M.build.flash_size=4M
+nodemcu.menu.eesz.4M.build.flash_size_bytes=0x400000
+nodemcu.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+nodemcu.menu.eesz.4M.build.spiffs_pagesize=256
+nodemcu.menu.eesz.4M.upload.maximum_size=1044464
+nodemcu.menu.eesz.4M.build.rfcal_addr=0x3FC000
+nodemcu.menu.ip.lm2f=v2 Lower Memory
+nodemcu.menu.ip.lm2f.build.lwip_include=lwip2/include
+nodemcu.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+nodemcu.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+nodemcu.menu.ip.hb2f=v2 Higher Bandwidth
+nodemcu.menu.ip.hb2f.build.lwip_include=lwip2/include
+nodemcu.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+nodemcu.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+nodemcu.menu.ip.lm2n=v2 Lower Memory (no features)
+nodemcu.menu.ip.lm2n.build.lwip_include=lwip2/include
+nodemcu.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+nodemcu.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+nodemcu.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+nodemcu.menu.ip.hb2n.build.lwip_include=lwip2/include
+nodemcu.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+nodemcu.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+nodemcu.menu.ip.lm6f=v2 IPv6 Lower Memory
+nodemcu.menu.ip.lm6f.build.lwip_include=lwip2/include
+nodemcu.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+nodemcu.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+nodemcu.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+nodemcu.menu.ip.hb6f.build.lwip_include=lwip2/include
+nodemcu.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+nodemcu.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+nodemcu.menu.ip.hb1=v1.4 Higher Bandwidth
+nodemcu.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+nodemcu.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+nodemcu.menu.ip.src=v1.4 Compile from source
+nodemcu.menu.ip.src.build.lwip_lib=-llwip_src
+nodemcu.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+nodemcu.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+nodemcu.menu.dbg.Disabled=Disabled
+nodemcu.menu.dbg.Disabled.build.debug_port=
+nodemcu.menu.dbg.Serial=Serial
+nodemcu.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+nodemcu.menu.dbg.Serial1=Serial1
+nodemcu.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+nodemcu.menu.lvl.None____=None
+nodemcu.menu.lvl.None____.build.debug_level=
+nodemcu.menu.lvl.SSL=SSL
+nodemcu.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+nodemcu.menu.lvl.TLS_MEM=TLS_MEM
+nodemcu.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+nodemcu.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+nodemcu.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+nodemcu.menu.lvl.HTTP_SERVER=HTTP_SERVER
+nodemcu.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+nodemcu.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+nodemcu.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+nodemcu.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+nodemcu.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+nodemcu.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+nodemcu.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+nodemcu.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+nodemcu.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+nodemcu.menu.lvl.CORE=CORE
+nodemcu.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+nodemcu.menu.lvl.WIFI=WIFI
+nodemcu.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+nodemcu.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+nodemcu.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+nodemcu.menu.lvl.UPDATER=UPDATER
+nodemcu.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+nodemcu.menu.lvl.OTA=OTA
+nodemcu.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+nodemcu.menu.lvl.OOM=OOM
+nodemcu.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+nodemcu.menu.lvl.MDNS=MDNS
+nodemcu.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+nodemcu.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+nodemcu.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+nodemcu.menu.wipe.none=Only Sketch
+nodemcu.menu.wipe.none.upload.erase_cmd=version
+nodemcu.menu.wipe.sdk=Sketch + WiFi Settings
+nodemcu.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+nodemcu.menu.wipe.all=All Flash Contents
+nodemcu.menu.wipe.all.upload.erase_cmd=erase_flash
+nodemcu.menu.baud.115200=115200
+nodemcu.menu.baud.115200.upload.speed=115200
+nodemcu.menu.baud.57600=57600
+nodemcu.menu.baud.57600.upload.speed=57600
+nodemcu.menu.baud.230400.linux=230400
+nodemcu.menu.baud.230400.macosx=230400
+nodemcu.menu.baud.230400.upload.speed=230400
+nodemcu.menu.baud.256000.windows=256000
+nodemcu.menu.baud.256000.upload.speed=256000
+nodemcu.menu.baud.460800.linux=460800
+nodemcu.menu.baud.460800.macosx=460800
+nodemcu.menu.baud.460800.upload.speed=460800
+nodemcu.menu.baud.512000.windows=512000
+nodemcu.menu.baud.512000.upload.speed=512000
+nodemcu.menu.baud.921600=921600
+nodemcu.menu.baud.921600.upload.speed=921600
+nodemcu.menu.baud.3000000=3000000
+nodemcu.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module)
+nodemcuv2.build.board=ESP8266_NODEMCU
+nodemcuv2.build.variant=nodemcu
+nodemcuv2.upload.tool=esptool
+nodemcuv2.upload.maximum_data_size=81920
+nodemcuv2.upload.wait_for_upload_port=true
+nodemcuv2.upload.erase_cmd=version
+nodemcuv2.serial.disableDTR=true
+nodemcuv2.serial.disableRTS=true
+nodemcuv2.build.mcu=esp8266
+nodemcuv2.build.core=esp8266
+nodemcuv2.build.spiffs_pagesize=256
+nodemcuv2.build.debug_port=
+nodemcuv2.build.debug_level=
+nodemcuv2.menu.xtal.80=80 MHz
+nodemcuv2.menu.xtal.80.build.f_cpu=80000000L
+nodemcuv2.menu.xtal.160=160 MHz
+nodemcuv2.menu.xtal.160.build.f_cpu=160000000L
+nodemcuv2.menu.vt.flash=Flash
+nodemcuv2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+nodemcuv2.menu.vt.heap=Heap
+nodemcuv2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+nodemcuv2.menu.vt.iram=IRAM
+nodemcuv2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+nodemcuv2.menu.exception.legacy=Legacy (new can return nullptr)
+nodemcuv2.menu.exception.legacy.build.exception_flags=-fno-exceptions
+nodemcuv2.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+nodemcuv2.menu.exception.disabled=Disabled (new can abort)
+nodemcuv2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+nodemcuv2.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+nodemcuv2.menu.exception.enabled=Enabled
+nodemcuv2.menu.exception.enabled.build.exception_flags=-fexceptions
+nodemcuv2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+nodemcuv2.menu.ssl.all=All SSL ciphers (most compatible)
+nodemcuv2.menu.ssl.all.build.sslflags=
+nodemcuv2.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+nodemcuv2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+nodemcuv2.upload.resetmethod=nodemcu
+nodemcuv2.build.flash_mode=dio
+nodemcuv2.build.flash_flags=-DFLASHMODE_DIO
+nodemcuv2.build.flash_freq=40
+nodemcuv2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+nodemcuv2.menu.eesz.4M2M.build.flash_size=4M
+nodemcuv2.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+nodemcuv2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+nodemcuv2.menu.eesz.4M2M.build.spiffs_pagesize=256
+nodemcuv2.menu.eesz.4M2M.upload.maximum_size=1044464
+nodemcuv2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+nodemcuv2.menu.eesz.4M2M.build.spiffs_start=0x200000
+nodemcuv2.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+nodemcuv2.menu.eesz.4M2M.build.spiffs_blocksize=8192
+nodemcuv2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+nodemcuv2.menu.eesz.4M3M.build.flash_size=4M
+nodemcuv2.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+nodemcuv2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+nodemcuv2.menu.eesz.4M3M.build.spiffs_pagesize=256
+nodemcuv2.menu.eesz.4M3M.upload.maximum_size=1044464
+nodemcuv2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+nodemcuv2.menu.eesz.4M3M.build.spiffs_start=0x100000
+nodemcuv2.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+nodemcuv2.menu.eesz.4M3M.build.spiffs_blocksize=8192
+nodemcuv2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+nodemcuv2.menu.eesz.4M1M.build.flash_size=4M
+nodemcuv2.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+nodemcuv2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+nodemcuv2.menu.eesz.4M1M.build.spiffs_pagesize=256
+nodemcuv2.menu.eesz.4M1M.upload.maximum_size=1044464
+nodemcuv2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+nodemcuv2.menu.eesz.4M1M.build.spiffs_start=0x300000
+nodemcuv2.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+nodemcuv2.menu.eesz.4M1M.build.spiffs_blocksize=8192
+nodemcuv2.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+nodemcuv2.menu.eesz.4M.build.flash_size=4M
+nodemcuv2.menu.eesz.4M.build.flash_size_bytes=0x400000
+nodemcuv2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+nodemcuv2.menu.eesz.4M.build.spiffs_pagesize=256
+nodemcuv2.menu.eesz.4M.upload.maximum_size=1044464
+nodemcuv2.menu.eesz.4M.build.rfcal_addr=0x3FC000
+nodemcuv2.menu.ip.lm2f=v2 Lower Memory
+nodemcuv2.menu.ip.lm2f.build.lwip_include=lwip2/include
+nodemcuv2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+nodemcuv2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+nodemcuv2.menu.ip.hb2f=v2 Higher Bandwidth
+nodemcuv2.menu.ip.hb2f.build.lwip_include=lwip2/include
+nodemcuv2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+nodemcuv2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+nodemcuv2.menu.ip.lm2n=v2 Lower Memory (no features)
+nodemcuv2.menu.ip.lm2n.build.lwip_include=lwip2/include
+nodemcuv2.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+nodemcuv2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+nodemcuv2.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+nodemcuv2.menu.ip.hb2n.build.lwip_include=lwip2/include
+nodemcuv2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+nodemcuv2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+nodemcuv2.menu.ip.lm6f=v2 IPv6 Lower Memory
+nodemcuv2.menu.ip.lm6f.build.lwip_include=lwip2/include
+nodemcuv2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+nodemcuv2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+nodemcuv2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+nodemcuv2.menu.ip.hb6f.build.lwip_include=lwip2/include
+nodemcuv2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+nodemcuv2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+nodemcuv2.menu.ip.hb1=v1.4 Higher Bandwidth
+nodemcuv2.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+nodemcuv2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+nodemcuv2.menu.ip.src=v1.4 Compile from source
+nodemcuv2.menu.ip.src.build.lwip_lib=-llwip_src
+nodemcuv2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+nodemcuv2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+nodemcuv2.menu.dbg.Disabled=Disabled
+nodemcuv2.menu.dbg.Disabled.build.debug_port=
+nodemcuv2.menu.dbg.Serial=Serial
+nodemcuv2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+nodemcuv2.menu.dbg.Serial1=Serial1
+nodemcuv2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+nodemcuv2.menu.lvl.None____=None
+nodemcuv2.menu.lvl.None____.build.debug_level=
+nodemcuv2.menu.lvl.SSL=SSL
+nodemcuv2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+nodemcuv2.menu.lvl.TLS_MEM=TLS_MEM
+nodemcuv2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+nodemcuv2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+nodemcuv2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+nodemcuv2.menu.lvl.HTTP_SERVER=HTTP_SERVER
+nodemcuv2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+nodemcuv2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+nodemcuv2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+nodemcuv2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+nodemcuv2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+nodemcuv2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+nodemcuv2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+nodemcuv2.menu.lvl.CORE=CORE
+nodemcuv2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+nodemcuv2.menu.lvl.WIFI=WIFI
+nodemcuv2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+nodemcuv2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+nodemcuv2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+nodemcuv2.menu.lvl.UPDATER=UPDATER
+nodemcuv2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+nodemcuv2.menu.lvl.OTA=OTA
+nodemcuv2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+nodemcuv2.menu.lvl.OOM=OOM
+nodemcuv2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+nodemcuv2.menu.lvl.MDNS=MDNS
+nodemcuv2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+nodemcuv2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+nodemcuv2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+nodemcuv2.menu.wipe.none=Only Sketch
+nodemcuv2.menu.wipe.none.upload.erase_cmd=version
+nodemcuv2.menu.wipe.sdk=Sketch + WiFi Settings
+nodemcuv2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+nodemcuv2.menu.wipe.all=All Flash Contents
+nodemcuv2.menu.wipe.all.upload.erase_cmd=erase_flash
+nodemcuv2.menu.baud.115200=115200
+nodemcuv2.menu.baud.115200.upload.speed=115200
+nodemcuv2.menu.baud.57600=57600
+nodemcuv2.menu.baud.57600.upload.speed=57600
+nodemcuv2.menu.baud.230400.linux=230400
+nodemcuv2.menu.baud.230400.macosx=230400
+nodemcuv2.menu.baud.230400.upload.speed=230400
+nodemcuv2.menu.baud.256000.windows=256000
+nodemcuv2.menu.baud.256000.upload.speed=256000
+nodemcuv2.menu.baud.460800.linux=460800
+nodemcuv2.menu.baud.460800.macosx=460800
+nodemcuv2.menu.baud.460800.upload.speed=460800
+nodemcuv2.menu.baud.512000.windows=512000
+nodemcuv2.menu.baud.512000.upload.speed=512000
+nodemcuv2.menu.baud.921600=921600
+nodemcuv2.menu.baud.921600.upload.speed=921600
+nodemcuv2.menu.baud.3000000=3000000
+nodemcuv2.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV)
+modwifi.build.board=MOD_WIFI_ESP8266
+modwifi.build.variant=modwifi
+modwifi.upload.tool=esptool
+modwifi.upload.maximum_data_size=81920
+modwifi.upload.wait_for_upload_port=true
+modwifi.upload.erase_cmd=version
+modwifi.serial.disableDTR=true
+modwifi.serial.disableRTS=true
+modwifi.build.mcu=esp8266
+modwifi.build.core=esp8266
+modwifi.build.spiffs_pagesize=256
+modwifi.build.debug_port=
+modwifi.build.debug_level=
+modwifi.menu.xtal.80=80 MHz
+modwifi.menu.xtal.80.build.f_cpu=80000000L
+modwifi.menu.xtal.160=160 MHz
+modwifi.menu.xtal.160.build.f_cpu=160000000L
+modwifi.menu.vt.flash=Flash
+modwifi.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+modwifi.menu.vt.heap=Heap
+modwifi.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+modwifi.menu.vt.iram=IRAM
+modwifi.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+modwifi.menu.exception.legacy=Legacy (new can return nullptr)
+modwifi.menu.exception.legacy.build.exception_flags=-fno-exceptions
+modwifi.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+modwifi.menu.exception.disabled=Disabled (new can abort)
+modwifi.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+modwifi.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+modwifi.menu.exception.enabled=Enabled
+modwifi.menu.exception.enabled.build.exception_flags=-fexceptions
+modwifi.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+modwifi.menu.ssl.all=All SSL ciphers (most compatible)
+modwifi.menu.ssl.all.build.sslflags=
+modwifi.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+modwifi.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+modwifi.upload.resetmethod=ck
+modwifi.build.flash_mode=qio
+modwifi.build.flash_flags=-DFLASHMODE_QIO
+modwifi.build.flash_freq=40
+modwifi.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB)
+modwifi.menu.eesz.2M64.build.flash_size=2M
+modwifi.menu.eesz.2M64.build.flash_size_bytes=0x200000
+modwifi.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld
+modwifi.menu.eesz.2M64.build.spiffs_pagesize=256
+modwifi.menu.eesz.2M64.upload.maximum_size=1044464
+modwifi.menu.eesz.2M64.build.rfcal_addr=0x1FC000
+modwifi.menu.eesz.2M64.build.spiffs_start=0x1F0000
+modwifi.menu.eesz.2M64.build.spiffs_end=0x1FB000
+modwifi.menu.eesz.2M64.build.spiffs_blocksize=4096
+modwifi.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB)
+modwifi.menu.eesz.2M128.build.flash_size=2M
+modwifi.menu.eesz.2M128.build.flash_size_bytes=0x200000
+modwifi.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld
+modwifi.menu.eesz.2M128.build.spiffs_pagesize=256
+modwifi.menu.eesz.2M128.upload.maximum_size=1044464
+modwifi.menu.eesz.2M128.build.rfcal_addr=0x1FC000
+modwifi.menu.eesz.2M128.build.spiffs_start=0x1E0000
+modwifi.menu.eesz.2M128.build.spiffs_end=0x1FB000
+modwifi.menu.eesz.2M128.build.spiffs_blocksize=4096
+modwifi.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB)
+modwifi.menu.eesz.2M256.build.flash_size=2M
+modwifi.menu.eesz.2M256.build.flash_size_bytes=0x200000
+modwifi.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld
+modwifi.menu.eesz.2M256.build.spiffs_pagesize=256
+modwifi.menu.eesz.2M256.upload.maximum_size=1044464
+modwifi.menu.eesz.2M256.build.rfcal_addr=0x1FC000
+modwifi.menu.eesz.2M256.build.spiffs_start=0x1C0000
+modwifi.menu.eesz.2M256.build.spiffs_end=0x1FB000
+modwifi.menu.eesz.2M256.build.spiffs_blocksize=4096
+modwifi.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB)
+modwifi.menu.eesz.2M512.build.flash_size=2M
+modwifi.menu.eesz.2M512.build.flash_size_bytes=0x200000
+modwifi.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld
+modwifi.menu.eesz.2M512.build.spiffs_pagesize=256
+modwifi.menu.eesz.2M512.upload.maximum_size=1044464
+modwifi.menu.eesz.2M512.build.rfcal_addr=0x1FC000
+modwifi.menu.eesz.2M512.build.spiffs_start=0x180000
+modwifi.menu.eesz.2M512.build.spiffs_end=0x1FA000
+modwifi.menu.eesz.2M512.build.spiffs_blocksize=8192
+modwifi.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB)
+modwifi.menu.eesz.2M1M.build.flash_size=2M
+modwifi.menu.eesz.2M1M.build.flash_size_bytes=0x200000
+modwifi.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld
+modwifi.menu.eesz.2M1M.build.spiffs_pagesize=256
+modwifi.menu.eesz.2M1M.upload.maximum_size=1044464
+modwifi.menu.eesz.2M1M.build.rfcal_addr=0x1FC000
+modwifi.menu.eesz.2M1M.build.spiffs_start=0x100000
+modwifi.menu.eesz.2M1M.build.spiffs_end=0x1FA000
+modwifi.menu.eesz.2M1M.build.spiffs_blocksize=8192
+modwifi.menu.eesz.2M=2MB (FS:none OTA:~1019KB)
+modwifi.menu.eesz.2M.build.flash_size=2M
+modwifi.menu.eesz.2M.build.flash_size_bytes=0x200000
+modwifi.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld
+modwifi.menu.eesz.2M.build.spiffs_pagesize=256
+modwifi.menu.eesz.2M.upload.maximum_size=1044464
+modwifi.menu.eesz.2M.build.rfcal_addr=0x1FC000
+modwifi.menu.ip.lm2f=v2 Lower Memory
+modwifi.menu.ip.lm2f.build.lwip_include=lwip2/include
+modwifi.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+modwifi.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+modwifi.menu.ip.hb2f=v2 Higher Bandwidth
+modwifi.menu.ip.hb2f.build.lwip_include=lwip2/include
+modwifi.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+modwifi.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+modwifi.menu.ip.lm2n=v2 Lower Memory (no features)
+modwifi.menu.ip.lm2n.build.lwip_include=lwip2/include
+modwifi.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+modwifi.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+modwifi.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+modwifi.menu.ip.hb2n.build.lwip_include=lwip2/include
+modwifi.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+modwifi.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+modwifi.menu.ip.lm6f=v2 IPv6 Lower Memory
+modwifi.menu.ip.lm6f.build.lwip_include=lwip2/include
+modwifi.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+modwifi.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+modwifi.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+modwifi.menu.ip.hb6f.build.lwip_include=lwip2/include
+modwifi.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+modwifi.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+modwifi.menu.ip.hb1=v1.4 Higher Bandwidth
+modwifi.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+modwifi.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+modwifi.menu.ip.src=v1.4 Compile from source
+modwifi.menu.ip.src.build.lwip_lib=-llwip_src
+modwifi.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+modwifi.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+modwifi.menu.dbg.Disabled=Disabled
+modwifi.menu.dbg.Disabled.build.debug_port=
+modwifi.menu.dbg.Serial=Serial
+modwifi.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+modwifi.menu.dbg.Serial1=Serial1
+modwifi.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+modwifi.menu.lvl.None____=None
+modwifi.menu.lvl.None____.build.debug_level=
+modwifi.menu.lvl.SSL=SSL
+modwifi.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+modwifi.menu.lvl.TLS_MEM=TLS_MEM
+modwifi.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+modwifi.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+modwifi.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+modwifi.menu.lvl.HTTP_SERVER=HTTP_SERVER
+modwifi.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+modwifi.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+modwifi.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+modwifi.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+modwifi.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+modwifi.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+modwifi.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+modwifi.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+modwifi.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+modwifi.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+modwifi.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+modwifi.menu.lvl.CORE=CORE
+modwifi.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+modwifi.menu.lvl.WIFI=WIFI
+modwifi.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+modwifi.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+modwifi.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+modwifi.menu.lvl.UPDATER=UPDATER
+modwifi.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+modwifi.menu.lvl.OTA=OTA
+modwifi.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+modwifi.menu.lvl.OOM=OOM
+modwifi.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+modwifi.menu.lvl.MDNS=MDNS
+modwifi.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+modwifi.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+modwifi.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+modwifi.menu.wipe.none=Only Sketch
+modwifi.menu.wipe.none.upload.erase_cmd=version
+modwifi.menu.wipe.sdk=Sketch + WiFi Settings
+modwifi.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+modwifi.menu.wipe.all=All Flash Contents
+modwifi.menu.wipe.all.upload.erase_cmd=erase_flash
+modwifi.menu.baud.115200=115200
+modwifi.menu.baud.115200.upload.speed=115200
+modwifi.menu.baud.57600=57600
+modwifi.menu.baud.57600.upload.speed=57600
+modwifi.menu.baud.230400.linux=230400
+modwifi.menu.baud.230400.macosx=230400
+modwifi.menu.baud.230400.upload.speed=230400
+modwifi.menu.baud.256000.windows=256000
+modwifi.menu.baud.256000.upload.speed=256000
+modwifi.menu.baud.460800.linux=460800
+modwifi.menu.baud.460800.macosx=460800
+modwifi.menu.baud.460800.upload.speed=460800
+modwifi.menu.baud.512000.windows=512000
+modwifi.menu.baud.512000.upload.speed=512000
+modwifi.menu.baud.921600=921600
+modwifi.menu.baud.921600.upload.speed=921600
+modwifi.menu.baud.3000000=3000000
+modwifi.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+thing.name=SparkFun ESP8266 Thing
+thing.build.board=ESP8266_THING
+thing.build.variant=thing
+thing.upload.tool=esptool
+thing.upload.maximum_data_size=81920
+thing.upload.wait_for_upload_port=true
+thing.upload.erase_cmd=version
+thing.serial.disableDTR=true
+thing.serial.disableRTS=true
+thing.build.mcu=esp8266
+thing.build.core=esp8266
+thing.build.spiffs_pagesize=256
+thing.build.debug_port=
+thing.build.debug_level=
+thing.menu.xtal.80=80 MHz
+thing.menu.xtal.80.build.f_cpu=80000000L
+thing.menu.xtal.160=160 MHz
+thing.menu.xtal.160.build.f_cpu=160000000L
+thing.menu.vt.flash=Flash
+thing.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+thing.menu.vt.heap=Heap
+thing.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+thing.menu.vt.iram=IRAM
+thing.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+thing.menu.exception.legacy=Legacy (new can return nullptr)
+thing.menu.exception.legacy.build.exception_flags=-fno-exceptions
+thing.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+thing.menu.exception.disabled=Disabled (new can abort)
+thing.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+thing.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+thing.menu.exception.enabled=Enabled
+thing.menu.exception.enabled.build.exception_flags=-fexceptions
+thing.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+thing.menu.ssl.all=All SSL ciphers (most compatible)
+thing.menu.ssl.all.build.sslflags=
+thing.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+thing.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+thing.upload.resetmethod=ck
+thing.build.flash_mode=qio
+thing.build.flash_flags=-DFLASHMODE_QIO
+thing.build.flash_freq=40
+thing.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB)
+thing.menu.eesz.512K32.build.flash_size=512K
+thing.menu.eesz.512K32.build.flash_size_bytes=0x80000
+thing.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld
+thing.menu.eesz.512K32.build.spiffs_pagesize=256
+thing.menu.eesz.512K32.upload.maximum_size=466928
+thing.menu.eesz.512K32.build.rfcal_addr=0x7C000
+thing.menu.eesz.512K32.build.spiffs_start=0x73000
+thing.menu.eesz.512K32.build.spiffs_end=0x7B000
+thing.menu.eesz.512K32.build.spiffs_blocksize=4096
+thing.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB)
+thing.menu.eesz.512K64.build.flash_size=512K
+thing.menu.eesz.512K64.build.flash_size_bytes=0x80000
+thing.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld
+thing.menu.eesz.512K64.build.spiffs_pagesize=256
+thing.menu.eesz.512K64.upload.maximum_size=434160
+thing.menu.eesz.512K64.build.rfcal_addr=0x7C000
+thing.menu.eesz.512K64.build.spiffs_start=0x6B000
+thing.menu.eesz.512K64.build.spiffs_end=0x7B000
+thing.menu.eesz.512K64.build.spiffs_blocksize=4096
+thing.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB)
+thing.menu.eesz.512K128.build.flash_size=512K
+thing.menu.eesz.512K128.build.flash_size_bytes=0x80000
+thing.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld
+thing.menu.eesz.512K128.build.spiffs_pagesize=256
+thing.menu.eesz.512K128.upload.maximum_size=368624
+thing.menu.eesz.512K128.build.rfcal_addr=0x7C000
+thing.menu.eesz.512K128.build.spiffs_start=0x5B000
+thing.menu.eesz.512K128.build.spiffs_end=0x7B000
+thing.menu.eesz.512K128.build.spiffs_blocksize=4096
+thing.menu.eesz.512K=512KB (FS:none OTA:~246KB)
+thing.menu.eesz.512K.build.flash_size=512K
+thing.menu.eesz.512K.build.flash_size_bytes=0x80000
+thing.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld
+thing.menu.eesz.512K.build.spiffs_pagesize=256
+thing.menu.eesz.512K.upload.maximum_size=499696
+thing.menu.eesz.512K.build.rfcal_addr=0x7C000
+thing.menu.ip.lm2f=v2 Lower Memory
+thing.menu.ip.lm2f.build.lwip_include=lwip2/include
+thing.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+thing.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+thing.menu.ip.hb2f=v2 Higher Bandwidth
+thing.menu.ip.hb2f.build.lwip_include=lwip2/include
+thing.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+thing.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+thing.menu.ip.lm2n=v2 Lower Memory (no features)
+thing.menu.ip.lm2n.build.lwip_include=lwip2/include
+thing.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+thing.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+thing.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+thing.menu.ip.hb2n.build.lwip_include=lwip2/include
+thing.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+thing.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+thing.menu.ip.lm6f=v2 IPv6 Lower Memory
+thing.menu.ip.lm6f.build.lwip_include=lwip2/include
+thing.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+thing.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+thing.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+thing.menu.ip.hb6f.build.lwip_include=lwip2/include
+thing.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+thing.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+thing.menu.ip.hb1=v1.4 Higher Bandwidth
+thing.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+thing.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+thing.menu.ip.src=v1.4 Compile from source
+thing.menu.ip.src.build.lwip_lib=-llwip_src
+thing.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+thing.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+thing.menu.dbg.Disabled=Disabled
+thing.menu.dbg.Disabled.build.debug_port=
+thing.menu.dbg.Serial=Serial
+thing.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+thing.menu.dbg.Serial1=Serial1
+thing.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+thing.menu.lvl.None____=None
+thing.menu.lvl.None____.build.debug_level=
+thing.menu.lvl.SSL=SSL
+thing.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+thing.menu.lvl.TLS_MEM=TLS_MEM
+thing.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+thing.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+thing.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+thing.menu.lvl.HTTP_SERVER=HTTP_SERVER
+thing.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+thing.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+thing.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+thing.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+thing.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+thing.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+thing.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+thing.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+thing.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+thing.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+thing.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+thing.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+thing.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+thing.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+thing.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+thing.menu.lvl.CORE=CORE
+thing.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+thing.menu.lvl.WIFI=WIFI
+thing.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+thing.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+thing.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+thing.menu.lvl.UPDATER=UPDATER
+thing.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+thing.menu.lvl.OTA=OTA
+thing.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+thing.menu.lvl.OOM=OOM
+thing.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+thing.menu.lvl.MDNS=MDNS
+thing.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+thing.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+thing.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+thing.menu.wipe.none=Only Sketch
+thing.menu.wipe.none.upload.erase_cmd=version
+thing.menu.wipe.sdk=Sketch + WiFi Settings
+thing.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+thing.menu.wipe.all=All Flash Contents
+thing.menu.wipe.all.upload.erase_cmd=erase_flash
+thing.menu.baud.115200=115200
+thing.menu.baud.115200.upload.speed=115200
+thing.menu.baud.57600=57600
+thing.menu.baud.57600.upload.speed=57600
+thing.menu.baud.230400.linux=230400
+thing.menu.baud.230400.macosx=230400
+thing.menu.baud.230400.upload.speed=230400
+thing.menu.baud.256000.windows=256000
+thing.menu.baud.256000.upload.speed=256000
+thing.menu.baud.460800.linux=460800
+thing.menu.baud.460800.macosx=460800
+thing.menu.baud.460800.upload.speed=460800
+thing.menu.baud.512000.windows=512000
+thing.menu.baud.512000.upload.speed=512000
+thing.menu.baud.921600=921600
+thing.menu.baud.921600.upload.speed=921600
+thing.menu.baud.3000000=3000000
+thing.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+thingdev.name=SparkFun ESP8266 Thing Dev
+thingdev.build.board=ESP8266_THING_DEV
+thingdev.build.variant=thing
+thingdev.upload.tool=esptool
+thingdev.upload.maximum_data_size=81920
+thingdev.upload.wait_for_upload_port=true
+thingdev.upload.erase_cmd=version
+thingdev.serial.disableDTR=true
+thingdev.serial.disableRTS=true
+thingdev.build.mcu=esp8266
+thingdev.build.core=esp8266
+thingdev.build.spiffs_pagesize=256
+thingdev.build.debug_port=
+thingdev.build.debug_level=
+thingdev.menu.xtal.80=80 MHz
+thingdev.menu.xtal.80.build.f_cpu=80000000L
+thingdev.menu.xtal.160=160 MHz
+thingdev.menu.xtal.160.build.f_cpu=160000000L
+thingdev.menu.vt.flash=Flash
+thingdev.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+thingdev.menu.vt.heap=Heap
+thingdev.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+thingdev.menu.vt.iram=IRAM
+thingdev.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+thingdev.menu.exception.legacy=Legacy (new can return nullptr)
+thingdev.menu.exception.legacy.build.exception_flags=-fno-exceptions
+thingdev.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+thingdev.menu.exception.disabled=Disabled (new can abort)
+thingdev.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+thingdev.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+thingdev.menu.exception.enabled=Enabled
+thingdev.menu.exception.enabled.build.exception_flags=-fexceptions
+thingdev.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+thingdev.menu.ssl.all=All SSL ciphers (most compatible)
+thingdev.menu.ssl.all.build.sslflags=
+thingdev.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+thingdev.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+thingdev.upload.resetmethod=nodemcu
+thingdev.build.flash_mode=dio
+thingdev.build.flash_flags=-DFLASHMODE_DIO
+thingdev.build.flash_freq=40
+thingdev.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB)
+thingdev.menu.eesz.512K32.build.flash_size=512K
+thingdev.menu.eesz.512K32.build.flash_size_bytes=0x80000
+thingdev.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld
+thingdev.menu.eesz.512K32.build.spiffs_pagesize=256
+thingdev.menu.eesz.512K32.upload.maximum_size=466928
+thingdev.menu.eesz.512K32.build.rfcal_addr=0x7C000
+thingdev.menu.eesz.512K32.build.spiffs_start=0x73000
+thingdev.menu.eesz.512K32.build.spiffs_end=0x7B000
+thingdev.menu.eesz.512K32.build.spiffs_blocksize=4096
+thingdev.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB)
+thingdev.menu.eesz.512K64.build.flash_size=512K
+thingdev.menu.eesz.512K64.build.flash_size_bytes=0x80000
+thingdev.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld
+thingdev.menu.eesz.512K64.build.spiffs_pagesize=256
+thingdev.menu.eesz.512K64.upload.maximum_size=434160
+thingdev.menu.eesz.512K64.build.rfcal_addr=0x7C000
+thingdev.menu.eesz.512K64.build.spiffs_start=0x6B000
+thingdev.menu.eesz.512K64.build.spiffs_end=0x7B000
+thingdev.menu.eesz.512K64.build.spiffs_blocksize=4096
+thingdev.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB)
+thingdev.menu.eesz.512K128.build.flash_size=512K
+thingdev.menu.eesz.512K128.build.flash_size_bytes=0x80000
+thingdev.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld
+thingdev.menu.eesz.512K128.build.spiffs_pagesize=256
+thingdev.menu.eesz.512K128.upload.maximum_size=368624
+thingdev.menu.eesz.512K128.build.rfcal_addr=0x7C000
+thingdev.menu.eesz.512K128.build.spiffs_start=0x5B000
+thingdev.menu.eesz.512K128.build.spiffs_end=0x7B000
+thingdev.menu.eesz.512K128.build.spiffs_blocksize=4096
+thingdev.menu.eesz.512K=512KB (FS:none OTA:~246KB)
+thingdev.menu.eesz.512K.build.flash_size=512K
+thingdev.menu.eesz.512K.build.flash_size_bytes=0x80000
+thingdev.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld
+thingdev.menu.eesz.512K.build.spiffs_pagesize=256
+thingdev.menu.eesz.512K.upload.maximum_size=499696
+thingdev.menu.eesz.512K.build.rfcal_addr=0x7C000
+thingdev.menu.ip.lm2f=v2 Lower Memory
+thingdev.menu.ip.lm2f.build.lwip_include=lwip2/include
+thingdev.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+thingdev.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+thingdev.menu.ip.hb2f=v2 Higher Bandwidth
+thingdev.menu.ip.hb2f.build.lwip_include=lwip2/include
+thingdev.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+thingdev.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+thingdev.menu.ip.lm2n=v2 Lower Memory (no features)
+thingdev.menu.ip.lm2n.build.lwip_include=lwip2/include
+thingdev.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+thingdev.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+thingdev.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+thingdev.menu.ip.hb2n.build.lwip_include=lwip2/include
+thingdev.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+thingdev.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+thingdev.menu.ip.lm6f=v2 IPv6 Lower Memory
+thingdev.menu.ip.lm6f.build.lwip_include=lwip2/include
+thingdev.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+thingdev.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+thingdev.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+thingdev.menu.ip.hb6f.build.lwip_include=lwip2/include
+thingdev.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+thingdev.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+thingdev.menu.ip.hb1=v1.4 Higher Bandwidth
+thingdev.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+thingdev.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+thingdev.menu.ip.src=v1.4 Compile from source
+thingdev.menu.ip.src.build.lwip_lib=-llwip_src
+thingdev.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+thingdev.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+thingdev.menu.dbg.Disabled=Disabled
+thingdev.menu.dbg.Disabled.build.debug_port=
+thingdev.menu.dbg.Serial=Serial
+thingdev.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+thingdev.menu.dbg.Serial1=Serial1
+thingdev.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+thingdev.menu.lvl.None____=None
+thingdev.menu.lvl.None____.build.debug_level=
+thingdev.menu.lvl.SSL=SSL
+thingdev.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+thingdev.menu.lvl.TLS_MEM=TLS_MEM
+thingdev.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+thingdev.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+thingdev.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+thingdev.menu.lvl.HTTP_SERVER=HTTP_SERVER
+thingdev.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+thingdev.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+thingdev.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+thingdev.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+thingdev.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+thingdev.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+thingdev.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+thingdev.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+thingdev.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+thingdev.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+thingdev.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+thingdev.menu.lvl.CORE=CORE
+thingdev.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+thingdev.menu.lvl.WIFI=WIFI
+thingdev.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+thingdev.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+thingdev.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+thingdev.menu.lvl.UPDATER=UPDATER
+thingdev.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+thingdev.menu.lvl.OTA=OTA
+thingdev.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+thingdev.menu.lvl.OOM=OOM
+thingdev.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+thingdev.menu.lvl.MDNS=MDNS
+thingdev.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+thingdev.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+thingdev.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+thingdev.menu.wipe.none=Only Sketch
+thingdev.menu.wipe.none.upload.erase_cmd=version
+thingdev.menu.wipe.sdk=Sketch + WiFi Settings
+thingdev.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+thingdev.menu.wipe.all=All Flash Contents
+thingdev.menu.wipe.all.upload.erase_cmd=erase_flash
+thingdev.menu.baud.115200=115200
+thingdev.menu.baud.115200.upload.speed=115200
+thingdev.menu.baud.57600=57600
+thingdev.menu.baud.57600.upload.speed=57600
+thingdev.menu.baud.230400.linux=230400
+thingdev.menu.baud.230400.macosx=230400
+thingdev.menu.baud.230400.upload.speed=230400
+thingdev.menu.baud.256000.windows=256000
+thingdev.menu.baud.256000.upload.speed=256000
+thingdev.menu.baud.460800.linux=460800
+thingdev.menu.baud.460800.macosx=460800
+thingdev.menu.baud.460800.upload.speed=460800
+thingdev.menu.baud.512000.windows=512000
+thingdev.menu.baud.512000.upload.speed=512000
+thingdev.menu.baud.921600=921600
+thingdev.menu.baud.921600.upload.speed=921600
+thingdev.menu.baud.3000000=3000000
+thingdev.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+esp210.name=SweetPea ESP-210
+esp210.build.board=ESP8266_ESP210
+esp210.upload.tool=esptool
+esp210.upload.maximum_data_size=81920
+esp210.upload.wait_for_upload_port=true
+esp210.upload.erase_cmd=version
+esp210.serial.disableDTR=true
+esp210.serial.disableRTS=true
+esp210.build.mcu=esp8266
+esp210.build.core=esp8266
+esp210.build.variant=generic
+esp210.build.spiffs_pagesize=256
+esp210.build.debug_port=
+esp210.build.debug_level=
+esp210.menu.xtal.80=80 MHz
+esp210.menu.xtal.80.build.f_cpu=80000000L
+esp210.menu.xtal.160=160 MHz
+esp210.menu.xtal.160.build.f_cpu=160000000L
+esp210.menu.vt.flash=Flash
+esp210.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+esp210.menu.vt.heap=Heap
+esp210.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+esp210.menu.vt.iram=IRAM
+esp210.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+esp210.menu.exception.legacy=Legacy (new can return nullptr)
+esp210.menu.exception.legacy.build.exception_flags=-fno-exceptions
+esp210.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+esp210.menu.exception.disabled=Disabled (new can abort)
+esp210.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+esp210.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+esp210.menu.exception.enabled=Enabled
+esp210.menu.exception.enabled.build.exception_flags=-fexceptions
+esp210.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+esp210.menu.ssl.all=All SSL ciphers (most compatible)
+esp210.menu.ssl.all.build.sslflags=
+esp210.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+esp210.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+esp210.upload.resetmethod=ck
+esp210.build.flash_mode=qio
+esp210.build.flash_flags=-DFLASHMODE_QIO
+esp210.build.flash_freq=40
+esp210.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+esp210.menu.eesz.4M2M.build.flash_size=4M
+esp210.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+esp210.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+esp210.menu.eesz.4M2M.build.spiffs_pagesize=256
+esp210.menu.eesz.4M2M.upload.maximum_size=1044464
+esp210.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+esp210.menu.eesz.4M2M.build.spiffs_start=0x200000
+esp210.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+esp210.menu.eesz.4M2M.build.spiffs_blocksize=8192
+esp210.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+esp210.menu.eesz.4M3M.build.flash_size=4M
+esp210.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+esp210.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+esp210.menu.eesz.4M3M.build.spiffs_pagesize=256
+esp210.menu.eesz.4M3M.upload.maximum_size=1044464
+esp210.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+esp210.menu.eesz.4M3M.build.spiffs_start=0x100000
+esp210.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+esp210.menu.eesz.4M3M.build.spiffs_blocksize=8192
+esp210.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+esp210.menu.eesz.4M1M.build.flash_size=4M
+esp210.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+esp210.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+esp210.menu.eesz.4M1M.build.spiffs_pagesize=256
+esp210.menu.eesz.4M1M.upload.maximum_size=1044464
+esp210.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+esp210.menu.eesz.4M1M.build.spiffs_start=0x300000
+esp210.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+esp210.menu.eesz.4M1M.build.spiffs_blocksize=8192
+esp210.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+esp210.menu.eesz.4M.build.flash_size=4M
+esp210.menu.eesz.4M.build.flash_size_bytes=0x400000
+esp210.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+esp210.menu.eesz.4M.build.spiffs_pagesize=256
+esp210.menu.eesz.4M.upload.maximum_size=1044464
+esp210.menu.eesz.4M.build.rfcal_addr=0x3FC000
+esp210.menu.ip.lm2f=v2 Lower Memory
+esp210.menu.ip.lm2f.build.lwip_include=lwip2/include
+esp210.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+esp210.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+esp210.menu.ip.hb2f=v2 Higher Bandwidth
+esp210.menu.ip.hb2f.build.lwip_include=lwip2/include
+esp210.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+esp210.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+esp210.menu.ip.lm2n=v2 Lower Memory (no features)
+esp210.menu.ip.lm2n.build.lwip_include=lwip2/include
+esp210.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+esp210.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+esp210.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+esp210.menu.ip.hb2n.build.lwip_include=lwip2/include
+esp210.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+esp210.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+esp210.menu.ip.lm6f=v2 IPv6 Lower Memory
+esp210.menu.ip.lm6f.build.lwip_include=lwip2/include
+esp210.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+esp210.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+esp210.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+esp210.menu.ip.hb6f.build.lwip_include=lwip2/include
+esp210.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+esp210.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+esp210.menu.ip.hb1=v1.4 Higher Bandwidth
+esp210.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+esp210.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+esp210.menu.ip.src=v1.4 Compile from source
+esp210.menu.ip.src.build.lwip_lib=-llwip_src
+esp210.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+esp210.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+esp210.menu.dbg.Disabled=Disabled
+esp210.menu.dbg.Disabled.build.debug_port=
+esp210.menu.dbg.Serial=Serial
+esp210.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+esp210.menu.dbg.Serial1=Serial1
+esp210.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+esp210.menu.lvl.None____=None
+esp210.menu.lvl.None____.build.debug_level=
+esp210.menu.lvl.SSL=SSL
+esp210.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+esp210.menu.lvl.TLS_MEM=TLS_MEM
+esp210.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+esp210.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+esp210.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+esp210.menu.lvl.HTTP_SERVER=HTTP_SERVER
+esp210.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+esp210.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+esp210.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+esp210.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+esp210.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+esp210.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+esp210.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+esp210.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+esp210.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+esp210.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+esp210.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+esp210.menu.lvl.CORE=CORE
+esp210.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+esp210.menu.lvl.WIFI=WIFI
+esp210.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+esp210.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+esp210.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+esp210.menu.lvl.UPDATER=UPDATER
+esp210.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+esp210.menu.lvl.OTA=OTA
+esp210.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+esp210.menu.lvl.OOM=OOM
+esp210.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+esp210.menu.lvl.MDNS=MDNS
+esp210.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+esp210.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+esp210.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+esp210.menu.wipe.none=Only Sketch
+esp210.menu.wipe.none.upload.erase_cmd=version
+esp210.menu.wipe.sdk=Sketch + WiFi Settings
+esp210.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+esp210.menu.wipe.all=All Flash Contents
+esp210.menu.wipe.all.upload.erase_cmd=erase_flash
+esp210.menu.baud.57600=57600
+esp210.menu.baud.57600.upload.speed=57600
+esp210.menu.baud.115200=115200
+esp210.menu.baud.115200.upload.speed=115200
+esp210.menu.baud.230400.linux=230400
+esp210.menu.baud.230400.macosx=230400
+esp210.menu.baud.230400.upload.speed=230400
+esp210.menu.baud.256000.windows=256000
+esp210.menu.baud.256000.upload.speed=256000
+esp210.menu.baud.460800.linux=460800
+esp210.menu.baud.460800.macosx=460800
+esp210.menu.baud.460800.upload.speed=460800
+esp210.menu.baud.512000.windows=512000
+esp210.menu.baud.512000.upload.speed=512000
+esp210.menu.baud.921600=921600
+esp210.menu.baud.921600.upload.speed=921600
+esp210.menu.baud.3000000=3000000
+esp210.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+d1_mini.name=LOLIN(WEMOS) D1 R2 & mini
+d1_mini.build.board=ESP8266_WEMOS_D1MINI
+d1_mini.build.variant=d1_mini
+d1_mini.upload.tool=esptool
+d1_mini.upload.maximum_data_size=81920
+d1_mini.upload.wait_for_upload_port=true
+d1_mini.upload.erase_cmd=version
+d1_mini.serial.disableDTR=true
+d1_mini.serial.disableRTS=true
+d1_mini.build.mcu=esp8266
+d1_mini.build.core=esp8266
+d1_mini.build.spiffs_pagesize=256
+d1_mini.build.debug_port=
+d1_mini.build.debug_level=
+d1_mini.menu.xtal.80=80 MHz
+d1_mini.menu.xtal.80.build.f_cpu=80000000L
+d1_mini.menu.xtal.160=160 MHz
+d1_mini.menu.xtal.160.build.f_cpu=160000000L
+d1_mini.menu.vt.flash=Flash
+d1_mini.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+d1_mini.menu.vt.heap=Heap
+d1_mini.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+d1_mini.menu.vt.iram=IRAM
+d1_mini.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+d1_mini.menu.exception.legacy=Legacy (new can return nullptr)
+d1_mini.menu.exception.legacy.build.exception_flags=-fno-exceptions
+d1_mini.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+d1_mini.menu.exception.disabled=Disabled (new can abort)
+d1_mini.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+d1_mini.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+d1_mini.menu.exception.enabled=Enabled
+d1_mini.menu.exception.enabled.build.exception_flags=-fexceptions
+d1_mini.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+d1_mini.menu.ssl.all=All SSL ciphers (most compatible)
+d1_mini.menu.ssl.all.build.sslflags=
+d1_mini.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+d1_mini.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+d1_mini.upload.resetmethod=nodemcu
+d1_mini.build.flash_mode=dio
+d1_mini.build.flash_flags=-DFLASHMODE_DIO
+d1_mini.build.flash_freq=40
+d1_mini.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+d1_mini.menu.eesz.4M2M.build.flash_size=4M
+d1_mini.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+d1_mini.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+d1_mini.menu.eesz.4M2M.build.spiffs_pagesize=256
+d1_mini.menu.eesz.4M2M.upload.maximum_size=1044464
+d1_mini.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+d1_mini.menu.eesz.4M2M.build.spiffs_start=0x200000
+d1_mini.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+d1_mini.menu.eesz.4M2M.build.spiffs_blocksize=8192
+d1_mini.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+d1_mini.menu.eesz.4M3M.build.flash_size=4M
+d1_mini.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+d1_mini.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+d1_mini.menu.eesz.4M3M.build.spiffs_pagesize=256
+d1_mini.menu.eesz.4M3M.upload.maximum_size=1044464
+d1_mini.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+d1_mini.menu.eesz.4M3M.build.spiffs_start=0x100000
+d1_mini.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+d1_mini.menu.eesz.4M3M.build.spiffs_blocksize=8192
+d1_mini.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+d1_mini.menu.eesz.4M1M.build.flash_size=4M
+d1_mini.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+d1_mini.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+d1_mini.menu.eesz.4M1M.build.spiffs_pagesize=256
+d1_mini.menu.eesz.4M1M.upload.maximum_size=1044464
+d1_mini.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+d1_mini.menu.eesz.4M1M.build.spiffs_start=0x300000
+d1_mini.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+d1_mini.menu.eesz.4M1M.build.spiffs_blocksize=8192
+d1_mini.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+d1_mini.menu.eesz.4M.build.flash_size=4M
+d1_mini.menu.eesz.4M.build.flash_size_bytes=0x400000
+d1_mini.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+d1_mini.menu.eesz.4M.build.spiffs_pagesize=256
+d1_mini.menu.eesz.4M.upload.maximum_size=1044464
+d1_mini.menu.eesz.4M.build.rfcal_addr=0x3FC000
+d1_mini.menu.ip.lm2f=v2 Lower Memory
+d1_mini.menu.ip.lm2f.build.lwip_include=lwip2/include
+d1_mini.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+d1_mini.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+d1_mini.menu.ip.hb2f=v2 Higher Bandwidth
+d1_mini.menu.ip.hb2f.build.lwip_include=lwip2/include
+d1_mini.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+d1_mini.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+d1_mini.menu.ip.lm2n=v2 Lower Memory (no features)
+d1_mini.menu.ip.lm2n.build.lwip_include=lwip2/include
+d1_mini.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+d1_mini.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+d1_mini.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+d1_mini.menu.ip.hb2n.build.lwip_include=lwip2/include
+d1_mini.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+d1_mini.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+d1_mini.menu.ip.lm6f=v2 IPv6 Lower Memory
+d1_mini.menu.ip.lm6f.build.lwip_include=lwip2/include
+d1_mini.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+d1_mini.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+d1_mini.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+d1_mini.menu.ip.hb6f.build.lwip_include=lwip2/include
+d1_mini.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+d1_mini.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+d1_mini.menu.ip.hb1=v1.4 Higher Bandwidth
+d1_mini.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+d1_mini.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+d1_mini.menu.ip.src=v1.4 Compile from source
+d1_mini.menu.ip.src.build.lwip_lib=-llwip_src
+d1_mini.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+d1_mini.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+d1_mini.menu.dbg.Disabled=Disabled
+d1_mini.menu.dbg.Disabled.build.debug_port=
+d1_mini.menu.dbg.Serial=Serial
+d1_mini.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+d1_mini.menu.dbg.Serial1=Serial1
+d1_mini.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+d1_mini.menu.lvl.None____=None
+d1_mini.menu.lvl.None____.build.debug_level=
+d1_mini.menu.lvl.SSL=SSL
+d1_mini.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+d1_mini.menu.lvl.TLS_MEM=TLS_MEM
+d1_mini.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+d1_mini.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+d1_mini.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+d1_mini.menu.lvl.HTTP_SERVER=HTTP_SERVER
+d1_mini.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+d1_mini.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+d1_mini.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+d1_mini.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+d1_mini.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+d1_mini.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+d1_mini.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+d1_mini.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+d1_mini.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini.menu.lvl.CORE=CORE
+d1_mini.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+d1_mini.menu.lvl.WIFI=WIFI
+d1_mini.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+d1_mini.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+d1_mini.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+d1_mini.menu.lvl.UPDATER=UPDATER
+d1_mini.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+d1_mini.menu.lvl.OTA=OTA
+d1_mini.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+d1_mini.menu.lvl.OOM=OOM
+d1_mini.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+d1_mini.menu.lvl.MDNS=MDNS
+d1_mini.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+d1_mini.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+d1_mini.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+d1_mini.menu.wipe.none=Only Sketch
+d1_mini.menu.wipe.none.upload.erase_cmd=version
+d1_mini.menu.wipe.sdk=Sketch + WiFi Settings
+d1_mini.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+d1_mini.menu.wipe.all=All Flash Contents
+d1_mini.menu.wipe.all.upload.erase_cmd=erase_flash
+d1_mini.menu.baud.921600=921600
+d1_mini.menu.baud.921600.upload.speed=921600
+d1_mini.menu.baud.57600=57600
+d1_mini.menu.baud.57600.upload.speed=57600
+d1_mini.menu.baud.115200=115200
+d1_mini.menu.baud.115200.upload.speed=115200
+d1_mini.menu.baud.230400.linux=230400
+d1_mini.menu.baud.230400.macosx=230400
+d1_mini.menu.baud.230400.upload.speed=230400
+d1_mini.menu.baud.256000.windows=256000
+d1_mini.menu.baud.256000.upload.speed=256000
+d1_mini.menu.baud.460800.linux=460800
+d1_mini.menu.baud.460800.macosx=460800
+d1_mini.menu.baud.460800.upload.speed=460800
+d1_mini.menu.baud.512000.windows=512000
+d1_mini.menu.baud.512000.upload.speed=512000
+d1_mini.menu.baud.3000000=3000000
+d1_mini.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+d1_mini_pro.name=LOLIN(WEMOS) D1 mini Pro
+d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO
+d1_mini_pro.build.variant=d1_mini
+d1_mini_pro.upload.tool=esptool
+d1_mini_pro.upload.maximum_data_size=81920
+d1_mini_pro.upload.wait_for_upload_port=true
+d1_mini_pro.upload.erase_cmd=version
+d1_mini_pro.serial.disableDTR=true
+d1_mini_pro.serial.disableRTS=true
+d1_mini_pro.build.mcu=esp8266
+d1_mini_pro.build.core=esp8266
+d1_mini_pro.build.spiffs_pagesize=256
+d1_mini_pro.build.debug_port=
+d1_mini_pro.build.debug_level=
+d1_mini_pro.menu.xtal.80=80 MHz
+d1_mini_pro.menu.xtal.80.build.f_cpu=80000000L
+d1_mini_pro.menu.xtal.160=160 MHz
+d1_mini_pro.menu.xtal.160.build.f_cpu=160000000L
+d1_mini_pro.menu.vt.flash=Flash
+d1_mini_pro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+d1_mini_pro.menu.vt.heap=Heap
+d1_mini_pro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+d1_mini_pro.menu.vt.iram=IRAM
+d1_mini_pro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+d1_mini_pro.menu.exception.legacy=Legacy (new can return nullptr)
+d1_mini_pro.menu.exception.legacy.build.exception_flags=-fno-exceptions
+d1_mini_pro.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+d1_mini_pro.menu.exception.disabled=Disabled (new can abort)
+d1_mini_pro.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+d1_mini_pro.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+d1_mini_pro.menu.exception.enabled=Enabled
+d1_mini_pro.menu.exception.enabled.build.exception_flags=-fexceptions
+d1_mini_pro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+d1_mini_pro.menu.ssl.all=All SSL ciphers (most compatible)
+d1_mini_pro.menu.ssl.all.build.sslflags=
+d1_mini_pro.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+d1_mini_pro.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+d1_mini_pro.upload.resetmethod=nodemcu
+d1_mini_pro.build.flash_mode=dio
+d1_mini_pro.build.flash_flags=-DFLASHMODE_DIO
+d1_mini_pro.build.flash_freq=40
+d1_mini_pro.menu.eesz.16M14M=16MB (FS:14MB OTA:~1019KB)
+d1_mini_pro.menu.eesz.16M14M.build.flash_size=16M
+d1_mini_pro.menu.eesz.16M14M.build.flash_size_bytes=0x1000000
+d1_mini_pro.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld
+d1_mini_pro.menu.eesz.16M14M.build.spiffs_pagesize=256
+d1_mini_pro.menu.eesz.16M14M.upload.maximum_size=1044464
+d1_mini_pro.menu.eesz.16M14M.build.rfcal_addr=0xFFC000
+d1_mini_pro.menu.eesz.16M14M.build.spiffs_start=0x200000
+d1_mini_pro.menu.eesz.16M14M.build.spiffs_end=0xFFA000
+d1_mini_pro.menu.eesz.16M14M.build.spiffs_blocksize=8192
+d1_mini_pro.menu.eesz.16M15M=16MB (FS:15MB OTA:~512KB)
+d1_mini_pro.menu.eesz.16M15M.build.flash_size=16M
+d1_mini_pro.menu.eesz.16M15M.build.flash_size_bytes=0x1000000
+d1_mini_pro.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld
+d1_mini_pro.menu.eesz.16M15M.build.spiffs_pagesize=256
+d1_mini_pro.menu.eesz.16M15M.upload.maximum_size=1044464
+d1_mini_pro.menu.eesz.16M15M.build.rfcal_addr=0xFFC000
+d1_mini_pro.menu.eesz.16M15M.build.spiffs_start=0x100000
+d1_mini_pro.menu.eesz.16M15M.build.spiffs_end=0xFFA000
+d1_mini_pro.menu.eesz.16M15M.build.spiffs_blocksize=8192
+d1_mini_pro.menu.ip.lm2f=v2 Lower Memory
+d1_mini_pro.menu.ip.lm2f.build.lwip_include=lwip2/include
+d1_mini_pro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+d1_mini_pro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+d1_mini_pro.menu.ip.hb2f=v2 Higher Bandwidth
+d1_mini_pro.menu.ip.hb2f.build.lwip_include=lwip2/include
+d1_mini_pro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+d1_mini_pro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+d1_mini_pro.menu.ip.lm2n=v2 Lower Memory (no features)
+d1_mini_pro.menu.ip.lm2n.build.lwip_include=lwip2/include
+d1_mini_pro.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+d1_mini_pro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+d1_mini_pro.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+d1_mini_pro.menu.ip.hb2n.build.lwip_include=lwip2/include
+d1_mini_pro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+d1_mini_pro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+d1_mini_pro.menu.ip.lm6f=v2 IPv6 Lower Memory
+d1_mini_pro.menu.ip.lm6f.build.lwip_include=lwip2/include
+d1_mini_pro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+d1_mini_pro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+d1_mini_pro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+d1_mini_pro.menu.ip.hb6f.build.lwip_include=lwip2/include
+d1_mini_pro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+d1_mini_pro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+d1_mini_pro.menu.ip.hb1=v1.4 Higher Bandwidth
+d1_mini_pro.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+d1_mini_pro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+d1_mini_pro.menu.ip.src=v1.4 Compile from source
+d1_mini_pro.menu.ip.src.build.lwip_lib=-llwip_src
+d1_mini_pro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+d1_mini_pro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+d1_mini_pro.menu.dbg.Disabled=Disabled
+d1_mini_pro.menu.dbg.Disabled.build.debug_port=
+d1_mini_pro.menu.dbg.Serial=Serial
+d1_mini_pro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+d1_mini_pro.menu.dbg.Serial1=Serial1
+d1_mini_pro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+d1_mini_pro.menu.lvl.None____=None
+d1_mini_pro.menu.lvl.None____.build.debug_level=
+d1_mini_pro.menu.lvl.SSL=SSL
+d1_mini_pro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+d1_mini_pro.menu.lvl.TLS_MEM=TLS_MEM
+d1_mini_pro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+d1_mini_pro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+d1_mini_pro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+d1_mini_pro.menu.lvl.HTTP_SERVER=HTTP_SERVER
+d1_mini_pro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+d1_mini_pro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+d1_mini_pro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+d1_mini_pro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+d1_mini_pro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+d1_mini_pro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+d1_mini_pro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini_pro.menu.lvl.CORE=CORE
+d1_mini_pro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+d1_mini_pro.menu.lvl.WIFI=WIFI
+d1_mini_pro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+d1_mini_pro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+d1_mini_pro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+d1_mini_pro.menu.lvl.UPDATER=UPDATER
+d1_mini_pro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+d1_mini_pro.menu.lvl.OTA=OTA
+d1_mini_pro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+d1_mini_pro.menu.lvl.OOM=OOM
+d1_mini_pro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+d1_mini_pro.menu.lvl.MDNS=MDNS
+d1_mini_pro.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+d1_mini_pro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+d1_mini_pro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+d1_mini_pro.menu.wipe.none=Only Sketch
+d1_mini_pro.menu.wipe.none.upload.erase_cmd=version
+d1_mini_pro.menu.wipe.sdk=Sketch + WiFi Settings
+d1_mini_pro.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+d1_mini_pro.menu.wipe.all=All Flash Contents
+d1_mini_pro.menu.wipe.all.upload.erase_cmd=erase_flash
+d1_mini_pro.menu.baud.921600=921600
+d1_mini_pro.menu.baud.921600.upload.speed=921600
+d1_mini_pro.menu.baud.57600=57600
+d1_mini_pro.menu.baud.57600.upload.speed=57600
+d1_mini_pro.menu.baud.115200=115200
+d1_mini_pro.menu.baud.115200.upload.speed=115200
+d1_mini_pro.menu.baud.230400.linux=230400
+d1_mini_pro.menu.baud.230400.macosx=230400
+d1_mini_pro.menu.baud.230400.upload.speed=230400
+d1_mini_pro.menu.baud.256000.windows=256000
+d1_mini_pro.menu.baud.256000.upload.speed=256000
+d1_mini_pro.menu.baud.460800.linux=460800
+d1_mini_pro.menu.baud.460800.macosx=460800
+d1_mini_pro.menu.baud.460800.upload.speed=460800
+d1_mini_pro.menu.baud.512000.windows=512000
+d1_mini_pro.menu.baud.512000.upload.speed=512000
+d1_mini_pro.menu.baud.3000000=3000000
+d1_mini_pro.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+d1_mini_lite.name=LOLIN(WEMOS) D1 mini Lite
+d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE
+d1_mini_lite.build.variant=d1_mini
+d1_mini_lite.upload.tool=esptool
+d1_mini_lite.upload.maximum_data_size=81920
+d1_mini_lite.upload.wait_for_upload_port=true
+d1_mini_lite.upload.erase_cmd=version
+d1_mini_lite.serial.disableDTR=true
+d1_mini_lite.serial.disableRTS=true
+d1_mini_lite.build.mcu=esp8266
+d1_mini_lite.build.core=esp8266
+d1_mini_lite.build.spiffs_pagesize=256
+d1_mini_lite.build.debug_port=
+d1_mini_lite.build.debug_level=
+d1_mini_lite.menu.xtal.80=80 MHz
+d1_mini_lite.menu.xtal.80.build.f_cpu=80000000L
+d1_mini_lite.menu.xtal.160=160 MHz
+d1_mini_lite.menu.xtal.160.build.f_cpu=160000000L
+d1_mini_lite.menu.vt.flash=Flash
+d1_mini_lite.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+d1_mini_lite.menu.vt.heap=Heap
+d1_mini_lite.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+d1_mini_lite.menu.vt.iram=IRAM
+d1_mini_lite.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+d1_mini_lite.menu.exception.legacy=Legacy (new can return nullptr)
+d1_mini_lite.menu.exception.legacy.build.exception_flags=-fno-exceptions
+d1_mini_lite.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+d1_mini_lite.menu.exception.disabled=Disabled (new can abort)
+d1_mini_lite.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+d1_mini_lite.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+d1_mini_lite.menu.exception.enabled=Enabled
+d1_mini_lite.menu.exception.enabled.build.exception_flags=-fexceptions
+d1_mini_lite.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+d1_mini_lite.menu.ssl.all=All SSL ciphers (most compatible)
+d1_mini_lite.menu.ssl.all.build.sslflags=
+d1_mini_lite.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+d1_mini_lite.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+d1_mini_lite.upload.resetmethod=nodemcu
+d1_mini_lite.build.flash_mode=dout
+d1_mini_lite.build.flash_flags=-DFLASHMODE_DOUT
+d1_mini_lite.build.flash_freq=40
+d1_mini_lite.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB)
+d1_mini_lite.menu.eesz.1M64.build.flash_size=1M
+d1_mini_lite.menu.eesz.1M64.build.flash_size_bytes=0x100000
+d1_mini_lite.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld
+d1_mini_lite.menu.eesz.1M64.build.spiffs_pagesize=256
+d1_mini_lite.menu.eesz.1M64.upload.maximum_size=958448
+d1_mini_lite.menu.eesz.1M64.build.rfcal_addr=0xFC000
+d1_mini_lite.menu.eesz.1M64.build.spiffs_start=0xEB000
+d1_mini_lite.menu.eesz.1M64.build.spiffs_end=0xFB000
+d1_mini_lite.menu.eesz.1M64.build.spiffs_blocksize=4096
+d1_mini_lite.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB)
+d1_mini_lite.menu.eesz.1M128.build.flash_size=1M
+d1_mini_lite.menu.eesz.1M128.build.flash_size_bytes=0x100000
+d1_mini_lite.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld
+d1_mini_lite.menu.eesz.1M128.build.spiffs_pagesize=256
+d1_mini_lite.menu.eesz.1M128.upload.maximum_size=892912
+d1_mini_lite.menu.eesz.1M128.build.rfcal_addr=0xFC000
+d1_mini_lite.menu.eesz.1M128.build.spiffs_start=0xDB000
+d1_mini_lite.menu.eesz.1M128.build.spiffs_end=0xFB000
+d1_mini_lite.menu.eesz.1M128.build.spiffs_blocksize=4096
+d1_mini_lite.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB)
+d1_mini_lite.menu.eesz.1M144.build.flash_size=1M
+d1_mini_lite.menu.eesz.1M144.build.flash_size_bytes=0x100000
+d1_mini_lite.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld
+d1_mini_lite.menu.eesz.1M144.build.spiffs_pagesize=256
+d1_mini_lite.menu.eesz.1M144.upload.maximum_size=876528
+d1_mini_lite.menu.eesz.1M144.build.rfcal_addr=0xFC000
+d1_mini_lite.menu.eesz.1M144.build.spiffs_start=0xD7000
+d1_mini_lite.menu.eesz.1M144.build.spiffs_end=0xFB000
+d1_mini_lite.menu.eesz.1M144.build.spiffs_blocksize=4096
+d1_mini_lite.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB)
+d1_mini_lite.menu.eesz.1M160.build.flash_size=1M
+d1_mini_lite.menu.eesz.1M160.build.flash_size_bytes=0x100000
+d1_mini_lite.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld
+d1_mini_lite.menu.eesz.1M160.build.spiffs_pagesize=256
+d1_mini_lite.menu.eesz.1M160.upload.maximum_size=860144
+d1_mini_lite.menu.eesz.1M160.build.rfcal_addr=0xFC000
+d1_mini_lite.menu.eesz.1M160.build.spiffs_start=0xD3000
+d1_mini_lite.menu.eesz.1M160.build.spiffs_end=0xFB000
+d1_mini_lite.menu.eesz.1M160.build.spiffs_blocksize=4096
+d1_mini_lite.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB)
+d1_mini_lite.menu.eesz.1M192.build.flash_size=1M
+d1_mini_lite.menu.eesz.1M192.build.flash_size_bytes=0x100000
+d1_mini_lite.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld
+d1_mini_lite.menu.eesz.1M192.build.spiffs_pagesize=256
+d1_mini_lite.menu.eesz.1M192.upload.maximum_size=827376
+d1_mini_lite.menu.eesz.1M192.build.rfcal_addr=0xFC000
+d1_mini_lite.menu.eesz.1M192.build.spiffs_start=0xCB000
+d1_mini_lite.menu.eesz.1M192.build.spiffs_end=0xFB000
+d1_mini_lite.menu.eesz.1M192.build.spiffs_blocksize=4096
+d1_mini_lite.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB)
+d1_mini_lite.menu.eesz.1M256.build.flash_size=1M
+d1_mini_lite.menu.eesz.1M256.build.flash_size_bytes=0x100000
+d1_mini_lite.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld
+d1_mini_lite.menu.eesz.1M256.build.spiffs_pagesize=256
+d1_mini_lite.menu.eesz.1M256.upload.maximum_size=761840
+d1_mini_lite.menu.eesz.1M256.build.rfcal_addr=0xFC000
+d1_mini_lite.menu.eesz.1M256.build.spiffs_start=0xBB000
+d1_mini_lite.menu.eesz.1M256.build.spiffs_end=0xFB000
+d1_mini_lite.menu.eesz.1M256.build.spiffs_blocksize=4096
+d1_mini_lite.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB)
+d1_mini_lite.menu.eesz.1M512.build.flash_size=1M
+d1_mini_lite.menu.eesz.1M512.build.flash_size_bytes=0x100000
+d1_mini_lite.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld
+d1_mini_lite.menu.eesz.1M512.build.spiffs_pagesize=256
+d1_mini_lite.menu.eesz.1M512.upload.maximum_size=499696
+d1_mini_lite.menu.eesz.1M512.build.rfcal_addr=0xFC000
+d1_mini_lite.menu.eesz.1M512.build.spiffs_start=0x7B000
+d1_mini_lite.menu.eesz.1M512.build.spiffs_end=0xFB000
+d1_mini_lite.menu.eesz.1M512.build.spiffs_blocksize=8192
+d1_mini_lite.menu.eesz.1M=1MB (FS:none OTA:~502KB)
+d1_mini_lite.menu.eesz.1M.build.flash_size=1M
+d1_mini_lite.menu.eesz.1M.build.flash_size_bytes=0x100000
+d1_mini_lite.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld
+d1_mini_lite.menu.eesz.1M.build.spiffs_pagesize=256
+d1_mini_lite.menu.eesz.1M.upload.maximum_size=1023984
+d1_mini_lite.menu.eesz.1M.build.rfcal_addr=0xFC000
+d1_mini_lite.menu.ip.lm2f=v2 Lower Memory
+d1_mini_lite.menu.ip.lm2f.build.lwip_include=lwip2/include
+d1_mini_lite.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+d1_mini_lite.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+d1_mini_lite.menu.ip.hb2f=v2 Higher Bandwidth
+d1_mini_lite.menu.ip.hb2f.build.lwip_include=lwip2/include
+d1_mini_lite.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+d1_mini_lite.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+d1_mini_lite.menu.ip.lm2n=v2 Lower Memory (no features)
+d1_mini_lite.menu.ip.lm2n.build.lwip_include=lwip2/include
+d1_mini_lite.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+d1_mini_lite.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+d1_mini_lite.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+d1_mini_lite.menu.ip.hb2n.build.lwip_include=lwip2/include
+d1_mini_lite.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+d1_mini_lite.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+d1_mini_lite.menu.ip.lm6f=v2 IPv6 Lower Memory
+d1_mini_lite.menu.ip.lm6f.build.lwip_include=lwip2/include
+d1_mini_lite.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+d1_mini_lite.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+d1_mini_lite.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+d1_mini_lite.menu.ip.hb6f.build.lwip_include=lwip2/include
+d1_mini_lite.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+d1_mini_lite.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+d1_mini_lite.menu.ip.hb1=v1.4 Higher Bandwidth
+d1_mini_lite.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+d1_mini_lite.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+d1_mini_lite.menu.ip.src=v1.4 Compile from source
+d1_mini_lite.menu.ip.src.build.lwip_lib=-llwip_src
+d1_mini_lite.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+d1_mini_lite.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+d1_mini_lite.menu.dbg.Disabled=Disabled
+d1_mini_lite.menu.dbg.Disabled.build.debug_port=
+d1_mini_lite.menu.dbg.Serial=Serial
+d1_mini_lite.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+d1_mini_lite.menu.dbg.Serial1=Serial1
+d1_mini_lite.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+d1_mini_lite.menu.lvl.None____=None
+d1_mini_lite.menu.lvl.None____.build.debug_level=
+d1_mini_lite.menu.lvl.SSL=SSL
+d1_mini_lite.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+d1_mini_lite.menu.lvl.TLS_MEM=TLS_MEM
+d1_mini_lite.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+d1_mini_lite.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+d1_mini_lite.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+d1_mini_lite.menu.lvl.HTTP_SERVER=HTTP_SERVER
+d1_mini_lite.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+d1_mini_lite.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+d1_mini_lite.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+d1_mini_lite.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+d1_mini_lite.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+d1_mini_lite.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+d1_mini_lite.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1_mini_lite.menu.lvl.CORE=CORE
+d1_mini_lite.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+d1_mini_lite.menu.lvl.WIFI=WIFI
+d1_mini_lite.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+d1_mini_lite.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+d1_mini_lite.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+d1_mini_lite.menu.lvl.UPDATER=UPDATER
+d1_mini_lite.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+d1_mini_lite.menu.lvl.OTA=OTA
+d1_mini_lite.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+d1_mini_lite.menu.lvl.OOM=OOM
+d1_mini_lite.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+d1_mini_lite.menu.lvl.MDNS=MDNS
+d1_mini_lite.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+d1_mini_lite.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+d1_mini_lite.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+d1_mini_lite.menu.wipe.none=Only Sketch
+d1_mini_lite.menu.wipe.none.upload.erase_cmd=version
+d1_mini_lite.menu.wipe.sdk=Sketch + WiFi Settings
+d1_mini_lite.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+d1_mini_lite.menu.wipe.all=All Flash Contents
+d1_mini_lite.menu.wipe.all.upload.erase_cmd=erase_flash
+d1_mini_lite.menu.baud.921600=921600
+d1_mini_lite.menu.baud.921600.upload.speed=921600
+d1_mini_lite.menu.baud.57600=57600
+d1_mini_lite.menu.baud.57600.upload.speed=57600
+d1_mini_lite.menu.baud.115200=115200
+d1_mini_lite.menu.baud.115200.upload.speed=115200
+d1_mini_lite.menu.baud.230400.linux=230400
+d1_mini_lite.menu.baud.230400.macosx=230400
+d1_mini_lite.menu.baud.230400.upload.speed=230400
+d1_mini_lite.menu.baud.256000.windows=256000
+d1_mini_lite.menu.baud.256000.upload.speed=256000
+d1_mini_lite.menu.baud.460800.linux=460800
+d1_mini_lite.menu.baud.460800.macosx=460800
+d1_mini_lite.menu.baud.460800.upload.speed=460800
+d1_mini_lite.menu.baud.512000.windows=512000
+d1_mini_lite.menu.baud.512000.upload.speed=512000
+d1_mini_lite.menu.baud.3000000=3000000
+d1_mini_lite.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+d1.name=WeMos D1 R1
+d1.build.board=ESP8266_WEMOS_D1R1
+d1.build.variant=d1
+d1.upload.tool=esptool
+d1.upload.maximum_data_size=81920
+d1.upload.wait_for_upload_port=true
+d1.upload.erase_cmd=version
+d1.serial.disableDTR=true
+d1.serial.disableRTS=true
+d1.build.mcu=esp8266
+d1.build.core=esp8266
+d1.build.spiffs_pagesize=256
+d1.build.debug_port=
+d1.build.debug_level=
+d1.menu.xtal.80=80 MHz
+d1.menu.xtal.80.build.f_cpu=80000000L
+d1.menu.xtal.160=160 MHz
+d1.menu.xtal.160.build.f_cpu=160000000L
+d1.menu.vt.flash=Flash
+d1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+d1.menu.vt.heap=Heap
+d1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+d1.menu.vt.iram=IRAM
+d1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+d1.menu.exception.legacy=Legacy (new can return nullptr)
+d1.menu.exception.legacy.build.exception_flags=-fno-exceptions
+d1.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+d1.menu.exception.disabled=Disabled (new can abort)
+d1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+d1.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+d1.menu.exception.enabled=Enabled
+d1.menu.exception.enabled.build.exception_flags=-fexceptions
+d1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+d1.menu.ssl.all=All SSL ciphers (most compatible)
+d1.menu.ssl.all.build.sslflags=
+d1.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+d1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+d1.upload.resetmethod=nodemcu
+d1.build.flash_mode=dio
+d1.build.flash_flags=-DFLASHMODE_DIO
+d1.build.flash_freq=40
+d1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+d1.menu.eesz.4M2M.build.flash_size=4M
+d1.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+d1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+d1.menu.eesz.4M2M.build.spiffs_pagesize=256
+d1.menu.eesz.4M2M.upload.maximum_size=1044464
+d1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+d1.menu.eesz.4M2M.build.spiffs_start=0x200000
+d1.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+d1.menu.eesz.4M2M.build.spiffs_blocksize=8192
+d1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+d1.menu.eesz.4M3M.build.flash_size=4M
+d1.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+d1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+d1.menu.eesz.4M3M.build.spiffs_pagesize=256
+d1.menu.eesz.4M3M.upload.maximum_size=1044464
+d1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+d1.menu.eesz.4M3M.build.spiffs_start=0x100000
+d1.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+d1.menu.eesz.4M3M.build.spiffs_blocksize=8192
+d1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+d1.menu.eesz.4M1M.build.flash_size=4M
+d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+d1.menu.eesz.4M1M.build.spiffs_pagesize=256
+d1.menu.eesz.4M1M.upload.maximum_size=1044464
+d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+d1.menu.eesz.4M1M.build.spiffs_start=0x300000
+d1.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+d1.menu.eesz.4M1M.build.spiffs_blocksize=8192
+d1.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+d1.menu.eesz.4M.build.flash_size=4M
+d1.menu.eesz.4M.build.flash_size_bytes=0x400000
+d1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+d1.menu.eesz.4M.build.spiffs_pagesize=256
+d1.menu.eesz.4M.upload.maximum_size=1044464
+d1.menu.eesz.4M.build.rfcal_addr=0x3FC000
+d1.menu.ip.lm2f=v2 Lower Memory
+d1.menu.ip.lm2f.build.lwip_include=lwip2/include
+d1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+d1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+d1.menu.ip.hb2f=v2 Higher Bandwidth
+d1.menu.ip.hb2f.build.lwip_include=lwip2/include
+d1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+d1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+d1.menu.ip.lm2n=v2 Lower Memory (no features)
+d1.menu.ip.lm2n.build.lwip_include=lwip2/include
+d1.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+d1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+d1.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+d1.menu.ip.hb2n.build.lwip_include=lwip2/include
+d1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+d1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+d1.menu.ip.lm6f=v2 IPv6 Lower Memory
+d1.menu.ip.lm6f.build.lwip_include=lwip2/include
+d1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+d1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+d1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+d1.menu.ip.hb6f.build.lwip_include=lwip2/include
+d1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+d1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+d1.menu.ip.hb1=v1.4 Higher Bandwidth
+d1.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+d1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+d1.menu.ip.src=v1.4 Compile from source
+d1.menu.ip.src.build.lwip_lib=-llwip_src
+d1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+d1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+d1.menu.dbg.Disabled=Disabled
+d1.menu.dbg.Disabled.build.debug_port=
+d1.menu.dbg.Serial=Serial
+d1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+d1.menu.dbg.Serial1=Serial1
+d1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+d1.menu.lvl.None____=None
+d1.menu.lvl.None____.build.debug_level=
+d1.menu.lvl.SSL=SSL
+d1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+d1.menu.lvl.TLS_MEM=TLS_MEM
+d1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+d1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+d1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+d1.menu.lvl.HTTP_SERVER=HTTP_SERVER
+d1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+d1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+d1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+d1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+d1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+d1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+d1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+d1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+d1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+d1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+d1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+d1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+d1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+d1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+d1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+d1.menu.lvl.CORE=CORE
+d1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+d1.menu.lvl.WIFI=WIFI
+d1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+d1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+d1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+d1.menu.lvl.UPDATER=UPDATER
+d1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+d1.menu.lvl.OTA=OTA
+d1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+d1.menu.lvl.OOM=OOM
+d1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+d1.menu.lvl.MDNS=MDNS
+d1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+d1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+d1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+d1.menu.wipe.none=Only Sketch
+d1.menu.wipe.none.upload.erase_cmd=version
+d1.menu.wipe.sdk=Sketch + WiFi Settings
+d1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+d1.menu.wipe.all=All Flash Contents
+d1.menu.wipe.all.upload.erase_cmd=erase_flash
+d1.menu.baud.921600=921600
+d1.menu.baud.921600.upload.speed=921600
+d1.menu.baud.57600=57600
+d1.menu.baud.57600.upload.speed=57600
+d1.menu.baud.115200=115200
+d1.menu.baud.115200.upload.speed=115200
+d1.menu.baud.230400.linux=230400
+d1.menu.baud.230400.macosx=230400
+d1.menu.baud.230400.upload.speed=230400
+d1.menu.baud.256000.windows=256000
+d1.menu.baud.256000.upload.speed=256000
+d1.menu.baud.460800.linux=460800
+d1.menu.baud.460800.macosx=460800
+d1.menu.baud.460800.upload.speed=460800
+d1.menu.baud.512000.windows=512000
+d1.menu.baud.512000.upload.speed=512000
+d1.menu.baud.3000000=3000000
+d1.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+espino.name=ESPino (ESP-12 Module)
+espino.build.board=ESP8266_ESP12
+espino.build.variant=espino
+espino.upload.tool=esptool
+espino.upload.maximum_data_size=81920
+espino.upload.wait_for_upload_port=true
+espino.upload.erase_cmd=version
+espino.serial.disableDTR=true
+espino.serial.disableRTS=true
+espino.build.mcu=esp8266
+espino.build.core=esp8266
+espino.build.spiffs_pagesize=256
+espino.build.debug_port=
+espino.build.debug_level=
+espino.menu.xtal.80=80 MHz
+espino.menu.xtal.80.build.f_cpu=80000000L
+espino.menu.xtal.160=160 MHz
+espino.menu.xtal.160.build.f_cpu=160000000L
+espino.menu.vt.flash=Flash
+espino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+espino.menu.vt.heap=Heap
+espino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+espino.menu.vt.iram=IRAM
+espino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+espino.menu.exception.legacy=Legacy (new can return nullptr)
+espino.menu.exception.legacy.build.exception_flags=-fno-exceptions
+espino.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+espino.menu.exception.disabled=Disabled (new can abort)
+espino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+espino.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+espino.menu.exception.enabled=Enabled
+espino.menu.exception.enabled.build.exception_flags=-fexceptions
+espino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+espino.menu.ssl.all=All SSL ciphers (most compatible)
+espino.menu.ssl.all.build.sslflags=
+espino.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+espino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+espino.menu.ResetMethod.ck=ck
+espino.menu.ResetMethod.ck.upload.resetmethod=ck
+espino.menu.ResetMethod.nodemcu=nodemcu
+espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu
+espino.build.flash_mode=qio
+espino.build.flash_flags=-DFLASHMODE_QIO
+espino.build.flash_freq=40
+espino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+espino.menu.eesz.4M2M.build.flash_size=4M
+espino.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+espino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+espino.menu.eesz.4M2M.build.spiffs_pagesize=256
+espino.menu.eesz.4M2M.upload.maximum_size=1044464
+espino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+espino.menu.eesz.4M2M.build.spiffs_start=0x200000
+espino.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+espino.menu.eesz.4M2M.build.spiffs_blocksize=8192
+espino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+espino.menu.eesz.4M3M.build.flash_size=4M
+espino.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+espino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+espino.menu.eesz.4M3M.build.spiffs_pagesize=256
+espino.menu.eesz.4M3M.upload.maximum_size=1044464
+espino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+espino.menu.eesz.4M3M.build.spiffs_start=0x100000
+espino.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+espino.menu.eesz.4M3M.build.spiffs_blocksize=8192
+espino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+espino.menu.eesz.4M1M.build.flash_size=4M
+espino.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+espino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+espino.menu.eesz.4M1M.build.spiffs_pagesize=256
+espino.menu.eesz.4M1M.upload.maximum_size=1044464
+espino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+espino.menu.eesz.4M1M.build.spiffs_start=0x300000
+espino.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+espino.menu.eesz.4M1M.build.spiffs_blocksize=8192
+espino.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+espino.menu.eesz.4M.build.flash_size=4M
+espino.menu.eesz.4M.build.flash_size_bytes=0x400000
+espino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+espino.menu.eesz.4M.build.spiffs_pagesize=256
+espino.menu.eesz.4M.upload.maximum_size=1044464
+espino.menu.eesz.4M.build.rfcal_addr=0x3FC000
+espino.menu.ip.lm2f=v2 Lower Memory
+espino.menu.ip.lm2f.build.lwip_include=lwip2/include
+espino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+espino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espino.menu.ip.hb2f=v2 Higher Bandwidth
+espino.menu.ip.hb2f.build.lwip_include=lwip2/include
+espino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+espino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espino.menu.ip.lm2n=v2 Lower Memory (no features)
+espino.menu.ip.lm2n.build.lwip_include=lwip2/include
+espino.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+espino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espino.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+espino.menu.ip.hb2n.build.lwip_include=lwip2/include
+espino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+espino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espino.menu.ip.lm6f=v2 IPv6 Lower Memory
+espino.menu.ip.lm6f.build.lwip_include=lwip2/include
+espino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+espino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+espino.menu.ip.hb6f.build.lwip_include=lwip2/include
+espino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+espino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espino.menu.ip.hb1=v1.4 Higher Bandwidth
+espino.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+espino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+espino.menu.ip.src=v1.4 Compile from source
+espino.menu.ip.src.build.lwip_lib=-llwip_src
+espino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+espino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+espino.menu.dbg.Disabled=Disabled
+espino.menu.dbg.Disabled.build.debug_port=
+espino.menu.dbg.Serial=Serial
+espino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+espino.menu.dbg.Serial1=Serial1
+espino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+espino.menu.lvl.None____=None
+espino.menu.lvl.None____.build.debug_level=
+espino.menu.lvl.SSL=SSL
+espino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+espino.menu.lvl.TLS_MEM=TLS_MEM
+espino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+espino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+espino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+espino.menu.lvl.HTTP_SERVER=HTTP_SERVER
+espino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+espino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+espino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+espino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+espino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+espino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+espino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+espino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+espino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+espino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+espino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+espino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espino.menu.lvl.CORE=CORE
+espino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+espino.menu.lvl.WIFI=WIFI
+espino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+espino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+espino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+espino.menu.lvl.UPDATER=UPDATER
+espino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+espino.menu.lvl.OTA=OTA
+espino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+espino.menu.lvl.OOM=OOM
+espino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+espino.menu.lvl.MDNS=MDNS
+espino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+espino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+espino.menu.wipe.none=Only Sketch
+espino.menu.wipe.none.upload.erase_cmd=version
+espino.menu.wipe.sdk=Sketch + WiFi Settings
+espino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+espino.menu.wipe.all=All Flash Contents
+espino.menu.wipe.all.upload.erase_cmd=erase_flash
+espino.menu.baud.115200=115200
+espino.menu.baud.115200.upload.speed=115200
+espino.menu.baud.57600=57600
+espino.menu.baud.57600.upload.speed=57600
+espino.menu.baud.230400.linux=230400
+espino.menu.baud.230400.macosx=230400
+espino.menu.baud.230400.upload.speed=230400
+espino.menu.baud.256000.windows=256000
+espino.menu.baud.256000.upload.speed=256000
+espino.menu.baud.460800.linux=460800
+espino.menu.baud.460800.macosx=460800
+espino.menu.baud.460800.upload.speed=460800
+espino.menu.baud.512000.windows=512000
+espino.menu.baud.512000.upload.speed=512000
+espino.menu.baud.921600=921600
+espino.menu.baud.921600.upload.speed=921600
+espino.menu.baud.3000000=3000000
+espino.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+espinotee.name=ThaiEasyElec's ESPino
+espinotee.build.board=ESP8266_ESP13
+espinotee.build.variant=espinotee
+espinotee.upload.tool=esptool
+espinotee.upload.maximum_data_size=81920
+espinotee.upload.wait_for_upload_port=true
+espinotee.upload.erase_cmd=version
+espinotee.serial.disableDTR=true
+espinotee.serial.disableRTS=true
+espinotee.build.mcu=esp8266
+espinotee.build.core=esp8266
+espinotee.build.spiffs_pagesize=256
+espinotee.build.debug_port=
+espinotee.build.debug_level=
+espinotee.menu.xtal.80=80 MHz
+espinotee.menu.xtal.80.build.f_cpu=80000000L
+espinotee.menu.xtal.160=160 MHz
+espinotee.menu.xtal.160.build.f_cpu=160000000L
+espinotee.menu.vt.flash=Flash
+espinotee.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+espinotee.menu.vt.heap=Heap
+espinotee.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+espinotee.menu.vt.iram=IRAM
+espinotee.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+espinotee.menu.exception.legacy=Legacy (new can return nullptr)
+espinotee.menu.exception.legacy.build.exception_flags=-fno-exceptions
+espinotee.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+espinotee.menu.exception.disabled=Disabled (new can abort)
+espinotee.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+espinotee.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+espinotee.menu.exception.enabled=Enabled
+espinotee.menu.exception.enabled.build.exception_flags=-fexceptions
+espinotee.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+espinotee.menu.ssl.all=All SSL ciphers (most compatible)
+espinotee.menu.ssl.all.build.sslflags=
+espinotee.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+espinotee.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+espinotee.upload.resetmethod=nodemcu
+espinotee.build.flash_mode=qio
+espinotee.build.flash_flags=-DFLASHMODE_QIO
+espinotee.build.flash_freq=40
+espinotee.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+espinotee.menu.eesz.4M2M.build.flash_size=4M
+espinotee.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+espinotee.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+espinotee.menu.eesz.4M2M.build.spiffs_pagesize=256
+espinotee.menu.eesz.4M2M.upload.maximum_size=1044464
+espinotee.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+espinotee.menu.eesz.4M2M.build.spiffs_start=0x200000
+espinotee.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+espinotee.menu.eesz.4M2M.build.spiffs_blocksize=8192
+espinotee.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+espinotee.menu.eesz.4M3M.build.flash_size=4M
+espinotee.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+espinotee.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+espinotee.menu.eesz.4M3M.build.spiffs_pagesize=256
+espinotee.menu.eesz.4M3M.upload.maximum_size=1044464
+espinotee.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+espinotee.menu.eesz.4M3M.build.spiffs_start=0x100000
+espinotee.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+espinotee.menu.eesz.4M3M.build.spiffs_blocksize=8192
+espinotee.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+espinotee.menu.eesz.4M1M.build.flash_size=4M
+espinotee.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+espinotee.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+espinotee.menu.eesz.4M1M.build.spiffs_pagesize=256
+espinotee.menu.eesz.4M1M.upload.maximum_size=1044464
+espinotee.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+espinotee.menu.eesz.4M1M.build.spiffs_start=0x300000
+espinotee.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+espinotee.menu.eesz.4M1M.build.spiffs_blocksize=8192
+espinotee.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+espinotee.menu.eesz.4M.build.flash_size=4M
+espinotee.menu.eesz.4M.build.flash_size_bytes=0x400000
+espinotee.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+espinotee.menu.eesz.4M.build.spiffs_pagesize=256
+espinotee.menu.eesz.4M.upload.maximum_size=1044464
+espinotee.menu.eesz.4M.build.rfcal_addr=0x3FC000
+espinotee.menu.ip.lm2f=v2 Lower Memory
+espinotee.menu.ip.lm2f.build.lwip_include=lwip2/include
+espinotee.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+espinotee.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espinotee.menu.ip.hb2f=v2 Higher Bandwidth
+espinotee.menu.ip.hb2f.build.lwip_include=lwip2/include
+espinotee.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+espinotee.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espinotee.menu.ip.lm2n=v2 Lower Memory (no features)
+espinotee.menu.ip.lm2n.build.lwip_include=lwip2/include
+espinotee.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+espinotee.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espinotee.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+espinotee.menu.ip.hb2n.build.lwip_include=lwip2/include
+espinotee.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+espinotee.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espinotee.menu.ip.lm6f=v2 IPv6 Lower Memory
+espinotee.menu.ip.lm6f.build.lwip_include=lwip2/include
+espinotee.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+espinotee.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espinotee.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+espinotee.menu.ip.hb6f.build.lwip_include=lwip2/include
+espinotee.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+espinotee.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espinotee.menu.ip.hb1=v1.4 Higher Bandwidth
+espinotee.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+espinotee.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+espinotee.menu.ip.src=v1.4 Compile from source
+espinotee.menu.ip.src.build.lwip_lib=-llwip_src
+espinotee.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+espinotee.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+espinotee.menu.dbg.Disabled=Disabled
+espinotee.menu.dbg.Disabled.build.debug_port=
+espinotee.menu.dbg.Serial=Serial
+espinotee.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+espinotee.menu.dbg.Serial1=Serial1
+espinotee.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+espinotee.menu.lvl.None____=None
+espinotee.menu.lvl.None____.build.debug_level=
+espinotee.menu.lvl.SSL=SSL
+espinotee.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+espinotee.menu.lvl.TLS_MEM=TLS_MEM
+espinotee.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+espinotee.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+espinotee.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+espinotee.menu.lvl.HTTP_SERVER=HTTP_SERVER
+espinotee.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+espinotee.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+espinotee.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+espinotee.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+espinotee.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+espinotee.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+espinotee.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+espinotee.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+espinotee.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espinotee.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+espinotee.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espinotee.menu.lvl.CORE=CORE
+espinotee.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+espinotee.menu.lvl.WIFI=WIFI
+espinotee.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+espinotee.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+espinotee.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+espinotee.menu.lvl.UPDATER=UPDATER
+espinotee.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+espinotee.menu.lvl.OTA=OTA
+espinotee.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+espinotee.menu.lvl.OOM=OOM
+espinotee.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+espinotee.menu.lvl.MDNS=MDNS
+espinotee.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espinotee.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+espinotee.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+espinotee.menu.wipe.none=Only Sketch
+espinotee.menu.wipe.none.upload.erase_cmd=version
+espinotee.menu.wipe.sdk=Sketch + WiFi Settings
+espinotee.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+espinotee.menu.wipe.all=All Flash Contents
+espinotee.menu.wipe.all.upload.erase_cmd=erase_flash
+espinotee.menu.baud.115200=115200
+espinotee.menu.baud.115200.upload.speed=115200
+espinotee.menu.baud.57600=57600
+espinotee.menu.baud.57600.upload.speed=57600
+espinotee.menu.baud.230400.linux=230400
+espinotee.menu.baud.230400.macosx=230400
+espinotee.menu.baud.230400.upload.speed=230400
+espinotee.menu.baud.256000.windows=256000
+espinotee.menu.baud.256000.upload.speed=256000
+espinotee.menu.baud.460800.linux=460800
+espinotee.menu.baud.460800.macosx=460800
+espinotee.menu.baud.460800.upload.speed=460800
+espinotee.menu.baud.512000.windows=512000
+espinotee.menu.baud.512000.upload.speed=512000
+espinotee.menu.baud.921600=921600
+espinotee.menu.baud.921600.upload.speed=921600
+espinotee.menu.baud.3000000=3000000
+espinotee.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+wifinfo.name=WifInfo
+wifinfo.build.board=WIFINFO
+wifinfo.build.variant=wifinfo
+wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS)
+wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07
+wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld
+wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M
+wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096
+wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000
+wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000
+wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376
+wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS)
+wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12
+wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld
+wifinfo.menu.ESPModule.ESP12.build.flash_size=4M
+wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192
+wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000
+wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256
+wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000
+wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464
+wifinfo.upload.tool=esptool
+wifinfo.upload.maximum_data_size=81920
+wifinfo.upload.wait_for_upload_port=true
+wifinfo.upload.erase_cmd=version
+wifinfo.serial.disableDTR=true
+wifinfo.serial.disableRTS=true
+wifinfo.build.mcu=esp8266
+wifinfo.build.core=esp8266
+wifinfo.build.spiffs_pagesize=256
+wifinfo.build.debug_port=
+wifinfo.build.debug_level=
+wifinfo.menu.xtal.80=80 MHz
+wifinfo.menu.xtal.80.build.f_cpu=80000000L
+wifinfo.menu.xtal.160=160 MHz
+wifinfo.menu.xtal.160.build.f_cpu=160000000L
+wifinfo.menu.vt.flash=Flash
+wifinfo.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+wifinfo.menu.vt.heap=Heap
+wifinfo.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+wifinfo.menu.vt.iram=IRAM
+wifinfo.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+wifinfo.menu.exception.legacy=Legacy (new can return nullptr)
+wifinfo.menu.exception.legacy.build.exception_flags=-fno-exceptions
+wifinfo.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+wifinfo.menu.exception.disabled=Disabled (new can abort)
+wifinfo.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+wifinfo.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+wifinfo.menu.exception.enabled=Enabled
+wifinfo.menu.exception.enabled.build.exception_flags=-fexceptions
+wifinfo.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+wifinfo.menu.ssl.all=All SSL ciphers (most compatible)
+wifinfo.menu.ssl.all.build.sslflags=
+wifinfo.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+wifinfo.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+wifinfo.upload.resetmethod=nodemcu
+wifinfo.build.flash_mode=qio
+wifinfo.build.flash_flags=-DFLASHMODE_QIO
+wifinfo.menu.FlashFreq.40=40MHz
+wifinfo.menu.FlashFreq.40.build.flash_freq=40
+wifinfo.menu.FlashFreq.80=80MHz
+wifinfo.menu.FlashFreq.80.build.flash_freq=80
+wifinfo.menu.FlashFreq.20=20MHz
+wifinfo.menu.FlashFreq.20.build.flash_freq=20
+wifinfo.menu.FlashFreq.26=26MHz
+wifinfo.menu.FlashFreq.26.build.flash_freq=26
+wifinfo.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB)
+wifinfo.menu.eesz.1M64.build.flash_size=1M
+wifinfo.menu.eesz.1M64.build.flash_size_bytes=0x100000
+wifinfo.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld
+wifinfo.menu.eesz.1M64.build.spiffs_pagesize=256
+wifinfo.menu.eesz.1M64.upload.maximum_size=958448
+wifinfo.menu.eesz.1M64.build.rfcal_addr=0xFC000
+wifinfo.menu.eesz.1M64.build.spiffs_start=0xEB000
+wifinfo.menu.eesz.1M64.build.spiffs_end=0xFB000
+wifinfo.menu.eesz.1M64.build.spiffs_blocksize=4096
+wifinfo.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB)
+wifinfo.menu.eesz.1M128.build.flash_size=1M
+wifinfo.menu.eesz.1M128.build.flash_size_bytes=0x100000
+wifinfo.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld
+wifinfo.menu.eesz.1M128.build.spiffs_pagesize=256
+wifinfo.menu.eesz.1M128.upload.maximum_size=892912
+wifinfo.menu.eesz.1M128.build.rfcal_addr=0xFC000
+wifinfo.menu.eesz.1M128.build.spiffs_start=0xDB000
+wifinfo.menu.eesz.1M128.build.spiffs_end=0xFB000
+wifinfo.menu.eesz.1M128.build.spiffs_blocksize=4096
+wifinfo.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB)
+wifinfo.menu.eesz.1M144.build.flash_size=1M
+wifinfo.menu.eesz.1M144.build.flash_size_bytes=0x100000
+wifinfo.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld
+wifinfo.menu.eesz.1M144.build.spiffs_pagesize=256
+wifinfo.menu.eesz.1M144.upload.maximum_size=876528
+wifinfo.menu.eesz.1M144.build.rfcal_addr=0xFC000
+wifinfo.menu.eesz.1M144.build.spiffs_start=0xD7000
+wifinfo.menu.eesz.1M144.build.spiffs_end=0xFB000
+wifinfo.menu.eesz.1M144.build.spiffs_blocksize=4096
+wifinfo.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB)
+wifinfo.menu.eesz.1M160.build.flash_size=1M
+wifinfo.menu.eesz.1M160.build.flash_size_bytes=0x100000
+wifinfo.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld
+wifinfo.menu.eesz.1M160.build.spiffs_pagesize=256
+wifinfo.menu.eesz.1M160.upload.maximum_size=860144
+wifinfo.menu.eesz.1M160.build.rfcal_addr=0xFC000
+wifinfo.menu.eesz.1M160.build.spiffs_start=0xD3000
+wifinfo.menu.eesz.1M160.build.spiffs_end=0xFB000
+wifinfo.menu.eesz.1M160.build.spiffs_blocksize=4096
+wifinfo.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB)
+wifinfo.menu.eesz.1M192.build.flash_size=1M
+wifinfo.menu.eesz.1M192.build.flash_size_bytes=0x100000
+wifinfo.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld
+wifinfo.menu.eesz.1M192.build.spiffs_pagesize=256
+wifinfo.menu.eesz.1M192.upload.maximum_size=827376
+wifinfo.menu.eesz.1M192.build.rfcal_addr=0xFC000
+wifinfo.menu.eesz.1M192.build.spiffs_start=0xCB000
+wifinfo.menu.eesz.1M192.build.spiffs_end=0xFB000
+wifinfo.menu.eesz.1M192.build.spiffs_blocksize=4096
+wifinfo.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB)
+wifinfo.menu.eesz.1M256.build.flash_size=1M
+wifinfo.menu.eesz.1M256.build.flash_size_bytes=0x100000
+wifinfo.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld
+wifinfo.menu.eesz.1M256.build.spiffs_pagesize=256
+wifinfo.menu.eesz.1M256.upload.maximum_size=761840
+wifinfo.menu.eesz.1M256.build.rfcal_addr=0xFC000
+wifinfo.menu.eesz.1M256.build.spiffs_start=0xBB000
+wifinfo.menu.eesz.1M256.build.spiffs_end=0xFB000
+wifinfo.menu.eesz.1M256.build.spiffs_blocksize=4096
+wifinfo.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB)
+wifinfo.menu.eesz.1M512.build.flash_size=1M
+wifinfo.menu.eesz.1M512.build.flash_size_bytes=0x100000
+wifinfo.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld
+wifinfo.menu.eesz.1M512.build.spiffs_pagesize=256
+wifinfo.menu.eesz.1M512.upload.maximum_size=499696
+wifinfo.menu.eesz.1M512.build.rfcal_addr=0xFC000
+wifinfo.menu.eesz.1M512.build.spiffs_start=0x7B000
+wifinfo.menu.eesz.1M512.build.spiffs_end=0xFB000
+wifinfo.menu.eesz.1M512.build.spiffs_blocksize=8192
+wifinfo.menu.eesz.1M=1MB (FS:none OTA:~502KB)
+wifinfo.menu.eesz.1M.build.flash_size=1M
+wifinfo.menu.eesz.1M.build.flash_size_bytes=0x100000
+wifinfo.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld
+wifinfo.menu.eesz.1M.build.spiffs_pagesize=256
+wifinfo.menu.eesz.1M.upload.maximum_size=1023984
+wifinfo.menu.eesz.1M.build.rfcal_addr=0xFC000
+wifinfo.menu.ip.lm2f=v2 Lower Memory
+wifinfo.menu.ip.lm2f.build.lwip_include=lwip2/include
+wifinfo.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+wifinfo.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+wifinfo.menu.ip.hb2f=v2 Higher Bandwidth
+wifinfo.menu.ip.hb2f.build.lwip_include=lwip2/include
+wifinfo.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+wifinfo.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+wifinfo.menu.ip.lm2n=v2 Lower Memory (no features)
+wifinfo.menu.ip.lm2n.build.lwip_include=lwip2/include
+wifinfo.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+wifinfo.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+wifinfo.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+wifinfo.menu.ip.hb2n.build.lwip_include=lwip2/include
+wifinfo.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+wifinfo.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+wifinfo.menu.ip.lm6f=v2 IPv6 Lower Memory
+wifinfo.menu.ip.lm6f.build.lwip_include=lwip2/include
+wifinfo.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+wifinfo.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+wifinfo.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+wifinfo.menu.ip.hb6f.build.lwip_include=lwip2/include
+wifinfo.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+wifinfo.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+wifinfo.menu.ip.hb1=v1.4 Higher Bandwidth
+wifinfo.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+wifinfo.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+wifinfo.menu.ip.src=v1.4 Compile from source
+wifinfo.menu.ip.src.build.lwip_lib=-llwip_src
+wifinfo.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+wifinfo.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+wifinfo.menu.dbg.Disabled=Disabled
+wifinfo.menu.dbg.Disabled.build.debug_port=
+wifinfo.menu.dbg.Serial=Serial
+wifinfo.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+wifinfo.menu.dbg.Serial1=Serial1
+wifinfo.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+wifinfo.menu.lvl.None____=None
+wifinfo.menu.lvl.None____.build.debug_level=
+wifinfo.menu.lvl.SSL=SSL
+wifinfo.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+wifinfo.menu.lvl.TLS_MEM=TLS_MEM
+wifinfo.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+wifinfo.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+wifinfo.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+wifinfo.menu.lvl.HTTP_SERVER=HTTP_SERVER
+wifinfo.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+wifinfo.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+wifinfo.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+wifinfo.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+wifinfo.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+wifinfo.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+wifinfo.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+wifinfo.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+wifinfo.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifinfo.menu.lvl.CORE=CORE
+wifinfo.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+wifinfo.menu.lvl.WIFI=WIFI
+wifinfo.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+wifinfo.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+wifinfo.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+wifinfo.menu.lvl.UPDATER=UPDATER
+wifinfo.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+wifinfo.menu.lvl.OTA=OTA
+wifinfo.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+wifinfo.menu.lvl.OOM=OOM
+wifinfo.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+wifinfo.menu.lvl.MDNS=MDNS
+wifinfo.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+wifinfo.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+wifinfo.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+wifinfo.menu.wipe.none=Only Sketch
+wifinfo.menu.wipe.none.upload.erase_cmd=version
+wifinfo.menu.wipe.sdk=Sketch + WiFi Settings
+wifinfo.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+wifinfo.menu.wipe.all=All Flash Contents
+wifinfo.menu.wipe.all.upload.erase_cmd=erase_flash
+wifinfo.menu.baud.115200=115200
+wifinfo.menu.baud.115200.upload.speed=115200
+wifinfo.menu.baud.57600=57600
+wifinfo.menu.baud.57600.upload.speed=57600
+wifinfo.menu.baud.230400.linux=230400
+wifinfo.menu.baud.230400.macosx=230400
+wifinfo.menu.baud.230400.upload.speed=230400
+wifinfo.menu.baud.256000.windows=256000
+wifinfo.menu.baud.256000.upload.speed=256000
+wifinfo.menu.baud.460800.linux=460800
+wifinfo.menu.baud.460800.macosx=460800
+wifinfo.menu.baud.460800.upload.speed=460800
+wifinfo.menu.baud.512000.windows=512000
+wifinfo.menu.baud.512000.upload.speed=512000
+wifinfo.menu.baud.921600=921600
+wifinfo.menu.baud.921600.upload.speed=921600
+wifinfo.menu.baud.3000000=3000000
+wifinfo.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+arduino-esp8266.name=Arduino
+arduino-esp8266.build.board=ESP8266_ARDUINO
+arduino-esp8266.menu.BoardModel.primo=Primo
+arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO
+arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266
+arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi
+arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO
+arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO
+arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266
+arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart
+arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi
+arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI
+arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266
+arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart
+arduino-esp8266.upload.tool=esptool
+arduino-esp8266.upload.maximum_data_size=81920
+arduino-esp8266.upload.wait_for_upload_port=true
+arduino-esp8266.upload.erase_cmd=version
+arduino-esp8266.serial.disableDTR=true
+arduino-esp8266.serial.disableRTS=true
+arduino-esp8266.build.mcu=esp8266
+arduino-esp8266.build.core=esp8266
+arduino-esp8266.build.variant=generic
+arduino-esp8266.build.spiffs_pagesize=256
+arduino-esp8266.build.debug_port=
+arduino-esp8266.build.debug_level=
+arduino-esp8266.menu.xtal.80=80 MHz
+arduino-esp8266.menu.xtal.80.build.f_cpu=80000000L
+arduino-esp8266.menu.xtal.160=160 MHz
+arduino-esp8266.menu.xtal.160.build.f_cpu=160000000L
+arduino-esp8266.menu.vt.flash=Flash
+arduino-esp8266.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+arduino-esp8266.menu.vt.heap=Heap
+arduino-esp8266.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+arduino-esp8266.menu.vt.iram=IRAM
+arduino-esp8266.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+arduino-esp8266.menu.exception.legacy=Legacy (new can return nullptr)
+arduino-esp8266.menu.exception.legacy.build.exception_flags=-fno-exceptions
+arduino-esp8266.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+arduino-esp8266.menu.exception.disabled=Disabled (new can abort)
+arduino-esp8266.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+arduino-esp8266.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+arduino-esp8266.menu.exception.enabled=Enabled
+arduino-esp8266.menu.exception.enabled.build.exception_flags=-fexceptions
+arduino-esp8266.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+arduino-esp8266.menu.ssl.all=All SSL ciphers (most compatible)
+arduino-esp8266.menu.ssl.all.build.sslflags=
+arduino-esp8266.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+arduino-esp8266.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+arduino-esp8266.upload.resetmethod=ck
+arduino-esp8266.build.flash_mode=qio
+arduino-esp8266.build.flash_flags=-DFLASHMODE_QIO
+arduino-esp8266.build.flash_freq=40
+arduino-esp8266.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+arduino-esp8266.menu.eesz.4M2M.build.flash_size=4M
+arduino-esp8266.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+arduino-esp8266.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+arduino-esp8266.menu.eesz.4M2M.build.spiffs_pagesize=256
+arduino-esp8266.menu.eesz.4M2M.upload.maximum_size=1044464
+arduino-esp8266.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+arduino-esp8266.menu.eesz.4M2M.build.spiffs_start=0x200000
+arduino-esp8266.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+arduino-esp8266.menu.eesz.4M2M.build.spiffs_blocksize=8192
+arduino-esp8266.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+arduino-esp8266.menu.eesz.4M3M.build.flash_size=4M
+arduino-esp8266.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+arduino-esp8266.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+arduino-esp8266.menu.eesz.4M3M.build.spiffs_pagesize=256
+arduino-esp8266.menu.eesz.4M3M.upload.maximum_size=1044464
+arduino-esp8266.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+arduino-esp8266.menu.eesz.4M3M.build.spiffs_start=0x100000
+arduino-esp8266.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+arduino-esp8266.menu.eesz.4M3M.build.spiffs_blocksize=8192
+arduino-esp8266.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+arduino-esp8266.menu.eesz.4M1M.build.flash_size=4M
+arduino-esp8266.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+arduino-esp8266.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+arduino-esp8266.menu.eesz.4M1M.build.spiffs_pagesize=256
+arduino-esp8266.menu.eesz.4M1M.upload.maximum_size=1044464
+arduino-esp8266.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+arduino-esp8266.menu.eesz.4M1M.build.spiffs_start=0x300000
+arduino-esp8266.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+arduino-esp8266.menu.eesz.4M1M.build.spiffs_blocksize=8192
+arduino-esp8266.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+arduino-esp8266.menu.eesz.4M.build.flash_size=4M
+arduino-esp8266.menu.eesz.4M.build.flash_size_bytes=0x400000
+arduino-esp8266.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+arduino-esp8266.menu.eesz.4M.build.spiffs_pagesize=256
+arduino-esp8266.menu.eesz.4M.upload.maximum_size=1044464
+arduino-esp8266.menu.eesz.4M.build.rfcal_addr=0x3FC000
+arduino-esp8266.menu.ip.lm2f=v2 Lower Memory
+arduino-esp8266.menu.ip.lm2f.build.lwip_include=lwip2/include
+arduino-esp8266.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+arduino-esp8266.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+arduino-esp8266.menu.ip.hb2f=v2 Higher Bandwidth
+arduino-esp8266.menu.ip.hb2f.build.lwip_include=lwip2/include
+arduino-esp8266.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+arduino-esp8266.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+arduino-esp8266.menu.ip.lm2n=v2 Lower Memory (no features)
+arduino-esp8266.menu.ip.lm2n.build.lwip_include=lwip2/include
+arduino-esp8266.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+arduino-esp8266.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+arduino-esp8266.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+arduino-esp8266.menu.ip.hb2n.build.lwip_include=lwip2/include
+arduino-esp8266.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+arduino-esp8266.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+arduino-esp8266.menu.ip.lm6f=v2 IPv6 Lower Memory
+arduino-esp8266.menu.ip.lm6f.build.lwip_include=lwip2/include
+arduino-esp8266.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+arduino-esp8266.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+arduino-esp8266.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+arduino-esp8266.menu.ip.hb6f.build.lwip_include=lwip2/include
+arduino-esp8266.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+arduino-esp8266.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+arduino-esp8266.menu.ip.hb1=v1.4 Higher Bandwidth
+arduino-esp8266.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+arduino-esp8266.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+arduino-esp8266.menu.ip.src=v1.4 Compile from source
+arduino-esp8266.menu.ip.src.build.lwip_lib=-llwip_src
+arduino-esp8266.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+arduino-esp8266.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+arduino-esp8266.menu.dbg.Disabled=Disabled
+arduino-esp8266.menu.dbg.Disabled.build.debug_port=
+arduino-esp8266.menu.dbg.Serial=Serial
+arduino-esp8266.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+arduino-esp8266.menu.dbg.Serial1=Serial1
+arduino-esp8266.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+arduino-esp8266.menu.lvl.None____=None
+arduino-esp8266.menu.lvl.None____.build.debug_level=
+arduino-esp8266.menu.lvl.SSL=SSL
+arduino-esp8266.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+arduino-esp8266.menu.lvl.TLS_MEM=TLS_MEM
+arduino-esp8266.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+arduino-esp8266.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+arduino-esp8266.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+arduino-esp8266.menu.lvl.HTTP_SERVER=HTTP_SERVER
+arduino-esp8266.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+arduino-esp8266.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+arduino-esp8266.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+arduino-esp8266.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+arduino-esp8266.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+arduino-esp8266.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+arduino-esp8266.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+arduino-esp8266.menu.lvl.CORE=CORE
+arduino-esp8266.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+arduino-esp8266.menu.lvl.WIFI=WIFI
+arduino-esp8266.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+arduino-esp8266.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+arduino-esp8266.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+arduino-esp8266.menu.lvl.UPDATER=UPDATER
+arduino-esp8266.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+arduino-esp8266.menu.lvl.OTA=OTA
+arduino-esp8266.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+arduino-esp8266.menu.lvl.OOM=OOM
+arduino-esp8266.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+arduino-esp8266.menu.lvl.MDNS=MDNS
+arduino-esp8266.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+arduino-esp8266.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+arduino-esp8266.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+arduino-esp8266.menu.wipe.none=Only Sketch
+arduino-esp8266.menu.wipe.none.upload.erase_cmd=version
+arduino-esp8266.menu.wipe.sdk=Sketch + WiFi Settings
+arduino-esp8266.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+arduino-esp8266.menu.wipe.all=All Flash Contents
+arduino-esp8266.menu.wipe.all.upload.erase_cmd=erase_flash
+arduino-esp8266.menu.baud.115200=115200
+arduino-esp8266.menu.baud.115200.upload.speed=115200
+arduino-esp8266.menu.baud.57600=57600
+arduino-esp8266.menu.baud.57600.upload.speed=57600
+arduino-esp8266.menu.baud.230400.linux=230400
+arduino-esp8266.menu.baud.230400.macosx=230400
+arduino-esp8266.menu.baud.230400.upload.speed=230400
+arduino-esp8266.menu.baud.256000.windows=256000
+arduino-esp8266.menu.baud.256000.upload.speed=256000
+arduino-esp8266.menu.baud.460800.linux=460800
+arduino-esp8266.menu.baud.460800.macosx=460800
+arduino-esp8266.menu.baud.460800.upload.speed=460800
+arduino-esp8266.menu.baud.512000.windows=512000
+arduino-esp8266.menu.baud.512000.upload.speed=512000
+arduino-esp8266.menu.baud.921600=921600
+arduino-esp8266.menu.baud.921600.upload.speed=921600
+arduino-esp8266.menu.baud.3000000=3000000
+arduino-esp8266.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+gen4iod.name=4D Systems gen4 IoD Range
+gen4iod.build.board=GEN4_IOD
+gen4iod.build.f_cpu=160000000L
+gen4iod.build.variant=generic
+gen4iod.upload.tool=esptool
+gen4iod.upload.maximum_data_size=81920
+gen4iod.upload.wait_for_upload_port=true
+gen4iod.upload.erase_cmd=version
+gen4iod.serial.disableDTR=true
+gen4iod.serial.disableRTS=true
+gen4iod.build.mcu=esp8266
+gen4iod.build.core=esp8266
+gen4iod.build.spiffs_pagesize=256
+gen4iod.build.debug_port=
+gen4iod.build.debug_level=
+gen4iod.menu.xtal.80=80 MHz
+gen4iod.menu.xtal.80.build.f_cpu=80000000L
+gen4iod.menu.xtal.160=160 MHz
+gen4iod.menu.xtal.160.build.f_cpu=160000000L
+gen4iod.menu.vt.flash=Flash
+gen4iod.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+gen4iod.menu.vt.heap=Heap
+gen4iod.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+gen4iod.menu.vt.iram=IRAM
+gen4iod.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+gen4iod.menu.exception.legacy=Legacy (new can return nullptr)
+gen4iod.menu.exception.legacy.build.exception_flags=-fno-exceptions
+gen4iod.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+gen4iod.menu.exception.disabled=Disabled (new can abort)
+gen4iod.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+gen4iod.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+gen4iod.menu.exception.enabled=Enabled
+gen4iod.menu.exception.enabled.build.exception_flags=-fexceptions
+gen4iod.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+gen4iod.menu.ssl.all=All SSL ciphers (most compatible)
+gen4iod.menu.ssl.all.build.sslflags=
+gen4iod.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+gen4iod.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+gen4iod.upload.resetmethod=nodemcu
+gen4iod.build.flash_mode=dio
+gen4iod.build.flash_flags=-DFLASHMODE_DIO
+gen4iod.build.flash_freq=80
+gen4iod.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB)
+gen4iod.menu.eesz.512K32.build.flash_size=512K
+gen4iod.menu.eesz.512K32.build.flash_size_bytes=0x80000
+gen4iod.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld
+gen4iod.menu.eesz.512K32.build.spiffs_pagesize=256
+gen4iod.menu.eesz.512K32.upload.maximum_size=466928
+gen4iod.menu.eesz.512K32.build.rfcal_addr=0x7C000
+gen4iod.menu.eesz.512K32.build.spiffs_start=0x73000
+gen4iod.menu.eesz.512K32.build.spiffs_end=0x7B000
+gen4iod.menu.eesz.512K32.build.spiffs_blocksize=4096
+gen4iod.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB)
+gen4iod.menu.eesz.512K64.build.flash_size=512K
+gen4iod.menu.eesz.512K64.build.flash_size_bytes=0x80000
+gen4iod.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld
+gen4iod.menu.eesz.512K64.build.spiffs_pagesize=256
+gen4iod.menu.eesz.512K64.upload.maximum_size=434160
+gen4iod.menu.eesz.512K64.build.rfcal_addr=0x7C000
+gen4iod.menu.eesz.512K64.build.spiffs_start=0x6B000
+gen4iod.menu.eesz.512K64.build.spiffs_end=0x7B000
+gen4iod.menu.eesz.512K64.build.spiffs_blocksize=4096
+gen4iod.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB)
+gen4iod.menu.eesz.512K128.build.flash_size=512K
+gen4iod.menu.eesz.512K128.build.flash_size_bytes=0x80000
+gen4iod.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld
+gen4iod.menu.eesz.512K128.build.spiffs_pagesize=256
+gen4iod.menu.eesz.512K128.upload.maximum_size=368624
+gen4iod.menu.eesz.512K128.build.rfcal_addr=0x7C000
+gen4iod.menu.eesz.512K128.build.spiffs_start=0x5B000
+gen4iod.menu.eesz.512K128.build.spiffs_end=0x7B000
+gen4iod.menu.eesz.512K128.build.spiffs_blocksize=4096
+gen4iod.menu.eesz.512K=512KB (FS:none OTA:~246KB)
+gen4iod.menu.eesz.512K.build.flash_size=512K
+gen4iod.menu.eesz.512K.build.flash_size_bytes=0x80000
+gen4iod.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld
+gen4iod.menu.eesz.512K.build.spiffs_pagesize=256
+gen4iod.menu.eesz.512K.upload.maximum_size=499696
+gen4iod.menu.eesz.512K.build.rfcal_addr=0x7C000
+gen4iod.menu.ip.lm2f=v2 Lower Memory
+gen4iod.menu.ip.lm2f.build.lwip_include=lwip2/include
+gen4iod.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+gen4iod.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+gen4iod.menu.ip.hb2f=v2 Higher Bandwidth
+gen4iod.menu.ip.hb2f.build.lwip_include=lwip2/include
+gen4iod.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+gen4iod.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+gen4iod.menu.ip.lm2n=v2 Lower Memory (no features)
+gen4iod.menu.ip.lm2n.build.lwip_include=lwip2/include
+gen4iod.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+gen4iod.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+gen4iod.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+gen4iod.menu.ip.hb2n.build.lwip_include=lwip2/include
+gen4iod.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+gen4iod.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+gen4iod.menu.ip.lm6f=v2 IPv6 Lower Memory
+gen4iod.menu.ip.lm6f.build.lwip_include=lwip2/include
+gen4iod.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+gen4iod.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+gen4iod.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+gen4iod.menu.ip.hb6f.build.lwip_include=lwip2/include
+gen4iod.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+gen4iod.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+gen4iod.menu.ip.hb1=v1.4 Higher Bandwidth
+gen4iod.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+gen4iod.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+gen4iod.menu.ip.src=v1.4 Compile from source
+gen4iod.menu.ip.src.build.lwip_lib=-llwip_src
+gen4iod.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+gen4iod.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+gen4iod.menu.dbg.Disabled=Disabled
+gen4iod.menu.dbg.Disabled.build.debug_port=
+gen4iod.menu.dbg.Serial=Serial
+gen4iod.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+gen4iod.menu.dbg.Serial1=Serial1
+gen4iod.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+gen4iod.menu.lvl.None____=None
+gen4iod.menu.lvl.None____.build.debug_level=
+gen4iod.menu.lvl.SSL=SSL
+gen4iod.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+gen4iod.menu.lvl.TLS_MEM=TLS_MEM
+gen4iod.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+gen4iod.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+gen4iod.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+gen4iod.menu.lvl.HTTP_SERVER=HTTP_SERVER
+gen4iod.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+gen4iod.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+gen4iod.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+gen4iod.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+gen4iod.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+gen4iod.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+gen4iod.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+gen4iod.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+gen4iod.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+gen4iod.menu.lvl.CORE=CORE
+gen4iod.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+gen4iod.menu.lvl.WIFI=WIFI
+gen4iod.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+gen4iod.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+gen4iod.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+gen4iod.menu.lvl.UPDATER=UPDATER
+gen4iod.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+gen4iod.menu.lvl.OTA=OTA
+gen4iod.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+gen4iod.menu.lvl.OOM=OOM
+gen4iod.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+gen4iod.menu.lvl.MDNS=MDNS
+gen4iod.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+gen4iod.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+gen4iod.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+gen4iod.menu.wipe.none=Only Sketch
+gen4iod.menu.wipe.none.upload.erase_cmd=version
+gen4iod.menu.wipe.sdk=Sketch + WiFi Settings
+gen4iod.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+gen4iod.menu.wipe.all=All Flash Contents
+gen4iod.menu.wipe.all.upload.erase_cmd=erase_flash
+gen4iod.menu.baud.115200=115200
+gen4iod.menu.baud.115200.upload.speed=115200
+gen4iod.menu.baud.57600=57600
+gen4iod.menu.baud.57600.upload.speed=57600
+gen4iod.menu.baud.230400.linux=230400
+gen4iod.menu.baud.230400.macosx=230400
+gen4iod.menu.baud.230400.upload.speed=230400
+gen4iod.menu.baud.256000.windows=256000
+gen4iod.menu.baud.256000.upload.speed=256000
+gen4iod.menu.baud.460800.linux=460800
+gen4iod.menu.baud.460800.macosx=460800
+gen4iod.menu.baud.460800.upload.speed=460800
+gen4iod.menu.baud.512000.windows=512000
+gen4iod.menu.baud.512000.upload.speed=512000
+gen4iod.menu.baud.921600=921600
+gen4iod.menu.baud.921600.upload.speed=921600
+gen4iod.menu.baud.3000000=3000000
+gen4iod.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+oak.name=Digistump Oak
+oak.build.board=ESP8266_OAK
+oak.build.variant=oak
+oak.upload.maximum_size=1040368
+oak.upload.tool=esptool
+oak.upload.maximum_data_size=81920
+oak.upload.wait_for_upload_port=true
+oak.upload.erase_cmd=version
+oak.serial.disableDTR=true
+oak.serial.disableRTS=true
+oak.build.mcu=esp8266
+oak.build.core=esp8266
+oak.build.spiffs_pagesize=256
+oak.build.debug_port=
+oak.build.debug_level=
+oak.menu.xtal.80=80 MHz
+oak.menu.xtal.80.build.f_cpu=80000000L
+oak.menu.xtal.160=160 MHz
+oak.menu.xtal.160.build.f_cpu=160000000L
+oak.menu.vt.flash=Flash
+oak.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+oak.menu.vt.heap=Heap
+oak.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+oak.menu.vt.iram=IRAM
+oak.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+oak.menu.exception.legacy=Legacy (new can return nullptr)
+oak.menu.exception.legacy.build.exception_flags=-fno-exceptions
+oak.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+oak.menu.exception.disabled=Disabled (new can abort)
+oak.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+oak.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+oak.menu.exception.enabled=Enabled
+oak.menu.exception.enabled.build.exception_flags=-fexceptions
+oak.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+oak.menu.ssl.all=All SSL ciphers (most compatible)
+oak.menu.ssl.all.build.sslflags=
+oak.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+oak.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+oak.upload.resetmethod=none
+oak.build.flash_mode=dio
+oak.build.flash_flags=-DFLASHMODE_DIO
+oak.build.flash_freq=40
+oak.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+oak.menu.eesz.4M2M.build.flash_size=4M
+oak.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+oak.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+oak.menu.eesz.4M2M.build.spiffs_pagesize=256
+oak.menu.eesz.4M2M.upload.maximum_size=1044464
+oak.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+oak.menu.eesz.4M2M.build.spiffs_start=0x200000
+oak.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+oak.menu.eesz.4M2M.build.spiffs_blocksize=8192
+oak.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+oak.menu.eesz.4M3M.build.flash_size=4M
+oak.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+oak.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+oak.menu.eesz.4M3M.build.spiffs_pagesize=256
+oak.menu.eesz.4M3M.upload.maximum_size=1044464
+oak.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+oak.menu.eesz.4M3M.build.spiffs_start=0x100000
+oak.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+oak.menu.eesz.4M3M.build.spiffs_blocksize=8192
+oak.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+oak.menu.eesz.4M1M.build.flash_size=4M
+oak.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+oak.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+oak.menu.eesz.4M1M.build.spiffs_pagesize=256
+oak.menu.eesz.4M1M.upload.maximum_size=1044464
+oak.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+oak.menu.eesz.4M1M.build.spiffs_start=0x300000
+oak.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+oak.menu.eesz.4M1M.build.spiffs_blocksize=8192
+oak.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+oak.menu.eesz.4M.build.flash_size=4M
+oak.menu.eesz.4M.build.flash_size_bytes=0x400000
+oak.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+oak.menu.eesz.4M.build.spiffs_pagesize=256
+oak.menu.eesz.4M.upload.maximum_size=1044464
+oak.menu.eesz.4M.build.rfcal_addr=0x3FC000
+oak.menu.ip.lm2f=v2 Lower Memory
+oak.menu.ip.lm2f.build.lwip_include=lwip2/include
+oak.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+oak.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+oak.menu.ip.hb2f=v2 Higher Bandwidth
+oak.menu.ip.hb2f.build.lwip_include=lwip2/include
+oak.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+oak.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+oak.menu.ip.lm2n=v2 Lower Memory (no features)
+oak.menu.ip.lm2n.build.lwip_include=lwip2/include
+oak.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+oak.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+oak.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+oak.menu.ip.hb2n.build.lwip_include=lwip2/include
+oak.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+oak.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+oak.menu.ip.lm6f=v2 IPv6 Lower Memory
+oak.menu.ip.lm6f.build.lwip_include=lwip2/include
+oak.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+oak.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+oak.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+oak.menu.ip.hb6f.build.lwip_include=lwip2/include
+oak.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+oak.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+oak.menu.ip.hb1=v1.4 Higher Bandwidth
+oak.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+oak.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+oak.menu.ip.src=v1.4 Compile from source
+oak.menu.ip.src.build.lwip_lib=-llwip_src
+oak.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+oak.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+oak.menu.dbg.Disabled=Disabled
+oak.menu.dbg.Disabled.build.debug_port=
+oak.menu.dbg.Serial=Serial
+oak.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+oak.menu.dbg.Serial1=Serial1
+oak.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+oak.menu.lvl.None____=None
+oak.menu.lvl.None____.build.debug_level=
+oak.menu.lvl.SSL=SSL
+oak.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+oak.menu.lvl.TLS_MEM=TLS_MEM
+oak.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+oak.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+oak.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+oak.menu.lvl.HTTP_SERVER=HTTP_SERVER
+oak.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+oak.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+oak.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+oak.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+oak.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+oak.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+oak.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+oak.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+oak.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+oak.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+oak.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+oak.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+oak.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+oak.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+oak.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+oak.menu.lvl.CORE=CORE
+oak.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+oak.menu.lvl.WIFI=WIFI
+oak.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+oak.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+oak.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+oak.menu.lvl.UPDATER=UPDATER
+oak.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+oak.menu.lvl.OTA=OTA
+oak.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+oak.menu.lvl.OOM=OOM
+oak.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+oak.menu.lvl.MDNS=MDNS
+oak.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+oak.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+oak.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+oak.menu.wipe.none=Only Sketch
+oak.menu.wipe.none.upload.erase_cmd=version
+oak.menu.wipe.sdk=Sketch + WiFi Settings
+oak.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+oak.menu.wipe.all=All Flash Contents
+oak.menu.wipe.all.upload.erase_cmd=erase_flash
+oak.menu.baud.921600=921600
+oak.menu.baud.921600.upload.speed=921600
+oak.menu.baud.57600=57600
+oak.menu.baud.57600.upload.speed=57600
+oak.menu.baud.115200=115200
+oak.menu.baud.115200.upload.speed=115200
+oak.menu.baud.230400.linux=230400
+oak.menu.baud.230400.macosx=230400
+oak.menu.baud.230400.upload.speed=230400
+oak.menu.baud.256000.windows=256000
+oak.menu.baud.256000.upload.speed=256000
+oak.menu.baud.460800.linux=460800
+oak.menu.baud.460800.macosx=460800
+oak.menu.baud.460800.upload.speed=460800
+oak.menu.baud.512000.windows=512000
+oak.menu.baud.512000.upload.speed=512000
+oak.menu.baud.3000000=3000000
+oak.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+wifiduino.name=WiFiduino
+wifiduino.build.board=WIFIDUINO_ESP8266
+wifiduino.build.variant=wifiduino
+wifiduino.upload.tool=esptool
+wifiduino.upload.maximum_data_size=81920
+wifiduino.upload.wait_for_upload_port=true
+wifiduino.upload.erase_cmd=version
+wifiduino.serial.disableDTR=true
+wifiduino.serial.disableRTS=true
+wifiduino.build.mcu=esp8266
+wifiduino.build.core=esp8266
+wifiduino.build.spiffs_pagesize=256
+wifiduino.build.debug_port=
+wifiduino.build.debug_level=
+wifiduino.menu.xtal.80=80 MHz
+wifiduino.menu.xtal.80.build.f_cpu=80000000L
+wifiduino.menu.xtal.160=160 MHz
+wifiduino.menu.xtal.160.build.f_cpu=160000000L
+wifiduino.menu.vt.flash=Flash
+wifiduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+wifiduino.menu.vt.heap=Heap
+wifiduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+wifiduino.menu.vt.iram=IRAM
+wifiduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+wifiduino.menu.exception.legacy=Legacy (new can return nullptr)
+wifiduino.menu.exception.legacy.build.exception_flags=-fno-exceptions
+wifiduino.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+wifiduino.menu.exception.disabled=Disabled (new can abort)
+wifiduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+wifiduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+wifiduino.menu.exception.enabled=Enabled
+wifiduino.menu.exception.enabled.build.exception_flags=-fexceptions
+wifiduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+wifiduino.menu.ssl.all=All SSL ciphers (most compatible)
+wifiduino.menu.ssl.all.build.sslflags=
+wifiduino.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+wifiduino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+wifiduino.upload.resetmethod=nodemcu
+wifiduino.build.flash_mode=dio
+wifiduino.build.flash_flags=-DFLASHMODE_DIO
+wifiduino.build.flash_freq=40
+wifiduino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+wifiduino.menu.eesz.4M2M.build.flash_size=4M
+wifiduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+wifiduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+wifiduino.menu.eesz.4M2M.build.spiffs_pagesize=256
+wifiduino.menu.eesz.4M2M.upload.maximum_size=1044464
+wifiduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+wifiduino.menu.eesz.4M2M.build.spiffs_start=0x200000
+wifiduino.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+wifiduino.menu.eesz.4M2M.build.spiffs_blocksize=8192
+wifiduino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+wifiduino.menu.eesz.4M3M.build.flash_size=4M
+wifiduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+wifiduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+wifiduino.menu.eesz.4M3M.build.spiffs_pagesize=256
+wifiduino.menu.eesz.4M3M.upload.maximum_size=1044464
+wifiduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+wifiduino.menu.eesz.4M3M.build.spiffs_start=0x100000
+wifiduino.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+wifiduino.menu.eesz.4M3M.build.spiffs_blocksize=8192
+wifiduino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+wifiduino.menu.eesz.4M1M.build.flash_size=4M
+wifiduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+wifiduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+wifiduino.menu.eesz.4M1M.build.spiffs_pagesize=256
+wifiduino.menu.eesz.4M1M.upload.maximum_size=1044464
+wifiduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+wifiduino.menu.eesz.4M1M.build.spiffs_start=0x300000
+wifiduino.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+wifiduino.menu.eesz.4M1M.build.spiffs_blocksize=8192
+wifiduino.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+wifiduino.menu.eesz.4M.build.flash_size=4M
+wifiduino.menu.eesz.4M.build.flash_size_bytes=0x400000
+wifiduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+wifiduino.menu.eesz.4M.build.spiffs_pagesize=256
+wifiduino.menu.eesz.4M.upload.maximum_size=1044464
+wifiduino.menu.eesz.4M.build.rfcal_addr=0x3FC000
+wifiduino.menu.ip.lm2f=v2 Lower Memory
+wifiduino.menu.ip.lm2f.build.lwip_include=lwip2/include
+wifiduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+wifiduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+wifiduino.menu.ip.hb2f=v2 Higher Bandwidth
+wifiduino.menu.ip.hb2f.build.lwip_include=lwip2/include
+wifiduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+wifiduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+wifiduino.menu.ip.lm2n=v2 Lower Memory (no features)
+wifiduino.menu.ip.lm2n.build.lwip_include=lwip2/include
+wifiduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+wifiduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+wifiduino.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+wifiduino.menu.ip.hb2n.build.lwip_include=lwip2/include
+wifiduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+wifiduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+wifiduino.menu.ip.lm6f=v2 IPv6 Lower Memory
+wifiduino.menu.ip.lm6f.build.lwip_include=lwip2/include
+wifiduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+wifiduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+wifiduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+wifiduino.menu.ip.hb6f.build.lwip_include=lwip2/include
+wifiduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+wifiduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+wifiduino.menu.ip.hb1=v1.4 Higher Bandwidth
+wifiduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+wifiduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+wifiduino.menu.ip.src=v1.4 Compile from source
+wifiduino.menu.ip.src.build.lwip_lib=-llwip_src
+wifiduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+wifiduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+wifiduino.menu.dbg.Disabled=Disabled
+wifiduino.menu.dbg.Disabled.build.debug_port=
+wifiduino.menu.dbg.Serial=Serial
+wifiduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+wifiduino.menu.dbg.Serial1=Serial1
+wifiduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+wifiduino.menu.lvl.None____=None
+wifiduino.menu.lvl.None____.build.debug_level=
+wifiduino.menu.lvl.SSL=SSL
+wifiduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+wifiduino.menu.lvl.TLS_MEM=TLS_MEM
+wifiduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+wifiduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+wifiduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+wifiduino.menu.lvl.HTTP_SERVER=HTTP_SERVER
+wifiduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+wifiduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+wifiduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+wifiduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+wifiduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+wifiduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+wifiduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+wifiduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+wifiduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifiduino.menu.lvl.CORE=CORE
+wifiduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+wifiduino.menu.lvl.WIFI=WIFI
+wifiduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+wifiduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+wifiduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+wifiduino.menu.lvl.UPDATER=UPDATER
+wifiduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+wifiduino.menu.lvl.OTA=OTA
+wifiduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+wifiduino.menu.lvl.OOM=OOM
+wifiduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+wifiduino.menu.lvl.MDNS=MDNS
+wifiduino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+wifiduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+wifiduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+wifiduino.menu.wipe.none=Only Sketch
+wifiduino.menu.wipe.none.upload.erase_cmd=version
+wifiduino.menu.wipe.sdk=Sketch + WiFi Settings
+wifiduino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+wifiduino.menu.wipe.all=All Flash Contents
+wifiduino.menu.wipe.all.upload.erase_cmd=erase_flash
+wifiduino.menu.baud.921600=921600
+wifiduino.menu.baud.921600.upload.speed=921600
+wifiduino.menu.baud.57600=57600
+wifiduino.menu.baud.57600.upload.speed=57600
+wifiduino.menu.baud.115200=115200
+wifiduino.menu.baud.115200.upload.speed=115200
+wifiduino.menu.baud.230400.linux=230400
+wifiduino.menu.baud.230400.macosx=230400
+wifiduino.menu.baud.230400.upload.speed=230400
+wifiduino.menu.baud.256000.windows=256000
+wifiduino.menu.baud.256000.upload.speed=256000
+wifiduino.menu.baud.460800.linux=460800
+wifiduino.menu.baud.460800.macosx=460800
+wifiduino.menu.baud.460800.upload.speed=460800
+wifiduino.menu.baud.512000.windows=512000
+wifiduino.menu.baud.512000.upload.speed=512000
+wifiduino.menu.baud.3000000=3000000
+wifiduino.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+wifi_slot.name=Amperka WiFi Slot
+wifi_slot.build.board=AMPERKA_WIFI_SLOT
+wifi_slot.build.variant=wifi_slot
+wifi_slot.upload.tool=esptool
+wifi_slot.upload.maximum_data_size=81920
+wifi_slot.upload.wait_for_upload_port=true
+wifi_slot.upload.erase_cmd=version
+wifi_slot.serial.disableDTR=true
+wifi_slot.serial.disableRTS=true
+wifi_slot.build.mcu=esp8266
+wifi_slot.build.core=esp8266
+wifi_slot.build.spiffs_pagesize=256
+wifi_slot.build.debug_port=
+wifi_slot.build.debug_level=
+wifi_slot.menu.xtal.80=80 MHz
+wifi_slot.menu.xtal.80.build.f_cpu=80000000L
+wifi_slot.menu.xtal.160=160 MHz
+wifi_slot.menu.xtal.160.build.f_cpu=160000000L
+wifi_slot.menu.vt.flash=Flash
+wifi_slot.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+wifi_slot.menu.vt.heap=Heap
+wifi_slot.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+wifi_slot.menu.vt.iram=IRAM
+wifi_slot.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+wifi_slot.menu.exception.legacy=Legacy (new can return nullptr)
+wifi_slot.menu.exception.legacy.build.exception_flags=-fno-exceptions
+wifi_slot.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+wifi_slot.menu.exception.disabled=Disabled (new can abort)
+wifi_slot.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+wifi_slot.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+wifi_slot.menu.exception.enabled=Enabled
+wifi_slot.menu.exception.enabled.build.exception_flags=-fexceptions
+wifi_slot.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+wifi_slot.menu.ssl.all=All SSL ciphers (most compatible)
+wifi_slot.menu.ssl.all.build.sslflags=
+wifi_slot.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+wifi_slot.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+wifi_slot.upload.resetmethod=nodemcu
+wifi_slot.menu.FlashFreq.40=40MHz
+wifi_slot.menu.FlashFreq.40.build.flash_freq=40
+wifi_slot.menu.FlashFreq.80=80MHz
+wifi_slot.menu.FlashFreq.80.build.flash_freq=80
+wifi_slot.menu.FlashFreq.20=20MHz
+wifi_slot.menu.FlashFreq.20.build.flash_freq=20
+wifi_slot.menu.FlashFreq.26=26MHz
+wifi_slot.menu.FlashFreq.26.build.flash_freq=26
+wifi_slot.menu.FlashMode.dout=DOUT (compatible)
+wifi_slot.menu.FlashMode.dout.build.flash_mode=dout
+wifi_slot.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT
+wifi_slot.menu.FlashMode.dio=DIO
+wifi_slot.menu.FlashMode.dio.build.flash_mode=dio
+wifi_slot.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO
+wifi_slot.menu.FlashMode.qout=QOUT
+wifi_slot.menu.FlashMode.qout.build.flash_mode=qout
+wifi_slot.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT
+wifi_slot.menu.FlashMode.qio=QIO (fast)
+wifi_slot.menu.FlashMode.qio.build.flash_mode=qio
+wifi_slot.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO
+wifi_slot.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB)
+wifi_slot.menu.eesz.1M64.build.flash_size=1M
+wifi_slot.menu.eesz.1M64.build.flash_size_bytes=0x100000
+wifi_slot.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld
+wifi_slot.menu.eesz.1M64.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.1M64.upload.maximum_size=958448
+wifi_slot.menu.eesz.1M64.build.rfcal_addr=0xFC000
+wifi_slot.menu.eesz.1M64.build.spiffs_start=0xEB000
+wifi_slot.menu.eesz.1M64.build.spiffs_end=0xFB000
+wifi_slot.menu.eesz.1M64.build.spiffs_blocksize=4096
+wifi_slot.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB)
+wifi_slot.menu.eesz.1M128.build.flash_size=1M
+wifi_slot.menu.eesz.1M128.build.flash_size_bytes=0x100000
+wifi_slot.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld
+wifi_slot.menu.eesz.1M128.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.1M128.upload.maximum_size=892912
+wifi_slot.menu.eesz.1M128.build.rfcal_addr=0xFC000
+wifi_slot.menu.eesz.1M128.build.spiffs_start=0xDB000
+wifi_slot.menu.eesz.1M128.build.spiffs_end=0xFB000
+wifi_slot.menu.eesz.1M128.build.spiffs_blocksize=4096
+wifi_slot.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB)
+wifi_slot.menu.eesz.1M144.build.flash_size=1M
+wifi_slot.menu.eesz.1M144.build.flash_size_bytes=0x100000
+wifi_slot.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld
+wifi_slot.menu.eesz.1M144.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.1M144.upload.maximum_size=876528
+wifi_slot.menu.eesz.1M144.build.rfcal_addr=0xFC000
+wifi_slot.menu.eesz.1M144.build.spiffs_start=0xD7000
+wifi_slot.menu.eesz.1M144.build.spiffs_end=0xFB000
+wifi_slot.menu.eesz.1M144.build.spiffs_blocksize=4096
+wifi_slot.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB)
+wifi_slot.menu.eesz.1M160.build.flash_size=1M
+wifi_slot.menu.eesz.1M160.build.flash_size_bytes=0x100000
+wifi_slot.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld
+wifi_slot.menu.eesz.1M160.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.1M160.upload.maximum_size=860144
+wifi_slot.menu.eesz.1M160.build.rfcal_addr=0xFC000
+wifi_slot.menu.eesz.1M160.build.spiffs_start=0xD3000
+wifi_slot.menu.eesz.1M160.build.spiffs_end=0xFB000
+wifi_slot.menu.eesz.1M160.build.spiffs_blocksize=4096
+wifi_slot.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB)
+wifi_slot.menu.eesz.1M192.build.flash_size=1M
+wifi_slot.menu.eesz.1M192.build.flash_size_bytes=0x100000
+wifi_slot.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld
+wifi_slot.menu.eesz.1M192.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.1M192.upload.maximum_size=827376
+wifi_slot.menu.eesz.1M192.build.rfcal_addr=0xFC000
+wifi_slot.menu.eesz.1M192.build.spiffs_start=0xCB000
+wifi_slot.menu.eesz.1M192.build.spiffs_end=0xFB000
+wifi_slot.menu.eesz.1M192.build.spiffs_blocksize=4096
+wifi_slot.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB)
+wifi_slot.menu.eesz.1M256.build.flash_size=1M
+wifi_slot.menu.eesz.1M256.build.flash_size_bytes=0x100000
+wifi_slot.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld
+wifi_slot.menu.eesz.1M256.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.1M256.upload.maximum_size=761840
+wifi_slot.menu.eesz.1M256.build.rfcal_addr=0xFC000
+wifi_slot.menu.eesz.1M256.build.spiffs_start=0xBB000
+wifi_slot.menu.eesz.1M256.build.spiffs_end=0xFB000
+wifi_slot.menu.eesz.1M256.build.spiffs_blocksize=4096
+wifi_slot.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB)
+wifi_slot.menu.eesz.1M512.build.flash_size=1M
+wifi_slot.menu.eesz.1M512.build.flash_size_bytes=0x100000
+wifi_slot.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld
+wifi_slot.menu.eesz.1M512.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.1M512.upload.maximum_size=499696
+wifi_slot.menu.eesz.1M512.build.rfcal_addr=0xFC000
+wifi_slot.menu.eesz.1M512.build.spiffs_start=0x7B000
+wifi_slot.menu.eesz.1M512.build.spiffs_end=0xFB000
+wifi_slot.menu.eesz.1M512.build.spiffs_blocksize=8192
+wifi_slot.menu.eesz.1M=1MB (FS:none OTA:~502KB)
+wifi_slot.menu.eesz.1M.build.flash_size=1M
+wifi_slot.menu.eesz.1M.build.flash_size_bytes=0x100000
+wifi_slot.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld
+wifi_slot.menu.eesz.1M.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.1M.upload.maximum_size=1023984
+wifi_slot.menu.eesz.1M.build.rfcal_addr=0xFC000
+wifi_slot.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB)
+wifi_slot.menu.eesz.2M64.build.flash_size=2M
+wifi_slot.menu.eesz.2M64.build.flash_size_bytes=0x200000
+wifi_slot.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld
+wifi_slot.menu.eesz.2M64.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.2M64.upload.maximum_size=1044464
+wifi_slot.menu.eesz.2M64.build.rfcal_addr=0x1FC000
+wifi_slot.menu.eesz.2M64.build.spiffs_start=0x1F0000
+wifi_slot.menu.eesz.2M64.build.spiffs_end=0x1FB000
+wifi_slot.menu.eesz.2M64.build.spiffs_blocksize=4096
+wifi_slot.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB)
+wifi_slot.menu.eesz.2M128.build.flash_size=2M
+wifi_slot.menu.eesz.2M128.build.flash_size_bytes=0x200000
+wifi_slot.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld
+wifi_slot.menu.eesz.2M128.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.2M128.upload.maximum_size=1044464
+wifi_slot.menu.eesz.2M128.build.rfcal_addr=0x1FC000
+wifi_slot.menu.eesz.2M128.build.spiffs_start=0x1E0000
+wifi_slot.menu.eesz.2M128.build.spiffs_end=0x1FB000
+wifi_slot.menu.eesz.2M128.build.spiffs_blocksize=4096
+wifi_slot.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB)
+wifi_slot.menu.eesz.2M256.build.flash_size=2M
+wifi_slot.menu.eesz.2M256.build.flash_size_bytes=0x200000
+wifi_slot.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld
+wifi_slot.menu.eesz.2M256.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.2M256.upload.maximum_size=1044464
+wifi_slot.menu.eesz.2M256.build.rfcal_addr=0x1FC000
+wifi_slot.menu.eesz.2M256.build.spiffs_start=0x1C0000
+wifi_slot.menu.eesz.2M256.build.spiffs_end=0x1FB000
+wifi_slot.menu.eesz.2M256.build.spiffs_blocksize=4096
+wifi_slot.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB)
+wifi_slot.menu.eesz.2M512.build.flash_size=2M
+wifi_slot.menu.eesz.2M512.build.flash_size_bytes=0x200000
+wifi_slot.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld
+wifi_slot.menu.eesz.2M512.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.2M512.upload.maximum_size=1044464
+wifi_slot.menu.eesz.2M512.build.rfcal_addr=0x1FC000
+wifi_slot.menu.eesz.2M512.build.spiffs_start=0x180000
+wifi_slot.menu.eesz.2M512.build.spiffs_end=0x1FA000
+wifi_slot.menu.eesz.2M512.build.spiffs_blocksize=8192
+wifi_slot.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB)
+wifi_slot.menu.eesz.2M1M.build.flash_size=2M
+wifi_slot.menu.eesz.2M1M.build.flash_size_bytes=0x200000
+wifi_slot.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld
+wifi_slot.menu.eesz.2M1M.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.2M1M.upload.maximum_size=1044464
+wifi_slot.menu.eesz.2M1M.build.rfcal_addr=0x1FC000
+wifi_slot.menu.eesz.2M1M.build.spiffs_start=0x100000
+wifi_slot.menu.eesz.2M1M.build.spiffs_end=0x1FA000
+wifi_slot.menu.eesz.2M1M.build.spiffs_blocksize=8192
+wifi_slot.menu.eesz.2M=2MB (FS:none OTA:~1019KB)
+wifi_slot.menu.eesz.2M.build.flash_size=2M
+wifi_slot.menu.eesz.2M.build.flash_size_bytes=0x200000
+wifi_slot.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld
+wifi_slot.menu.eesz.2M.build.spiffs_pagesize=256
+wifi_slot.menu.eesz.2M.upload.maximum_size=1044464
+wifi_slot.menu.eesz.2M.build.rfcal_addr=0x1FC000
+wifi_slot.menu.ip.lm2f=v2 Lower Memory
+wifi_slot.menu.ip.lm2f.build.lwip_include=lwip2/include
+wifi_slot.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+wifi_slot.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+wifi_slot.menu.ip.hb2f=v2 Higher Bandwidth
+wifi_slot.menu.ip.hb2f.build.lwip_include=lwip2/include
+wifi_slot.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+wifi_slot.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+wifi_slot.menu.ip.lm2n=v2 Lower Memory (no features)
+wifi_slot.menu.ip.lm2n.build.lwip_include=lwip2/include
+wifi_slot.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+wifi_slot.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+wifi_slot.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+wifi_slot.menu.ip.hb2n.build.lwip_include=lwip2/include
+wifi_slot.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+wifi_slot.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+wifi_slot.menu.ip.lm6f=v2 IPv6 Lower Memory
+wifi_slot.menu.ip.lm6f.build.lwip_include=lwip2/include
+wifi_slot.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+wifi_slot.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+wifi_slot.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+wifi_slot.menu.ip.hb6f.build.lwip_include=lwip2/include
+wifi_slot.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+wifi_slot.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+wifi_slot.menu.ip.hb1=v1.4 Higher Bandwidth
+wifi_slot.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+wifi_slot.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+wifi_slot.menu.ip.src=v1.4 Compile from source
+wifi_slot.menu.ip.src.build.lwip_lib=-llwip_src
+wifi_slot.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+wifi_slot.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+wifi_slot.menu.dbg.Disabled=Disabled
+wifi_slot.menu.dbg.Disabled.build.debug_port=
+wifi_slot.menu.dbg.Serial=Serial
+wifi_slot.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+wifi_slot.menu.dbg.Serial1=Serial1
+wifi_slot.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+wifi_slot.menu.lvl.None____=None
+wifi_slot.menu.lvl.None____.build.debug_level=
+wifi_slot.menu.lvl.SSL=SSL
+wifi_slot.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+wifi_slot.menu.lvl.TLS_MEM=TLS_MEM
+wifi_slot.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+wifi_slot.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+wifi_slot.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+wifi_slot.menu.lvl.HTTP_SERVER=HTTP_SERVER
+wifi_slot.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+wifi_slot.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+wifi_slot.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+wifi_slot.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+wifi_slot.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+wifi_slot.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+wifi_slot.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wifi_slot.menu.lvl.CORE=CORE
+wifi_slot.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+wifi_slot.menu.lvl.WIFI=WIFI
+wifi_slot.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+wifi_slot.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+wifi_slot.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+wifi_slot.menu.lvl.UPDATER=UPDATER
+wifi_slot.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+wifi_slot.menu.lvl.OTA=OTA
+wifi_slot.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+wifi_slot.menu.lvl.OOM=OOM
+wifi_slot.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+wifi_slot.menu.lvl.MDNS=MDNS
+wifi_slot.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+wifi_slot.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+wifi_slot.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+wifi_slot.menu.wipe.none=Only Sketch
+wifi_slot.menu.wipe.none.upload.erase_cmd=version
+wifi_slot.menu.wipe.sdk=Sketch + WiFi Settings
+wifi_slot.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+wifi_slot.menu.wipe.all=All Flash Contents
+wifi_slot.menu.wipe.all.upload.erase_cmd=erase_flash
+wifi_slot.menu.baud.115200=115200
+wifi_slot.menu.baud.115200.upload.speed=115200
+wifi_slot.menu.baud.57600=57600
+wifi_slot.menu.baud.57600.upload.speed=57600
+wifi_slot.menu.baud.230400.linux=230400
+wifi_slot.menu.baud.230400.macosx=230400
+wifi_slot.menu.baud.230400.upload.speed=230400
+wifi_slot.menu.baud.256000.windows=256000
+wifi_slot.menu.baud.256000.upload.speed=256000
+wifi_slot.menu.baud.460800.linux=460800
+wifi_slot.menu.baud.460800.macosx=460800
+wifi_slot.menu.baud.460800.upload.speed=460800
+wifi_slot.menu.baud.512000.windows=512000
+wifi_slot.menu.baud.512000.upload.speed=512000
+wifi_slot.menu.baud.921600=921600
+wifi_slot.menu.baud.921600.upload.speed=921600
+wifi_slot.menu.baud.3000000=3000000
+wifi_slot.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+wiolink.name=Seeed Wio Link
+wiolink.build.board=ESP8266_WIO_LINK
+wiolink.build.variant=wiolink
+wiolink.upload.tool=esptool
+wiolink.upload.maximum_data_size=81920
+wiolink.upload.wait_for_upload_port=true
+wiolink.upload.erase_cmd=version
+wiolink.serial.disableDTR=true
+wiolink.serial.disableRTS=true
+wiolink.build.mcu=esp8266
+wiolink.build.core=esp8266
+wiolink.build.spiffs_pagesize=256
+wiolink.build.debug_port=
+wiolink.build.debug_level=
+wiolink.menu.xtal.80=80 MHz
+wiolink.menu.xtal.80.build.f_cpu=80000000L
+wiolink.menu.xtal.160=160 MHz
+wiolink.menu.xtal.160.build.f_cpu=160000000L
+wiolink.menu.vt.flash=Flash
+wiolink.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+wiolink.menu.vt.heap=Heap
+wiolink.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+wiolink.menu.vt.iram=IRAM
+wiolink.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+wiolink.menu.exception.legacy=Legacy (new can return nullptr)
+wiolink.menu.exception.legacy.build.exception_flags=-fno-exceptions
+wiolink.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+wiolink.menu.exception.disabled=Disabled (new can abort)
+wiolink.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+wiolink.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+wiolink.menu.exception.enabled=Enabled
+wiolink.menu.exception.enabled.build.exception_flags=-fexceptions
+wiolink.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+wiolink.menu.ssl.all=All SSL ciphers (most compatible)
+wiolink.menu.ssl.all.build.sslflags=
+wiolink.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+wiolink.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+wiolink.upload.resetmethod=nodemcu
+wiolink.build.flash_mode=qio
+wiolink.build.flash_flags=-DFLASHMODE_QIO
+wiolink.build.flash_freq=40
+wiolink.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+wiolink.menu.eesz.4M2M.build.flash_size=4M
+wiolink.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+wiolink.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+wiolink.menu.eesz.4M2M.build.spiffs_pagesize=256
+wiolink.menu.eesz.4M2M.upload.maximum_size=1044464
+wiolink.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+wiolink.menu.eesz.4M2M.build.spiffs_start=0x200000
+wiolink.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+wiolink.menu.eesz.4M2M.build.spiffs_blocksize=8192
+wiolink.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+wiolink.menu.eesz.4M3M.build.flash_size=4M
+wiolink.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+wiolink.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+wiolink.menu.eesz.4M3M.build.spiffs_pagesize=256
+wiolink.menu.eesz.4M3M.upload.maximum_size=1044464
+wiolink.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+wiolink.menu.eesz.4M3M.build.spiffs_start=0x100000
+wiolink.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+wiolink.menu.eesz.4M3M.build.spiffs_blocksize=8192
+wiolink.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+wiolink.menu.eesz.4M1M.build.flash_size=4M
+wiolink.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+wiolink.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+wiolink.menu.eesz.4M1M.build.spiffs_pagesize=256
+wiolink.menu.eesz.4M1M.upload.maximum_size=1044464
+wiolink.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+wiolink.menu.eesz.4M1M.build.spiffs_start=0x300000
+wiolink.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+wiolink.menu.eesz.4M1M.build.spiffs_blocksize=8192
+wiolink.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+wiolink.menu.eesz.4M.build.flash_size=4M
+wiolink.menu.eesz.4M.build.flash_size_bytes=0x400000
+wiolink.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+wiolink.menu.eesz.4M.build.spiffs_pagesize=256
+wiolink.menu.eesz.4M.upload.maximum_size=1044464
+wiolink.menu.eesz.4M.build.rfcal_addr=0x3FC000
+wiolink.menu.ip.lm2f=v2 Lower Memory
+wiolink.menu.ip.lm2f.build.lwip_include=lwip2/include
+wiolink.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+wiolink.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+wiolink.menu.ip.hb2f=v2 Higher Bandwidth
+wiolink.menu.ip.hb2f.build.lwip_include=lwip2/include
+wiolink.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+wiolink.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+wiolink.menu.ip.lm2n=v2 Lower Memory (no features)
+wiolink.menu.ip.lm2n.build.lwip_include=lwip2/include
+wiolink.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+wiolink.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+wiolink.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+wiolink.menu.ip.hb2n.build.lwip_include=lwip2/include
+wiolink.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+wiolink.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+wiolink.menu.ip.lm6f=v2 IPv6 Lower Memory
+wiolink.menu.ip.lm6f.build.lwip_include=lwip2/include
+wiolink.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+wiolink.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+wiolink.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+wiolink.menu.ip.hb6f.build.lwip_include=lwip2/include
+wiolink.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+wiolink.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+wiolink.menu.ip.hb1=v1.4 Higher Bandwidth
+wiolink.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+wiolink.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+wiolink.menu.ip.src=v1.4 Compile from source
+wiolink.menu.ip.src.build.lwip_lib=-llwip_src
+wiolink.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+wiolink.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+wiolink.menu.dbg.Disabled=Disabled
+wiolink.menu.dbg.Disabled.build.debug_port=
+wiolink.menu.dbg.Serial=Serial
+wiolink.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+wiolink.menu.dbg.Serial1=Serial1
+wiolink.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+wiolink.menu.lvl.None____=None
+wiolink.menu.lvl.None____.build.debug_level=
+wiolink.menu.lvl.SSL=SSL
+wiolink.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+wiolink.menu.lvl.TLS_MEM=TLS_MEM
+wiolink.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+wiolink.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+wiolink.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+wiolink.menu.lvl.HTTP_SERVER=HTTP_SERVER
+wiolink.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+wiolink.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+wiolink.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+wiolink.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+wiolink.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+wiolink.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+wiolink.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+wiolink.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+wiolink.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+wiolink.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+wiolink.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+wiolink.menu.lvl.CORE=CORE
+wiolink.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+wiolink.menu.lvl.WIFI=WIFI
+wiolink.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+wiolink.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+wiolink.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+wiolink.menu.lvl.UPDATER=UPDATER
+wiolink.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+wiolink.menu.lvl.OTA=OTA
+wiolink.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+wiolink.menu.lvl.OOM=OOM
+wiolink.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+wiolink.menu.lvl.MDNS=MDNS
+wiolink.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+wiolink.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+wiolink.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+wiolink.menu.wipe.none=Only Sketch
+wiolink.menu.wipe.none.upload.erase_cmd=version
+wiolink.menu.wipe.sdk=Sketch + WiFi Settings
+wiolink.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+wiolink.menu.wipe.all=All Flash Contents
+wiolink.menu.wipe.all.upload.erase_cmd=erase_flash
+wiolink.menu.baud.115200=115200
+wiolink.menu.baud.115200.upload.speed=115200
+wiolink.menu.baud.57600=57600
+wiolink.menu.baud.57600.upload.speed=57600
+wiolink.menu.baud.230400.linux=230400
+wiolink.menu.baud.230400.macosx=230400
+wiolink.menu.baud.230400.upload.speed=230400
+wiolink.menu.baud.256000.windows=256000
+wiolink.menu.baud.256000.upload.speed=256000
+wiolink.menu.baud.460800.linux=460800
+wiolink.menu.baud.460800.macosx=460800
+wiolink.menu.baud.460800.upload.speed=460800
+wiolink.menu.baud.512000.windows=512000
+wiolink.menu.baud.512000.upload.speed=512000
+wiolink.menu.baud.921600=921600
+wiolink.menu.baud.921600.upload.speed=921600
+wiolink.menu.baud.3000000=3000000
+wiolink.menu.baud.3000000.upload.speed=3000000
+
+##############################################################
+espectro.name=ESPectro Core
+espectro.build.board=ESP8266_ESPECTRO_CORE
+espectro.build.variant=espectro
+espectro.upload.tool=esptool
+espectro.upload.maximum_data_size=81920
+espectro.upload.wait_for_upload_port=true
+espectro.upload.erase_cmd=version
+espectro.serial.disableDTR=true
+espectro.serial.disableRTS=true
+espectro.build.mcu=esp8266
+espectro.build.core=esp8266
+espectro.build.spiffs_pagesize=256
+espectro.build.debug_port=
+espectro.build.debug_level=
+espectro.menu.xtal.80=80 MHz
+espectro.menu.xtal.80.build.f_cpu=80000000L
+espectro.menu.xtal.160=160 MHz
+espectro.menu.xtal.160.build.f_cpu=160000000L
+espectro.menu.vt.flash=Flash
+espectro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH
+espectro.menu.vt.heap=Heap
+espectro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM
+espectro.menu.vt.iram=IRAM
+espectro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM
+espectro.menu.exception.legacy=Legacy (new can return nullptr)
+espectro.menu.exception.legacy.build.exception_flags=-fno-exceptions
+espectro.menu.exception.legacy.build.stdcpp_lib=-lstdc++
+espectro.menu.exception.disabled=Disabled (new can abort)
+espectro.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT
+espectro.menu.exception.disabled.build.stdcpp_lib=-lstdc++
+espectro.menu.exception.enabled=Enabled
+espectro.menu.exception.enabled.build.exception_flags=-fexceptions
+espectro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc
+espectro.menu.ssl.all=All SSL ciphers (most compatible)
+espectro.menu.ssl.all.build.sslflags=
+espectro.menu.ssl.basic=Basic SSL ciphers (lower ROM use)
+espectro.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC
+espectro.upload.resetmethod=nodemcu
+espectro.build.flash_mode=dio
+espectro.build.flash_flags=-DFLASHMODE_DIO
+espectro.build.flash_freq=40
+espectro.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
+espectro.menu.eesz.4M2M.build.flash_size=4M
+espectro.menu.eesz.4M2M.build.flash_size_bytes=0x400000
+espectro.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
+espectro.menu.eesz.4M2M.build.spiffs_pagesize=256
+espectro.menu.eesz.4M2M.upload.maximum_size=1044464
+espectro.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
+espectro.menu.eesz.4M2M.build.spiffs_start=0x200000
+espectro.menu.eesz.4M2M.build.spiffs_end=0x3FA000
+espectro.menu.eesz.4M2M.build.spiffs_blocksize=8192
+espectro.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
+espectro.menu.eesz.4M3M.build.flash_size=4M
+espectro.menu.eesz.4M3M.build.flash_size_bytes=0x400000
+espectro.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
+espectro.menu.eesz.4M3M.build.spiffs_pagesize=256
+espectro.menu.eesz.4M3M.upload.maximum_size=1044464
+espectro.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
+espectro.menu.eesz.4M3M.build.spiffs_start=0x100000
+espectro.menu.eesz.4M3M.build.spiffs_end=0x3FA000
+espectro.menu.eesz.4M3M.build.spiffs_blocksize=8192
+espectro.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
+espectro.menu.eesz.4M1M.build.flash_size=4M
+espectro.menu.eesz.4M1M.build.flash_size_bytes=0x400000
+espectro.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
+espectro.menu.eesz.4M1M.build.spiffs_pagesize=256
+espectro.menu.eesz.4M1M.upload.maximum_size=1044464
+espectro.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
+espectro.menu.eesz.4M1M.build.spiffs_start=0x300000
+espectro.menu.eesz.4M1M.build.spiffs_end=0x3FA000
+espectro.menu.eesz.4M1M.build.spiffs_blocksize=8192
+espectro.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
+espectro.menu.eesz.4M.build.flash_size=4M
+espectro.menu.eesz.4M.build.flash_size_bytes=0x400000
+espectro.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
+espectro.menu.eesz.4M.build.spiffs_pagesize=256
+espectro.menu.eesz.4M.upload.maximum_size=1044464
+espectro.menu.eesz.4M.build.rfcal_addr=0x3FC000
+espectro.menu.ip.lm2f=v2 Lower Memory
+espectro.menu.ip.lm2f.build.lwip_include=lwip2/include
+espectro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
+espectro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espectro.menu.ip.hb2f=v2 Higher Bandwidth
+espectro.menu.ip.hb2f.build.lwip_include=lwip2/include
+espectro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat
+espectro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0
+espectro.menu.ip.lm2n=v2 Lower Memory (no features)
+espectro.menu.ip.lm2n.build.lwip_include=lwip2/include
+espectro.menu.ip.lm2n.build.lwip_lib=-llwip2-536
+espectro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espectro.menu.ip.hb2n=v2 Higher Bandwidth (no features)
+espectro.menu.ip.hb2n.build.lwip_include=lwip2/include
+espectro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460
+espectro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0
+espectro.menu.ip.lm6f=v2 IPv6 Lower Memory
+espectro.menu.ip.lm6f.build.lwip_include=lwip2/include
+espectro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat
+espectro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espectro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth
+espectro.menu.ip.hb6f.build.lwip_include=lwip2/include
+espectro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat
+espectro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1
+espectro.menu.ip.hb1=v1.4 Higher Bandwidth
+espectro.menu.ip.hb1.build.lwip_lib=-llwip_gcc
+espectro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC
+espectro.menu.ip.src=v1.4 Compile from source
+espectro.menu.ip.src.build.lwip_lib=-llwip_src
+espectro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC
+espectro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-"
+espectro.menu.dbg.Disabled=Disabled
+espectro.menu.dbg.Disabled.build.debug_port=
+espectro.menu.dbg.Serial=Serial
+espectro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial
+espectro.menu.dbg.Serial1=Serial1
+espectro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1
+espectro.menu.lvl.None____=None
+espectro.menu.lvl.None____.build.debug_level=
+espectro.menu.lvl.SSL=SSL
+espectro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL
+espectro.menu.lvl.TLS_MEM=TLS_MEM
+espectro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM
+espectro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT
+espectro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT
+espectro.menu.lvl.HTTP_SERVER=HTTP_SERVER
+espectro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER
+espectro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM
+espectro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM
+espectro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT
+espectro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT
+espectro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER
+espectro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER
+espectro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT
+espectro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espectro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER
+espectro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER
+espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT
+espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT
+espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER
+espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER
+espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER
+espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER
+espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER
+espectro.menu.lvl.CORE=CORE
+espectro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE
+espectro.menu.lvl.WIFI=WIFI
+espectro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI
+espectro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE
+espectro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE
+espectro.menu.lvl.UPDATER=UPDATER
+espectro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER
+espectro.menu.lvl.OTA=OTA
+espectro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA
+espectro.menu.lvl.OOM=OOM
+espectro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM
+espectro.menu.lvl.MDNS=MDNS
+espectro.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS
+espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS
+espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS
+espectro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG
+espectro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG
+espectro.menu.wipe.none=Only Sketch
+espectro.menu.wipe.none.upload.erase_cmd=version
+espectro.menu.wipe.sdk=Sketch + WiFi Settings
+espectro.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000
+espectro.menu.wipe.all=All Flash Contents
+espectro.menu.wipe.all.upload.erase_cmd=erase_flash
+espectro.menu.baud.115200=115200
+espectro.menu.baud.115200.upload.speed=115200
+espectro.menu.baud.57600=57600
+espectro.menu.baud.57600.upload.speed=57600
+espectro.menu.baud.230400.linux=230400
+espectro.menu.baud.230400.macosx=230400
+espectro.menu.baud.230400.upload.speed=230400
+espectro.menu.baud.256000.windows=256000
+espectro.menu.baud.256000.upload.speed=256000
+espectro.menu.baud.460800.linux=460800
+espectro.menu.baud.460800.macosx=460800
+espectro.menu.baud.460800.upload.speed=460800
+espectro.menu.baud.512000.windows=512000
+espectro.menu.baud.512000.upload.speed=512000
+espectro.menu.baud.921600=921600
+espectro.menu.baud.921600.upload.speed=921600
+espectro.menu.baud.3000000=3000000
+espectro.menu.baud.3000000.upload.speed=3000000
+
diff --git a/arduino/version pre-2.6.0/platform.txt b/arduino/version pre-2.6.0/platform.txt
new file mode 100644
index 000000000..aed8672f9
--- /dev/null
+++ b/arduino/version pre-2.6.0/platform.txt
@@ -0,0 +1,166 @@
+
+# ESP8266 platform
+# ------------------------------
+
+# For more info:
+# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification
+
+name=ESP8266 Boards (2.5.2-196-g45d71ae4)
+version=2.5.2-196-g45d71ae4
+
+# These will be removed by the packager script when doing a JSON release
+
+
+
+
+runtime.tools.signing={runtime.platform.path}/tools/signing.py
+runtime.tools.elf2bin={runtime.platform.path}/tools/elf2bin.py
+runtime.tools.sizes={runtime.platform.path}/tools/sizes.py
+runtime.tools.makecorever={runtime.platform.path}/tools/makecorever.py
+runtime.tools.eboot={runtime.platform.path}/bootloaders/eboot/eboot.elf
+
+compiler.warning_flags=-w
+compiler.warning_flags.none=-w
+compiler.warning_flags.default=
+compiler.warning_flags.more=-Wall
+compiler.warning_flags.all=-Wall -Wextra
+
+build.lwip_lib=-llwip_gcc
+build.lwip_include=lwip/include
+build.lwip_flags=-DLWIP_OPEN_SRC
+
+build.vtable_flags=-DVTABLES_IN_FLASH
+
+build.sslflags=
+
+build.exception_flags=-fno-exceptions
+build.stdcpp_lib=-lstdc++
+build.stdcpp_level=-std=gnu++11
+
+# build.float=-u _printf_float -u _scanf_float
+build.float=
+build.led=
+build.sdk=NONOSDK22y
+
+compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
+compiler.sdk.path={runtime.platform.path}/tools/sdk
+
+compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
+compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
+
+compiler.c.cmd=xtensa-lx106-elf-gcc
+compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags}
+
+compiler.S.cmd=xtensa-lx106-elf-gcc
+compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
+
+compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/lib/{build.sdk}" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
+
+compiler.c.elf.cmd=xtensa-lx106-elf-gcc
+compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc
+
+compiler.cpp.cmd=xtensa-lx106-elf-g++
+compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags}
+
+compiler.as.cmd=xtensa-lx106-elf-as
+
+compiler.ar.cmd=xtensa-lx106-elf-ar
+compiler.ar.flags=cru
+
+compiler.elf2hex.cmd=esptool
+compiler.elf2hex.flags=
+
+compiler.size.cmd=xtensa-lx106-elf-size
+
+# This can be overriden in boards.txt
+build.extra_flags=-DESP8266
+
+# These can be overridden in platform.local.txt
+compiler.c.extra_flags=
+compiler.c.elf.extra_flags=
+compiler.S.extra_flags=
+compiler.cpp.extra_flags=
+compiler.ar.extra_flags=
+compiler.objcopy.eep.extra_flags=
+compiler.elf2hex.extra_flags=
+
+## generate file with git version number
+## needs git
+recipe.hooks.sketch.prebuild.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h"
+# This is quite a working hack. This form of prebuild hook, while intuitive, is not explicitly documented.
+recipe.hooks.prebuild.10.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.makecorever}" --build_path "{build.path}" --platform_path "{runtime.platform.path}" --version "unix-{version}"
+
+## Build the app.ld linker file
+recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld"
+
+## Compile c files
+recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
+
+## Compile c++ files
+recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
+
+## Compile S files
+recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
+
+## Create archives
+recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
+
+## Combine gc-sections, archives, and objects
+recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}"
+
+## Create eeprom
+recipe.objcopy.eep.pattern=
+
+## Create hex
+recipe.objcopy.hex.1.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.elf2bin}" --eboot "{runtime.tools.eboot}" --app "{build.path}/{build.project_name}.elf" --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} --path "{runtime.tools.xtensa-lx106-elf-gcc.path}/bin" --out "{build.path}/{build.project_name}.bin"
+recipe.objcopy.hex.2.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed" --legacy "{build.path}/{build.project_name}.bin.legacy_sig"
+recipe.objcopy.hex.3.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.sizes}" --elf "{build.path}/{build.project_name}.elf" --path "{runtime.tools.xtensa-lx106-elf-gcc.path}/bin"
+
+## Save hex
+recipe.output.tmp_file={build.project_name}.bin
+recipe.output.save_file={build.project_name}.{build.variant}.bin
+
+## Compute size
+recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
+recipe.size.regex=^(?:\.irom0\.text|\.text|\.text1|\.data|\.rodata|)\s+([0-9]+).*
+recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
+#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
+
+# ------------------------------
+
+tools.esptool.path=
+# Because the variable expansion doesn't allow one tool to find another, the following lines
+# will point to "{runtime.platform.path}/tools/python3/python3" in GIT and
+# "{runtime.tools.python3.path}/python3" for JSON board manager releases.
+tools.esptool.cmd={runtime.tools.python3.path}/python3
+tools.esptool.network_cmd={runtime.tools.python3.path}/python3
+
+
+
+tools.esptool.upload.protocol=esp
+# esptool.py --trace option is a debug option, not a verbose option
+tools.esptool.upload.params.verbose=
+tools.esptool.upload.params.quiet=
+
+# First, potentially perform an erase or nothing
+# Next, do the binary upload
+# Combined in one rule because Arduino doesn't suport upload.1.pattern/upload.3.pattern
+tools.esptool.upload.pattern="{cmd}" "{runtime.platform.path}/tools/upload.py" --chip esp8266 --port "{serial.port}" --baud "{upload.speed}" "{upload.verbose}" {upload.erase_cmd} --end --chip esp8266 --port "{serial.port}" --baud "{upload.speed}" "{upload.verbose}" write_flash 0x0 "{build.path}/{build.project_name}.bin" --end
+
+tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
+
+tools.mkspiffs.cmd=mkspiffs
+tools.mkspiffs.cmd.windows=mkspiffs.exe
+tools.mkspiffs.path={runtime.tools.mkspiffs.path}
+
+tools.mklittlefs.cmd=mklittlefs
+tools.mklittlefs.cmd.windows=mklittlefs.exe
+tools.mklittlefs.path={runtime.platform.path}/tools/mklittlefs
+
+tools.espupload.cmd=python
+tools.espupload.cmd.windows=python.exe
+tools.espupload.path={runtime.platform.path}/tools
+tools.espupload.upload.protocol=espupload
+tools.espupload.upload.params.verbose=
+tools.espupload.upload.params.quiet=
+tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"
diff --git a/build-container/Dockerfile b/build-container/Dockerfile
new file mode 100644
index 000000000..a5852d41c
--- /dev/null
+++ b/build-container/Dockerfile
@@ -0,0 +1,24 @@
+FROM python:2
+
+LABEL author="Eduard Angold"
+
+# Install platformio. To be able to build tasmota <=v6.6.0 (and later)
+# we have to use version 3.6.7 of platformio.
+RUN pip install --upgrade pip &&\
+ pip install -U platformio==3.6.7
+
+# Init project
+COPY init_pio_tasmota /init_pio_tasmota
+
+# Install project dependencies using a init project.
+RUN cd /init_pio_tasmota &&\
+ pio run &&\
+ cd ../ &&\
+ rm -fr init_pio_tasmota &&\
+ cp -r /root/.platformio / &&\
+ chmod -R 777 /.platformio
+
+COPY entrypoint.sh /entrypoint.sh
+
+ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
+
diff --git a/build-container/README.md b/build-container/README.md
new file mode 100644
index 000000000..a02f1860e
--- /dev/null
+++ b/build-container/README.md
@@ -0,0 +1,26 @@
+# Docker container for tasmota builds
+This Container will setup a proper build environment for [Sonoff-Tasmota](https://github.com/arendst/Sonoff-Tasmota)
+
+## Create container
+`docker build -t mytasmota:latest .`
+
+## Use a ready container from docker hub
+Use instead of the container `mytasmota:latest` the published container `eddyhub/docker-tasmota:latest` from docker hub.
+
+## Build all development binaries
+`git clone https://github.com/arendst/Sonoff-Tasmota.git`
+`docker run -ti --rm -v $(pwd)/Sonoff-Tasmota:/tasmota -u $UID:$GID mytasmota:latest`
+
+## Build a specific binary with custom options
+Checkout Sonoff-Tasmota: `git clone https://github.com/arendst/Sonoff-Tasmota.git`
+Mount the source as volume in `/tasmota`. **Prefix** any parameter available in `Sonoff-Tasmota/sonoff/my_user_config.h` with `TASMOTA_` as a environment variable for the container. **Also don't forget to escape what needs to be escaped in your shell.** **Strings** should be in **double quotes**. My config example:
+`docker run -ti --rm -v $(pwd)/Sonoff-Tasmota:/tasmota -e TASMOTA_STA_SSID1='"my-wifi"' -e TASMOTA_STA_PASS1='"my-wifi-password"' -e TASMOTA_MQTT_HOST='my-mqtt-host' -e TASMOTA_MQTT_USER='"my-mqtt-user"' -e TASMOTA_MQTT_PASS='"my-mqtt-password"' -e TASMOTA_WEB_PASSWORD='"my-web-password"' -u $UID:$GID mytasmota:latest --environment sonoff-DE
+
+Now you should have the file Sonoff-Tasmota/.pioenvs/sonoff-DE/firmware.bin which can be flashed on your device.
+
+## Build a specific version of tasmota
+Checkout out the needed version before using the build instructions above:
+- `git clone https://github.com/arendst/Sonoff-Tasmota.git`
+- `git -C Sonoff-Tasmota checkout v6.6.0`
+Build it:
+- `docker run -ti --rm -v $(pwd)/Sonoff-Tasmota:/tasmota -u $UID:$GID mytasmota:latest`
diff --git a/build-container/entrypoint.sh b/build-container/entrypoint.sh
new file mode 100644
index 000000000..6bdf2dea6
--- /dev/null
+++ b/build-container/entrypoint.sh
@@ -0,0 +1,35 @@
+# configure build via environment
+#!/bin/bash
+
+TASMOTA_VOLUME='/tasmota'
+USER_CONFIG_OVERRIDE="${TASMOTA_VOLUME}/sonoff/user_config_override.h"
+
+if [ -d $TASMOTA_VOLUME ]; then
+ cd $TASMOTA_VOLUME
+ if [ -n "$(env | grep ^TASMOTA_)" ]; then
+ echo "Removing $USER_CONFIG_OVERRIDE and creating a new one."
+ rm "$USER_CONFIG_OVERRIDE"
+ #export PLATFORMIO_BUILD_FLAGS='-DUSE_CONFIG_OVERRIDE'
+ sed -i 's/^; *-DUSE_CONFIG_OVERRIDE/ -DUSE_CONFIG_OVERRIDE/' platformio.ini
+ echo '#ifndef _USER_CONFIG_OVERRIDE_H_' >> $USER_CONFIG_OVERRIDE
+ echo '#define _USER_CONFIG_OVERRIDE_H_' >> $USER_CONFIG_OVERRIDE
+ echo '#warning **** user_config_override.h: Using Settings from this File ****' >> $USER_CONFIG_OVERRIDE
+ echo '#undef CFG_HOLDER' >> $USER_CONFIG_OVERRIDE
+ echo '#define CFG_HOLDER 1' >> $USER_CONFIG_OVERRIDE
+ for i in $(env | grep ^TASMOTA_); do
+ config=${i#TASMOTA_}
+ key=$(echo $config | cut -d '=' -f 1)
+ value=$(echo $config | cut -d '=' -f 2)
+ echo "#undef ${key}" >> $USER_CONFIG_OVERRIDE
+ echo "#define ${key} ${value}" >> $USER_CONFIG_OVERRIDE
+ done
+ echo '#endif' >> $USER_CONFIG_OVERRIDE
+ fi
+ echo "Compiling..."
+ #pio run -t clean
+ pio run $@
+ echo "Everything done you find your builds in .pioenvs//firmware.bin"
+else
+ echo ">>> NO TASMOTA VOLUME MOUNTED --> EXITING"
+ exit 0;
+fi
diff --git a/build-container/init_pio_tasmota/platformio.ini b/build-container/init_pio_tasmota/platformio.ini
new file mode 100644
index 000000000..058e9064f
--- /dev/null
+++ b/build-container/init_pio_tasmota/platformio.ini
@@ -0,0 +1,30 @@
+[env:core_2_3_0]
+; *** Esp8266 core for Arduino version 2.3.0
+platform = espressif8266@1.5.0
+framework = arduino
+board = esp01_1m
+
+[env:core_2_4_2]
+; *** Esp8266 core for Arduino version 2.4.2
+platform = espressif8266@1.8.0
+framework = arduino
+board = esp01_1m
+
+[env:core_2_5_2]
+; *** Esp8266 core for Arduino version 2.5.2
+platform = espressif8266@~2.2.2
+framework = arduino
+board = esp01_1m
+
+[env:core_stage]
+; *** Esp8266 core for Arduino version latest beta
+platform = https://github.com/platformio/platform-espressif8266.git#feature/stage
+framework = arduino
+board = esp01_1m
+
+[env:core_pre]
+; *** Arduino Esp8266 core pre 2.6.x for Tasmota (mqtt reconnects fixed)
+platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota
+framework = arduino
+board = esp01_1m
+
diff --git a/build-container/init_pio_tasmota/src/main.cpp b/build-container/init_pio_tasmota/src/main.cpp
new file mode 100644
index 000000000..27f3768b7
--- /dev/null
+++ b/build-container/init_pio_tasmota/src/main.cpp
@@ -0,0 +1,3 @@
+#include
+void setup() {}
+void loop() {}
diff --git a/lib/A4988_Stepper/README.adoc b/lib/A4988_Stepper/README.adoc
new file mode 100644
index 000000000..0cac353f3
--- /dev/null
+++ b/lib/A4988_Stepper/README.adoc
@@ -0,0 +1,19 @@
+Stepper Library for Tasmota
+
+This Class allows you to control bipolar stepper motors. To use it you will need an A4988-StepperDriverCircuit, connected at least with 2 GPIO's (direction and step) and of cause a stepper motor.
+
+== License ==
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
diff --git a/lib/A4988_Stepper/keywords.txt b/lib/A4988_Stepper/keywords.txt
new file mode 100644
index 000000000..c83465c8b
--- /dev/null
+++ b/lib/A4988_Stepper/keywords.txt
@@ -0,0 +1,24 @@
+#######################################
+# Syntax Coloring Map For Test
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+A4988_Stepper KEYWORD1 A4988_Stepper
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+doMove KEYWORD2
+doRotate KEYWORD2
+setRPM KEYWORD2
+setSPR KEYWORD2
+setMIS KEYWORD2
+version KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
diff --git a/lib/A4988_Stepper/library.properties b/lib/A4988_Stepper/library.properties
new file mode 100644
index 000000000..2e6b38bf9
--- /dev/null
+++ b/lib/A4988_Stepper/library.properties
@@ -0,0 +1,9 @@
+name=A4988_Stepper
+version=0.0.1
+author=Tim Leuschner
+maintainer=Tim Leuschner
+sentence=Allows Tasmota to control stepper motors, connected to A4988-StepperDriverCircuit.
+paragraph=This library allows you to control bipolar stepper motors, controlled by A4988-stepperDriverCircuit.
+category=Device Control
+url=
+architectures=*
diff --git a/lib/A4988_Stepper/src/A4988_Stepper.cpp b/lib/A4988_Stepper/src/A4988_Stepper.cpp
new file mode 100644
index 000000000..cbd72390a
--- /dev/null
+++ b/lib/A4988_Stepper/src/A4988_Stepper.cpp
@@ -0,0 +1,155 @@
+/*
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+ Drives a bipolar motor, controlled by A4988 stepper driver circuit
+ */
+//
+#include "Arduino.h"
+#include "A4988_Stepper.h"
+A4988_Stepper::A4988_Stepper( int m_spr
+ , int m_rpm
+ , short m_mis
+ , short m_dir_pin
+ , short m_stp_pin
+ , short m_ena_pin
+ , short m_ms1_pin
+ , short m_ms2_pin
+ , short m_ms3_pin ) {
+ last_time = 0; // time stamp in us of the last step taken
+ motor_SPR = m_spr; // StepsPerRevolution
+ motor_RPM = m_rpm; // RoundsPerMinute
+ motor_MIS = m_mis; // Microsteps w/o effect if MS1-MS3 not connected - then full steps anyway
+ motor_dir_pin = m_dir_pin;
+ motor_stp_pin = m_stp_pin;
+ motor_ena_pin = m_ena_pin;
+ motor_ms1_pin = m_ms1_pin;
+ motor_ms2_pin = m_ms2_pin;
+ motor_ms3_pin = m_ms3_pin;
+
+ adjustDelay();
+ adjustPins();
+ adjustMicrosteps();
+}
+
+void A4988_Stepper::adjustPins(void) {
+ // setup the pins on the microcontroller:
+ pinMode(motor_dir_pin, OUTPUT);
+ pinMode(motor_stp_pin, OUTPUT);
+ if (motor_ena_pin <99) {
+ pinMode(motor_ena_pin, OUTPUT);
+ digitalWrite(motor_ena_pin, HIGH);
+ }
+
+ if ((motor_ms1_pin<99)&&(motor_ms2_pin<99)&&(motor_ms3_pin<99)) {
+ pinMode(motor_ms1_pin, OUTPUT);
+ pinMode(motor_ms2_pin, OUTPUT);
+ pinMode(motor_ms3_pin, OUTPUT);
+ }
+}
+
+void A4988_Stepper::adjustMicrosteps() {
+ if ((motor_ms1_pin<99)&&(motor_ms2_pin<99)&&(motor_ms3_pin<99)) {
+ unsigned short i = 0;
+ while (i < 5){
+ if (motor_MIS & (1<0?LOW:HIGH);
+ enable();
+ while (steps_togo > 0) {
+ delay(0); // don't get watchdoged in loop
+ unsigned long now = micros();
+ // move if delay has passed:
+ if (now - last_time >= motor_delay) {
+ digitalWrite(motor_stp_pin, lastStepWasHigh?LOW:HIGH);
+ lastStepWasHigh = !lastStepWasHigh;
+ // remeber step-time
+ last_time = now;
+ if (!lastStepWasHigh) steps_togo--; // same here - only HIGH moves, if pulled LOW step is completed...
+ }
+ }
+ disable();
+}
+
+void A4988_Stepper::doRotate(long howManyDegrees)
+{ long lSteps = 0;
+ lSteps = motor_SPR*motor_MIS*howManyDegrees/360;
+ doMove(lSteps);
+}
+
+void A4988_Stepper::doTurn(float howManyTimes)
+{ long lSteps = 0;
+ lSteps = howManyTimes*motor_SPR;
+ doMove(lSteps);
+}
+
+int A4988_Stepper::version(void)
+{
+ return 1;
+}
diff --git a/lib/A4988_Stepper/src/A4988_Stepper.h b/lib/A4988_Stepper/src/A4988_Stepper.h
new file mode 100644
index 000000000..a907adfb1
--- /dev/null
+++ b/lib/A4988_Stepper/src/A4988_Stepper.h
@@ -0,0 +1,73 @@
+/*
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+
+#ifndef A4988_Stepper_h
+#define A4988_Stepper_h
+
+class A4988_Stepper {
+ public:
+ // constructor:
+ A4988_Stepper( int motor_spr
+ , int motor_rpm
+ , short motor_mis
+ , short motor_dir_pin
+ , short motor_stp_pin
+ , short motor_ena_pin
+ , short motor_ms1_pin
+ , short motor_ms2_pin
+ , short motor_ms3_pin
+ );
+
+ void setRPM (int whatRPM );
+ int getRPM (void );
+
+ void setMIS (short OneToSixteen);
+ short getMIS (void );
+
+ void setSPR (int howMany );
+ int getSPR (void );
+
+ void doMove (long steps_to_move);
+ void doRotate(long degrs_to_turn);
+ void doTurn (float howManyTimes);
+
+ void enable (void );
+ void disable (void );
+
+ int version (void );
+ const unsigned short MIS_TABLE[5] = {0b000,0b001,0b010,0b011,0b111};
+
+ private:
+ void adjustDelay(void);
+ void adjustPins(void);
+ void adjustMicrosteps(void);
+ unsigned long motor_delay; // delay between steps, in ms
+ int motor_SPR; // Steps Per Revolution
+ int motor_RPM; // Rounds Per Minute
+ short motor_MIS; // Micro Steps
+
+ // motor pins:
+ short motor_dir_pin;
+ short motor_stp_pin;
+ short motor_ena_pin;
+ short motor_ms1_pin;
+ short motor_ms2_pin;
+ short motor_ms3_pin;
+
+ unsigned long last_time; // timestamp of last pincycle of last step
+};
+
+#endif
diff --git a/lib/AT24C256/Eeprom24C128_256.cpp b/lib/AT24C256/Eeprom24C128_256.cpp
new file mode 100644
index 000000000..f7b66afba
--- /dev/null
+++ b/lib/AT24C256/Eeprom24C128_256.cpp
@@ -0,0 +1,334 @@
+/**************************************************************************//**
+ * \brief EEPROM 24C128 / 24C256 library for Arduino
+ * \author Copyright (C) 2012 Julien Le Sech - www.idreammicro.com
+ * \version 1.0
+ * \date 20120203
+ *
+ * This file is part of the EEPROM 24C128 / 24C256 library for Arduino.
+ *
+ * This library is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/
+ ******************************************************************************/
+
+/**************************************************************************//**
+ * \file Eeprom24C128_256.cpp
+ ******************************************************************************/
+
+/******************************************************************************
+ * Header file inclusions.
+ ******************************************************************************/
+
+#include
+#include
+
+#include
+
+/******************************************************************************
+ * Private macro definitions.
+ ******************************************************************************/
+
+/**************************************************************************//**
+ * \def EEPROM__PAGE_SIZE
+ * \brief Size of a page in EEPROM memory.
+ * This size is given by EEPROM memory datasheet.
+ ******************************************************************************/
+#define EEPROM__PAGE_SIZE 64
+
+/**************************************************************************//**
+ * \def EEPROM__RD_BUFFER_SIZE
+ * \brief Size of input TWI buffer.
+ * This size is equal to BUFFER_LENGTH defined in Wire library (32 bytes).
+ ******************************************************************************/
+ #define xBUFFER_LENGTH 24
+#define EEPROM__RD_BUFFER_SIZE xBUFFER_LENGTH
+
+/**************************************************************************//**
+ * \def EEPROM__WR_BUFFER_SIZE
+ * \brief Size of output TWI buffer.
+ * This size is equal to BUFFER_LENGTH - 2 bytes reserved for address.
+ ******************************************************************************/
+#define EEPROM__WR_BUFFER_SIZE (xBUFFER_LENGTH - 2)
+
+/******************************************************************************
+ * Public method definitions.
+ ******************************************************************************/
+
+/**************************************************************************//**
+ * \fn Eeprom24C128_256::Eeprom24C128_256(byte deviceAddress)
+ *
+ * \brief Constructor.
+ *
+ * \param deviceAddress EEPROM address on TWI bus.
+ ******************************************************************************/
+Eeprom24C128_256::Eeprom24C128_256
+(
+ byte deviceAddress
+){
+ m_deviceAddress = deviceAddress;
+}
+
+/**************************************************************************//**
+ * \fn void Eeprom24C128_256::initialize()
+ *
+ * \brief Initialize library and TWI bus.
+ *
+ * If several devices are connected to TWI bus, this method mustn't be
+ * called. TWI bus must be initialized out of this library using
+ * Wire.begin() method.
+ ******************************************************************************/
+void
+Eeprom24C128_256::initialize()
+{
+ Wire.begin();
+}
+
+/**************************************************************************//**
+ * \fn void Eeprom24C128_256::writeByte(
+ * word address,
+ * byte data)
+ *
+ * \brief Write a byte in EEPROM memory.
+ *
+ * \remarks A delay of 10 ms is required after write cycle.
+ *
+ * \param address Address.
+ * \param data Byte to write.
+ ******************************************************************************/
+void
+Eeprom24C128_256::writeByte
+(
+ word address,
+ byte data
+){
+ Wire.beginTransmission(m_deviceAddress);
+ Wire.write(address >> 8);
+ Wire.write(address & 0xFF);
+ Wire.write(data);
+ Wire.endTransmission();
+}
+
+/**************************************************************************//**
+ * \fn void Eeprom24C128_256::writeBytes(
+ * word address,
+ * word length,
+ * byte* p_data)
+ *
+ * \brief Write bytes in EEPROM memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes to write.
+ * \param[in] p_data Bytes to write.
+ ******************************************************************************/
+void
+Eeprom24C128_256::writeBytes
+(
+ word address,
+ word length,
+ byte* p_data
+){
+ // Write first page if not aligned.
+ byte notAlignedLength = 0;
+ byte pageOffset = address % EEPROM__PAGE_SIZE;
+ if (pageOffset > 0)
+ {
+ notAlignedLength = EEPROM__PAGE_SIZE - pageOffset;
+ if (length < notAlignedLength)
+ {
+ notAlignedLength = length;
+ }
+ writePage(address, notAlignedLength, p_data);
+ length -= notAlignedLength;
+ }
+
+ if (length > 0)
+ {
+ address += notAlignedLength;
+ p_data += notAlignedLength;
+
+ // Write complete and aligned pages.
+ word pageCount = length / EEPROM__PAGE_SIZE;
+ for (word i = 0; i < pageCount; i++)
+ {
+ writePage(address, EEPROM__PAGE_SIZE, p_data);
+ address += EEPROM__PAGE_SIZE;
+ p_data += EEPROM__PAGE_SIZE;
+ length -= EEPROM__PAGE_SIZE;
+ }
+
+ if (length > 0)
+ {
+ // Write remaining uncomplete page.
+ writePage(address, length, p_data);
+ }
+ }
+}
+
+/**************************************************************************//**
+ * \fn byte Eeprom24C128_256::readByte(word address)
+ *
+ * \brief Read a byte in EEPROM memory.
+ *
+ * \param address Address.
+ *
+ * \return Read byte.
+ ******************************************************************************/
+byte
+Eeprom24C128_256::readByte
+(
+ word address
+){
+ Wire.beginTransmission(m_deviceAddress);
+ Wire.write(address >> 8);
+ Wire.write(address & 0xFF);
+ Wire.endTransmission();
+ Wire.requestFrom(m_deviceAddress, (byte)1);
+ byte data = 0;
+ if (Wire.available())
+ {
+ data = Wire.read();
+ }
+ return data;
+}
+
+/**************************************************************************//**
+ * \fn void Eeprom24C128_256::readBytes(
+ * word address,
+ * word length,
+ * byte* p_data)
+ *
+ * \brief Read bytes in EEPROM memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes to read.
+ * \patam[in] p_data Byte array to fill with read bytes.
+ ******************************************************************************/
+void
+Eeprom24C128_256::readBytes
+(
+ word address,
+ word length,
+ byte* p_data
+){
+ byte bufferCount = length / EEPROM__RD_BUFFER_SIZE;
+ for (byte i = 0; i < bufferCount; i++)
+ {
+ word offset = i * EEPROM__RD_BUFFER_SIZE;
+ readBuffer(address + offset, EEPROM__RD_BUFFER_SIZE, p_data + offset);
+ }
+
+ byte remainingBytes = length % EEPROM__RD_BUFFER_SIZE;
+ word offset = length - remainingBytes;
+ readBuffer(address + offset, remainingBytes, p_data + offset);
+}
+
+/******************************************************************************
+ * Private method definitions.
+ ******************************************************************************/
+
+/**************************************************************************//**
+ * \fn void Eeprom24C128_256::writePage(
+ * word address,
+ * byte length,
+ * byte* p_data)
+ *
+ * \brief Write page in EEPROM memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes (EEPROM__PAGE_SIZE bytes max).
+ * \param[in] p_data Data.
+ ******************************************************************************/
+void
+Eeprom24C128_256::writePage
+(
+ word address,
+ byte length,
+ byte* p_data
+){
+ // Write complete buffers.
+ byte bufferCount = length / EEPROM__WR_BUFFER_SIZE;
+ for (byte i = 0; i < bufferCount; i++)
+ {
+ byte offset = i * EEPROM__WR_BUFFER_SIZE;
+ writeBuffer(address + offset, EEPROM__WR_BUFFER_SIZE, p_data + offset);
+ }
+
+ // Write remaining bytes.
+ byte remainingBytes = length % EEPROM__WR_BUFFER_SIZE;
+ byte offset = length - remainingBytes;
+ writeBuffer(address + offset, remainingBytes, p_data + offset);
+}
+
+/**************************************************************************//**
+ * \fn void Eeprom24C128_256::writeBuffer(
+ * word address,
+ * byte length,
+ * byte* p_data)
+ *
+ * \brief Write bytes into memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes (EEPROM__WR_BUFFER_SIZE bytes max).
+ * \param[in] p_data Data.
+ ******************************************************************************/
+void
+Eeprom24C128_256::writeBuffer
+(
+ word address,
+ byte length,
+ byte* p_data
+){
+ Wire.beginTransmission(m_deviceAddress);
+ Wire.write(address >> 8);
+ Wire.write(address & 0xFF);
+ for (byte i = 0; i < length; i++)
+ {
+ Wire.write(p_data[i]);
+ }
+ Wire.endTransmission();
+
+ // Write cycle time (tWR). See EEPROM memory datasheet for more details.
+ delay(10);
+}
+
+/**************************************************************************//**
+ * \fn void Eeprom24C128_256::readBuffer(
+ * word address,
+ * byte length,
+ * byte* p_data)
+ *
+ * \brief Read bytes in memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes (EEPROM__RD_BUFFER_SIZE bytes max).
+ * \param[in] p_data Buffer to fill with read bytes.
+ ******************************************************************************/
+void
+Eeprom24C128_256::readBuffer
+(
+ word address,
+ byte length,
+ byte* p_data
+){
+ Wire.beginTransmission(m_deviceAddress);
+ Wire.write(address >> 8);
+ Wire.write(address & 0xFF);
+ Wire.endTransmission();
+ Wire.requestFrom(m_deviceAddress, length);
+ for (byte i = 0; i < length; i++)
+ {
+ if (Wire.available())
+ {
+ p_data[i] = Wire.read();
+ }
+ }
+}
diff --git a/lib/AT24C256/Eeprom24C128_256.h b/lib/AT24C256/Eeprom24C128_256.h
new file mode 100644
index 000000000..865c76226
--- /dev/null
+++ b/lib/AT24C256/Eeprom24C128_256.h
@@ -0,0 +1,212 @@
+/**************************************************************************//**
+ * \brief EEPROM 24C128 / 24C256 library for Arduino
+ * \author Copyright (C) 2012 Julien Le Sech - www.idreammicro.com
+ * \version 1.0
+ * \date 20120203
+ *
+ * This file is part of the EEPROM 24C128 / 24C256 library for Arduino.
+ *
+ * This library is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/
+ ******************************************************************************/
+
+/**************************************************************************//**
+ * \headerfile Eeprom24C128_256.h
+ ******************************************************************************/
+
+#ifndef Eeprom24C128_256_h
+#define Eeprom24C128_256_h
+
+/******************************************************************************
+ * Header file inclusion.
+ ******************************************************************************/
+
+#include
+
+/**************************************************************************//**
+ * \class Eeprom24C128_256
+ *
+ * \brief EEPROM 24C128 / 24C256 memory driver.
+ *
+ * This driver is mainly designed for 24C128 and 24C256 EEPROM memories. It's
+ * also suitable for 24C512 memories.
+ ******************************************************************************/
+class Eeprom24C128_256
+{
+ public:
+
+ /******************************************************************//**
+ * \fn Eeprom24C128_256(byte deviceAddress)
+ *
+ * \brief Constructor.
+ *
+ * \param deviceAddress EEPROM address on TWI bus.
+ **********************************************************************/
+ Eeprom24C128_256
+ (
+ byte deviceAddress
+ );
+
+ /******************************************************************//**
+ * \fn void initialize()
+ *
+ * \brief Initialize library abnd TWI bus.
+ *
+ * If several devices are connected to TWI bus, this method mustn't be
+ * called. TWI bus must be initialized out of this library using
+ * Wire.begin() method.
+ **********************************************************************/
+ void
+ initialize();
+
+ /******************************************************************//**
+ * \fn void writeByte(
+ * word address,
+ * byte data)
+ *
+ * \brief Write a byte in EEPROM memory.
+ *
+ * \remarks A delay of 10 ms is required after write cycle.
+ *
+ * \param address Address.
+ * \param data Byte to write.
+ **********************************************************************/
+ void
+ writeByte
+ (
+ word address,
+ byte data
+ );
+
+ /******************************************************************//**
+ * \fn void writeBytes(
+ * word address,
+ * word length,
+ * byte* p_data)
+ *
+ * \brief Write bytes in EEPROM memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes to write.
+ * \param[in] p_data Bytes to write.
+ **********************************************************************/
+ void
+ writeBytes
+ (
+ word address,
+ word length,
+ byte* p_data
+ );
+
+ /******************************************************************//**
+ * \fn byte readByte(word address)
+ *
+ * \brief Read a byte in EEPROM memory.
+ *
+ * \param address Address.
+ *
+ * \return Read byte.
+ **********************************************************************/
+ byte
+ readByte
+ (
+ word address
+ );
+
+ /******************************************************************//**
+ * \fn void readBytes(
+ * word address,
+ * word length,
+ * byte* p_data)
+ *
+ * \brief Read bytes in EEPROM memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes to read.
+ * \patam[in] p_data Byte array to fill with read bytes.
+ **********************************************************************/
+ void
+ readBytes
+ (
+ word address,
+ word length,
+ byte* p_buffer
+ );
+
+ private:
+
+ byte m_deviceAddress;
+
+ /******************************************************************//**
+ * \fn void writePage(
+ * word address,
+ * byte length,
+ * byte* p_data)
+ *
+ * \brief Write page in EEPROM memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes (64 bytes max).
+ * \param[in] p_data Data.
+ **********************************************************************/
+ void
+ writePage
+ (
+ word address,
+ byte length,
+ byte* p_data
+ );
+
+ /******************************************************************//**
+ * \fn void writeBuffer(
+ * word address,
+ * byte length,
+ * byte* p_data)
+ *
+ * \brief Write bytes into memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes (30 bytes max).
+ * \param[in] p_date Data.
+ **********************************************************************/
+ void
+ writeBuffer
+ (
+ word address,
+ byte length,
+ byte* p_data
+ );
+
+ /******************************************************************//**
+ * \fn void readBuffer(
+ * word address,
+ * byte length,
+ * byte* p_data)
+ *
+ * \brief Read bytes in memory.
+ *
+ * \param address Start address.
+ * \param length Number of bytes to read (32 bytes max).
+ * \param[in] p_data Buffer to fill with read bytes.
+ **********************************************************************/
+ void
+ readBuffer
+ (
+ word address,
+ byte length,
+ byte* p_data
+ );
+};
+
+#endif // Eeprom24C128_256_h
+
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Adafruit_SPITFT.cpp b/lib/Adafruit-GFX-Library-1.2.9/Adafruit_SPITFT.cpp
deleted file mode 100644
index 51b53cc3b..000000000
--- a/lib/Adafruit-GFX-Library-1.2.9/Adafruit_SPITFT.cpp
+++ /dev/null
@@ -1,555 +0,0 @@
-/*!
-* @file Adafruit_SPITFT.cpp
-*
-* @mainpage Adafruit SPI TFT Displays
-*
-* @section intro_sec Introduction
- This is our library for generic SPI TFT Displays with
- address windows and 16 bit color (e.g. ILI9341, HX8357D, ST7735...)
-
- Check out the links above for our tutorials and wiring diagrams
- These displays use SPI to communicate, 4 or 5 pins are required to
- interface (RST is optional)
- Adafruit invests time and resources providing this open source code,
- please support Adafruit and open-source hardware by purchasing
- products from Adafruit!
-
- Written by Limor Fried/Ladyada for Adafruit Industries.
- MIT license, all text above must be included in any redistribution
-* @section dependencies Dependencies
-*
-* This library depends on
-* Adafruit_GFX being present on your system. Please make sure you have
-* installed the latest version before using this library.
-*
-* @section author Author
-*
-* Written by Limor "ladyada" Fried for Adafruit Industries.
-*
-* @section license License
-*
-* BSD license, all text here must be included in any redistribution.
-*
-*/
-
-#ifndef __AVR_ATtiny85__ // NOT A CHANCE of this stuff working on ATtiny!
-
-#include "Adafruit_SPITFT.h"
-#ifndef ARDUINO_STM32_FEATHER
- #include "pins_arduino.h"
-#ifndef RASPI
- #include "wiring_private.h"
-#endif
-#endif
-#include
-
-#include "Adafruit_SPITFT_Macros.h"
-
-
-
-/**************************************************************************/
-/*!
- @brief Pass 8-bit (each) R,G,B, get back 16-bit packed color
- This function converts 8-8-8 RGB data to 16-bit 5-6-5
- @param red Red 8 bit color
- @param green Green 8 bit color
- @param blue Blue 8 bit color
- @return Unsigned 16-bit down-sampled color in 5-6-5 format
-*/
-/**************************************************************************/
-uint16_t Adafruit_SPITFT::color565(uint8_t red, uint8_t green, uint8_t blue) {
- return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
-}
-
-
-/**************************************************************************/
-/*!
- @brief Instantiate Adafruit SPI display driver with software SPI
- @param w Display width in pixels
- @param h Display height in pixels
- @param cs Chip select pin #
- @param dc Data/Command pin #
- @param mosi SPI MOSI pin #
- @param sclk SPI Clock pin #
- @param rst Reset pin # (optional, pass -1 if unused)
- @param miso SPI MISO pin # (optional, pass -1 if unused)
-*/
-/**************************************************************************/
-Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
- int8_t cs, int8_t dc, int8_t mosi,
- int8_t sclk, int8_t rst, int8_t miso)
- : Adafruit_GFX(w, h) {
- _cs = cs;
- _dc = dc;
- _rst = rst;
- _sclk = sclk;
- _mosi = mosi;
- _miso = miso;
- _freq = 0;
-#ifdef USE_FAST_PINIO
- dcport = (RwReg *)portOutputRegister(digitalPinToPort(dc));
- dcpinmask = digitalPinToBitMask(dc);
- clkport = (RwReg *)portOutputRegister(digitalPinToPort(sclk));
- clkpinmask = digitalPinToBitMask(sclk);
- mosiport = (RwReg *)portOutputRegister(digitalPinToPort(mosi));
- mosipinmask = digitalPinToBitMask(mosi);
- if(miso >= 0){
- misoport = (RwReg *)portInputRegister(digitalPinToPort(miso));
- misopinmask = digitalPinToBitMask(miso);
- } else {
- misoport = 0;
- misopinmask = 0;
- }
- if(cs >= 0) {
- csport = (RwReg *)portOutputRegister(digitalPinToPort(cs));
- cspinmask = digitalPinToBitMask(cs);
- } else {
- // No chip-select line defined; might be permanently tied to GND.
- // Assign a valid GPIO register (though not used for CS), and an
- // empty pin bitmask...the nonsense bit-twiddling might be faster
- // than checking _cs and possibly branching.
- csport = dcport;
- cspinmask = 0;
- }
-#endif
-}
-
-/**************************************************************************/
-/*!
- @brief Instantiate Adafruit SPI display driver with hardware SPI
- @param w Display width in pixels
- @param h Display height in pixels
- @param cs Chip select pin #
- @param dc Data/Command pin #
- @param rst Reset pin # (optional, pass -1 if unused)
-*/
-/**************************************************************************/
-Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
- int8_t cs, int8_t dc, int8_t rst)
- : Adafruit_GFX(w, h) {
- _cs = cs;
- _dc = dc;
- _rst = rst;
- _sclk = -1;
- _mosi = -1;
- _miso = -1;
- _freq = 0;
-#ifdef USE_FAST_PINIO
- clkport = 0;
- clkpinmask = 0;
- mosiport = 0;
- mosipinmask = 0;
- misoport = 0;
- misopinmask = 0;
- dcport = (RwReg *)portOutputRegister(digitalPinToPort(dc));
- dcpinmask = digitalPinToBitMask(dc);
- if(cs >= 0) {
- csport = (RwReg *)portOutputRegister(digitalPinToPort(cs));
- cspinmask = digitalPinToBitMask(cs);
- } else {
- // See notes in prior constructor.
- csport = dcport;
- cspinmask = 0;
- }
-#endif
-}
-
-/**************************************************************************/
-/*!
- @brief Initialiaze the SPI interface (hardware or software)
- @param freq The desired maximum SPI hardware clock frequency
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::initSPI(uint32_t freq) {
- _freq = freq;
-
- // Control Pins
- if(_cs >= 0) {
- pinMode(_cs, OUTPUT);
- digitalWrite(_cs, HIGH); // Deselect
- }
- pinMode(_dc, OUTPUT);
- digitalWrite(_dc, LOW);
-
- // Software SPI
- if(_sclk >= 0){
- pinMode(_mosi, OUTPUT);
- digitalWrite(_mosi, LOW);
- pinMode(_sclk, OUTPUT);
- digitalWrite(_sclk, HIGH);
- if(_miso >= 0){
- pinMode(_miso, INPUT);
- }
- }
-
- // Hardware SPI
- SPI_BEGIN();
-
- // toggle RST low to reset
- if (_rst >= 0) {
- pinMode(_rst, OUTPUT);
- digitalWrite(_rst, HIGH);
- delay(100);
- digitalWrite(_rst, LOW);
- delay(100);
- digitalWrite(_rst, HIGH);
- delay(200);
- }
-}
-
-/**************************************************************************/
-/*!
- @brief Read one byte from SPI interface (hardware or software
- @returns One byte, MSB order
-*/
-/**************************************************************************/
-uint8_t Adafruit_SPITFT::spiRead() {
- if(_sclk < 0){
- return HSPI_READ();
- }
- if(_miso < 0){
- return 0;
- }
- uint8_t r = 0;
- for (uint8_t i=0; i<8; i++) {
- SSPI_SCK_LOW();
- SSPI_SCK_HIGH();
- r <<= 1;
- if (SSPI_MISO_READ()){
- r |= 0x1;
- }
- }
- return r;
-}
-
-/**************************************************************************/
-/*!
- @brief Write one byte to SPI interface (hardware or software
- @param b One byte to send, MSB order
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::spiWrite(uint8_t b) {
- if(_sclk < 0){
- HSPI_WRITE(b);
- return;
- }
- for(uint8_t bit = 0x80; bit; bit >>= 1){
- if((b) & bit){
- SSPI_MOSI_HIGH();
- } else {
- SSPI_MOSI_LOW();
- }
- SSPI_SCK_LOW();
- SSPI_SCK_HIGH();
- }
-}
-
-
-/*
- * Transaction API
- * */
-
-/**************************************************************************/
-/*!
- @brief Begin an SPI transaction & set CS low.
-*/
-/**************************************************************************/
-void inline Adafruit_SPITFT::startWrite(void){
- SPI_BEGIN_TRANSACTION();
- SPI_CS_LOW();
-}
-
-/**************************************************************************/
-/*!
- @brief Begin an SPI transaction & set CS high.
-*/
-/**************************************************************************/
-void inline Adafruit_SPITFT::endWrite(void){
- SPI_CS_HIGH();
- SPI_END_TRANSACTION();
-}
-
-/**************************************************************************/
-/*!
- @brief Write a command byte (must have a transaction in progress)
- @param cmd The 8-bit command to send
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::writeCommand(uint8_t cmd){
- SPI_DC_LOW();
- spiWrite(cmd);
- SPI_DC_HIGH();
-}
-
-/**************************************************************************/
-/*!
- @brief Push a 2-byte color to the framebuffer RAM, will start transaction
- @param color 16-bit 5-6-5 Color to draw
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::pushColor(uint16_t color) {
- startWrite();
- SPI_WRITE16(color);
- endWrite();
-}
-
-
-
-/**************************************************************************/
-/*!
- @brief Blit multiple 2-byte colors (must have a transaction in progress)
- @param colors Array of 16-bit 5-6-5 Colors to draw
- @param len How many pixels to draw - 2 bytes per pixel!
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::writePixels(uint16_t * colors, uint32_t len){
- SPI_WRITE_PIXELS((uint8_t*)colors , len * 2);
-}
-
-/**************************************************************************/
-/*!
- @brief Blit a 2-byte color many times (must have a transaction in progress)
- @param color The 16-bit 5-6-5 Color to draw
- @param len How many pixels to draw
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::writeColor(uint16_t color, uint32_t len){
-#ifdef SPI_HAS_WRITE_PIXELS
- if(_sclk >= 0){
- for (uint32_t t=0; t SPI_MAX_PIXELS_AT_ONCE)?SPI_MAX_PIXELS_AT_ONCE:len;
- uint16_t tlen = 0;
-
- for (uint32_t t=0; tblen)?blen:len;
- writePixels(temp, tlen);
- len -= tlen;
- }
-#else
- uint8_t hi = color >> 8, lo = color;
- if(_sclk < 0){ //AVR Optimization
- for (uint32_t t=len; t; t--){
- HSPI_WRITE(hi);
- HSPI_WRITE(lo);
- }
- return;
- }
- for (uint32_t t=len; t; t--){
- spiWrite(hi);
- spiWrite(lo);
- }
-#endif
-}
-
-/**************************************************************************/
-/*!
- @brief Write a pixel (must have a transaction in progress)
- @param x x coordinate
- @param y y coordinate
- @param color 16-bit 5-6-5 Color to draw with
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
- if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
- setAddrWindow(x,y,1,1);
- writePixel(color);
-}
-
-/**************************************************************************/
-/*!
- @brief Write a filled rectangle (must have a transaction in progress)
- @param x Top left corner x coordinate
- @param y Top left corner y coordinate
- @param w Width in pixels
- @param h Height in pixels
- @param color 16-bit 5-6-5 Color to fill with
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
- if((x >= _width) || (y >= _height)) return;
- int16_t x2 = x + w - 1, y2 = y + h - 1;
- if((x2 < 0) || (y2 < 0)) return;
-
- // Clip left/top
- if(x < 0) {
- x = 0;
- w = x2 + 1;
- }
- if(y < 0) {
- y = 0;
- h = y2 + 1;
- }
-
- // Clip right/bottom
- if(x2 >= _width) w = _width - x;
- if(y2 >= _height) h = _height - y;
-
- int32_t len = (int32_t)w * h;
- setAddrWindow(x, y, w, h);
- writeColor(color, len);
-}
-
-/**************************************************************************/
-/*!
- @brief Write a perfectly vertical line (must have a transaction in progress)
- @param x Top-most x coordinate
- @param y Top-most y coordinate
- @param h Height in pixels
- @param color 16-bit 5-6-5 Color to fill with
-*/
-/**************************************************************************/
-void inline Adafruit_SPITFT::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
- writeFillRect(x, y, 1, h, color);
-}
-
-/**************************************************************************/
-/*!
- @brief Write a perfectly horizontal line (must have a transaction in progress)
- @param x Left-most x coordinate
- @param y Left-most y coordinate
- @param w Width in pixels
- @param color 16-bit 5-6-5 Color to fill with
-*/
-/**************************************************************************/
-void inline Adafruit_SPITFT::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
- writeFillRect(x, y, w, 1, color);
-}
-
-/**************************************************************************/
-/*!
- @brief Draw a pixel - sets up transaction
- @param x x coordinate
- @param y y coordinate
- @param color 16-bit 5-6-5 Color to draw with
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::drawPixel(int16_t x, int16_t y, uint16_t color){
- startWrite();
- writePixel(x, y, color);
- endWrite();
-}
-
-/**************************************************************************/
-/*!
- @brief Write a perfectly vertical line - sets up transaction
- @param x Top-most x coordinate
- @param y Top-most y coordinate
- @param h Height in pixels
- @param color 16-bit 5-6-5 Color to fill with
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::drawFastVLine(int16_t x, int16_t y,
- int16_t h, uint16_t color) {
- startWrite();
- writeFastVLine(x, y, h, color);
- endWrite();
-}
-
-/**************************************************************************/
-/*!
- @brief Write a perfectly horizontal line - sets up transaction
- @param x Left-most x coordinate
- @param y Left-most y coordinate
- @param w Width in pixels
- @param color 16-bit 5-6-5 Color to fill with
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::drawFastHLine(int16_t x, int16_t y,
- int16_t w, uint16_t color) {
- startWrite();
- writeFastHLine(x, y, w, color);
- endWrite();
-}
-
-/**************************************************************************/
-/*!
- @brief Fill a rectangle completely with one color.
- @param x Top left corner x coordinate
- @param y Top left corner y coordinate
- @param w Width in pixels
- @param h Height in pixels
- @param color 16-bit 5-6-5 Color to fill with
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
- uint16_t color) {
- startWrite();
- writeFillRect(x,y,w,h,color);
- endWrite();
-}
-
-
-/**************************************************************************/
-/*!
- @brief Invert the display using built-in hardware command
- @param i True if you want to invert, false to make 'normal'
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::invertDisplay(boolean i) {
- startWrite();
- writeCommand(i ? invertOnCommand : invertOffCommand);
- endWrite();
-}
-
-
-/**************************************************************************/
-/*!
- @brief Draw a 16-bit image (RGB 5/6/5) at the specified (x,y) position.
- For 16-bit display devices; no color reduction performed.
- Adapted from https://github.com/PaulStoffregen/ILI9341_t3
- by Marc MERLIN. See examples/pictureEmbed to use this.
- 5/6/2017: function name and arguments have changed for compatibility
- with current GFX library and to avoid naming problems in prior
- implementation. Formerly drawBitmap() with arguments in different order.
-
- @param x Top left corner x coordinate
- @param y Top left corner y coordinate
- @param pcolors 16-bit array with 16-bit color bitmap
- @param w Width of bitmap in pixels
- @param h Height of bitmap in pixels
-*/
-/**************************************************************************/
-void Adafruit_SPITFT::drawRGBBitmap(int16_t x, int16_t y,
- uint16_t *pcolors, int16_t w, int16_t h) {
-
- int16_t x2, y2; // Lower-right coord
- if(( x >= _width ) || // Off-edge right
- ( y >= _height) || // " top
- ((x2 = (x+w-1)) < 0 ) || // " left
- ((y2 = (y+h-1)) < 0) ) return; // " bottom
-
- int16_t bx1=0, by1=0, // Clipped top-left within bitmap
- saveW=w; // Save original bitmap width value
- if(x < 0) { // Clip left
- w += x;
- bx1 = -x;
- x = 0;
- }
- if(y < 0) { // Clip top
- h += y;
- by1 = -y;
- y = 0;
- }
- if(x2 >= _width ) w = _width - x; // Clip right
- if(y2 >= _height) h = _height - y; // Clip bottom
-
- pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
- startWrite();
- setAddrWindow(x, y, w, h); // Clipped area
- while(h--) { // For each (clipped) scanline...
- writePixels(pcolors, w); // Push one (clipped) row
- pcolors += saveW; // Advance pointer by one full (unclipped) line
- }
- endWrite();
-}
-
-#endif // !__AVR_ATtiny85__
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Adafruit_SPITFT.h b/lib/Adafruit-GFX-Library-1.2.9/Adafruit_SPITFT.h
deleted file mode 100644
index 53cdd985d..000000000
--- a/lib/Adafruit-GFX-Library-1.2.9/Adafruit_SPITFT.h
+++ /dev/null
@@ -1,125 +0,0 @@
-#ifndef _ADAFRUIT_SPITFT_
-#define _ADAFRUIT_SPITFT_
-
-#if ARDUINO >= 100
- #include "Arduino.h"
- #include "Print.h"
-#else
- #include "WProgram.h"
-#endif
-#include
-#include "Adafruit_GFX.h"
-
-#define USE_FAST_PINIO
-
-#if defined(__AVR__)
- typedef volatile uint8_t RwReg;
-#elif defined(ARDUINO_STM32_FEATHER)
- typedef volatile uint32 RwReg;
- #undef USE_FAST_PINIO
-#elif defined(__OPENCR__) || defined (__OPENCM904__)
- #undef USE_FAST_PINIO
-#elif defined(ARDUINO_FEATHER52) || defined(__arm__)
- typedef volatile uint32_t RwReg;
-#elif defined(ESP32) || defined(ESP8266)
- typedef volatile uint32_t RwReg;
- #undef USE_FAST_PINIO
-#else
- #undef USE_FAST_PINIO
-#endif
-
-#include "Adafruit_SPITFT_Macros.h"
-
-/// A heavily optimized SPI display subclass of GFX. Manages SPI bitbanging, transactions, DMA, etc! Despite being called SPITFT, the classic SPI data/command interface is also used by OLEDs.
-class Adafruit_SPITFT : public Adafruit_GFX {
- protected:
-
- public:
- Adafruit_SPITFT(uint16_t w, uint16_t h, int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK, int8_t _RST = -1, int8_t _MISO = -1);
- Adafruit_SPITFT(uint16_t w, uint16_t h, int8_t _CS, int8_t _DC, int8_t _RST = -1);
-
- virtual void begin(uint32_t freq) = 0; ///< Virtual begin() function to set SPI frequency, must be overridden in subclass. @param freq Maximum SPI hardware clock speed
-
- void initSPI(uint32_t freq);
-
- // Required Non-Transaction
- void drawPixel(int16_t x, int16_t y, uint16_t color);
-
- // Transaction API
- void startWrite(void);
- void endWrite(void);
-
- void writePixel(int16_t x, int16_t y, uint16_t color);
- void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
- void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
- void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
-
- // Transaction API not used by GFX
-
- /*!
- @brief SPI displays set an address window rectangle for blitting pixels
- @param x Top left corner x coordinate
- @param y Top left corner x coordinate
- @param w Width of window
- @param h Height of window
- */
- virtual void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) = 0;
-
- /*!
- @brief Write a 2-byte color (must have a transaction in progress)
- @param color 16-bit 5-6-5 Color to draw
- */
- void inline writePixel(uint16_t color) { SPI_WRITE16(color); }
- void writePixels(uint16_t * colors, uint32_t len);
- void writeColor(uint16_t color, uint32_t len);
- void pushColor(uint16_t color);
-
- // Recommended Non-Transaction
- void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
- void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
- void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
-
- using Adafruit_GFX::drawRGBBitmap; // Check base class first
- void drawRGBBitmap(int16_t x, int16_t y,
- uint16_t *pcolors, int16_t w, int16_t h);
- void invertDisplay(boolean i);
-
- uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
-
- protected:
- uint32_t _freq; ///< SPI clock frequency (for hardware SPI)
-#if defined (__AVR__) || defined(TEENSYDUINO) || defined (ESP8266) || defined (ESP32)
- int8_t _cs, _dc, _rst, _sclk, _mosi, _miso;
-#else
- int32_t _cs, ///< Arduino pin # for chip-select pin
- _dc, ///< Arduino pin # for data-command pin
- _rst, ///< Arduino pin # for reset pin
- _sclk, ///< Arduino pin # for SPI clock pin
- _mosi, ///< Arduino pin # for SPI MOSI pin
- _miso; ///< Arduino pin # for SPI MISO pin
-#endif
-
-#ifdef USE_FAST_PINIO
- volatile RwReg *mosiport, ///< Direct chip register for toggling MOSI with fast bitbang IO
- *misoport, ///< Direct chip register for toggling MISO with fast bitbang IO
- *clkport, ///< Direct chip register for toggling CLK with fast bitbang IO
- *dcport, ///< Direct chip register for toggling DC with fast bitbang IO
- *csport; ///< Direct chip register for toggling CS with fast bitbang IO
- RwReg mosipinmask, ///< bitmask for turning on/off MOSI with fast register bitbang IO
- misopinmask, ///< bitmask for turning on/off MISO with fast register bitbang IO
- clkpinmask, ///< bitmask for turning on/off CLK with fast register bitbang IO
- cspinmask, ///< bitmask for turning on/off CS with fast register bitbang IO
- dcpinmask; ///< bitmask for turning on/off DC with fast register bitbang IO
-#endif
-
- void writeCommand(uint8_t cmd);
- void spiWrite(uint8_t v);
- uint8_t spiRead(void);
-
- uint8_t invertOnCommand = 0, ///< SPI command byte to turn on invert
- invertOffCommand = 0; ///< SPI command byte to turn off invert
- int16_t _xstart = 0; ///< Many displays don't have pixels starting at (0,0) of the internal framebuffer, this is the x offset from 0 to align
- int16_t _ystart = 0; ///< Many displays don't have pixels starting at (0,0) of the internal framebuffer, this is the y offset from 0 to align
-};
-
-#endif
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Adafruit_SPITFT_Macros.h b/lib/Adafruit-GFX-Library-1.2.9/Adafruit_SPITFT_Macros.h
deleted file mode 100644
index f0466ef5f..000000000
--- a/lib/Adafruit-GFX-Library-1.2.9/Adafruit_SPITFT_Macros.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#ifndef _ADAFRUIT_SPITFT_MACROS
-#define _ADAFRUIT_SPITFT_MACROS
-
-/*
- * Control Pins
- * */
-
-#ifdef USE_FAST_PINIO
-#define SPI_DC_HIGH() *dcport |= dcpinmask
-#define SPI_DC_LOW() *dcport &= ~dcpinmask
-#define SPI_CS_HIGH() *csport |= cspinmask
-#define SPI_CS_LOW() *csport &= ~cspinmask
-#else
-#define SPI_DC_HIGH() digitalWrite(_dc, HIGH)
-#define SPI_DC_LOW() digitalWrite(_dc, LOW)
-#define SPI_CS_HIGH() { if(_cs >= 0) digitalWrite(_cs, HIGH); }
-#define SPI_CS_LOW() { if(_cs >= 0) digitalWrite(_cs, LOW); }
-#endif
-
-/*
- * Software SPI Macros
- * */
-
-#ifdef USE_FAST_PINIO
-#define SSPI_MOSI_HIGH() *mosiport |= mosipinmask
-#define SSPI_MOSI_LOW() *mosiport &= ~mosipinmask
-#define SSPI_SCK_HIGH() *clkport |= clkpinmask
-#define SSPI_SCK_LOW() *clkport &= ~clkpinmask
-#define SSPI_MISO_READ() ((*misoport & misopinmask) != 0)
-#else
-#define SSPI_MOSI_HIGH() digitalWrite(_mosi, HIGH)
-#define SSPI_MOSI_LOW() digitalWrite(_mosi, LOW)
-#define SSPI_SCK_HIGH() digitalWrite(_sclk, HIGH)
-#define SSPI_SCK_LOW() digitalWrite(_sclk, LOW)
-#define SSPI_MISO_READ() digitalRead(_miso)
-#endif
-
-#define SSPI_BEGIN_TRANSACTION()
-#define SSPI_END_TRANSACTION()
-#define SSPI_WRITE(v) spiWrite(v)
-#define SSPI_WRITE16(s) SSPI_WRITE((s) >> 8); SSPI_WRITE(s)
-#define SSPI_WRITE32(l) SSPI_WRITE((l) >> 24); SSPI_WRITE((l) >> 16); SSPI_WRITE((l) >> 8); SSPI_WRITE(l)
-#define SSPI_WRITE_PIXELS(c,l) for(uint32_t i=0; i<(l); i+=2){ SSPI_WRITE(((uint8_t*)(c))[i+1]); SSPI_WRITE(((uint8_t*)(c))[i]); }
-
-/*
- * Hardware SPI Macros
- * */
-
-#define SPI_OBJECT SPI
-
-#if defined (__AVR__) || defined(TEENSYDUINO) || defined(ARDUINO_ARCH_STM32F1)
- #define HSPI_SET_CLOCK() SPI_OBJECT.setClockDivider(SPI_CLOCK_DIV2);
-#elif defined (__arm__)
- #define HSPI_SET_CLOCK() SPI_OBJECT.setClockDivider(11);
-#elif defined(ESP8266) || defined(ESP32)
- #define HSPI_SET_CLOCK() SPI_OBJECT.setFrequency(_freq);
-#elif defined(RASPI)
- #define HSPI_SET_CLOCK() SPI_OBJECT.setClock(_freq);
-#elif defined(ARDUINO_ARCH_STM32F1)
- #define HSPI_SET_CLOCK() SPI_OBJECT.setClock(_freq);
-#else
- #define HSPI_SET_CLOCK()
-#endif
-
-#ifdef SPI_HAS_TRANSACTION
- #define HSPI_BEGIN_TRANSACTION() SPI_OBJECT.beginTransaction(SPISettings(_freq, MSBFIRST, SPI_MODE0))
- #define HSPI_END_TRANSACTION() SPI_OBJECT.endTransaction()
-#else
- #define HSPI_BEGIN_TRANSACTION() HSPI_SET_CLOCK(); SPI_OBJECT.setBitOrder(MSBFIRST); SPI_OBJECT.setDataMode(SPI_MODE0)
- #define HSPI_END_TRANSACTION()
-#endif
-
-#ifdef ESP32
- #define SPI_HAS_WRITE_PIXELS
-#endif
-#if defined(ESP8266) || defined(ESP32)
- // Optimized SPI (ESP8266 and ESP32)
- #define HSPI_READ() SPI_OBJECT.transfer(0)
- #define HSPI_WRITE(b) SPI_OBJECT.write(b)
- #define HSPI_WRITE16(s) SPI_OBJECT.write16(s)
- #define HSPI_WRITE32(l) SPI_OBJECT.write32(l)
- #ifdef SPI_HAS_WRITE_PIXELS
- #define SPI_MAX_PIXELS_AT_ONCE 32
- #define HSPI_WRITE_PIXELS(c,l) SPI_OBJECT.writePixels(c,l)
- #else
- #define HSPI_WRITE_PIXELS(c,l) for(uint32_t i=0; i<((l)/2); i++){ SPI_WRITE16(((uint16_t*)(c))[i]); }
- #endif
-#else
- // Standard Byte-by-Byte SPI
-
- #if defined (__AVR__) || defined(TEENSYDUINO)
-static inline uint8_t _avr_spi_read(void) __attribute__((always_inline));
-static inline uint8_t _avr_spi_read(void) {
- uint8_t r = 0;
- SPDR = r;
- while(!(SPSR & _BV(SPIF)));
- r = SPDR;
- return r;
-}
- #define HSPI_WRITE(b) {SPDR = (b); while(!(SPSR & _BV(SPIF)));}
- #define HSPI_READ() _avr_spi_read()
- #else
- #define HSPI_WRITE(b) SPI_OBJECT.transfer((uint8_t)(b))
- #define HSPI_READ() HSPI_WRITE(0)
- #endif
- #define HSPI_WRITE16(s) HSPI_WRITE((s) >> 8); HSPI_WRITE(s)
- #define HSPI_WRITE32(l) HSPI_WRITE((l) >> 24); HSPI_WRITE((l) >> 16); HSPI_WRITE((l) >> 8); HSPI_WRITE(l)
- #define HSPI_WRITE_PIXELS(c,l) for(uint32_t i=0; i<(l); i+=2){ HSPI_WRITE(((uint8_t*)(c))[i+1]); HSPI_WRITE(((uint8_t*)(c))[i]); }
-#endif
-
-#define SPI_BEGIN() if(_sclk < 0){SPI_OBJECT.begin();}
-#define SPI_BEGIN_TRANSACTION() if(_sclk < 0){HSPI_BEGIN_TRANSACTION();}
-#define SPI_END_TRANSACTION() if(_sclk < 0){HSPI_END_TRANSACTION();}
-#define SPI_WRITE16(s) if(_sclk < 0){HSPI_WRITE16(s);}else{SSPI_WRITE16(s);}
-#define SPI_WRITE32(l) if(_sclk < 0){HSPI_WRITE32(l);}else{SSPI_WRITE32(l);}
-#define SPI_WRITE_PIXELS(c,l) if(_sclk < 0){HSPI_WRITE_PIXELS(c,l);}else{SSPI_WRITE_PIXELS(c,l);}
-
-#endif // _ADAFRUIT_SPITFT_MACROS
diff --git a/lib/Adafruit-GFX-Library-1.2.9/.gitignore b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/.gitignore
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore
diff --git a/lib/Adafruit-GFX-Library-1.2.9/.travis.yml b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml
similarity index 87%
rename from lib/Adafruit-GFX-Library-1.2.9/.travis.yml
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml
index a856c6db6..d0836629f 100644
--- a/lib/Adafruit-GFX-Library-1.2.9/.travis.yml
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml
@@ -9,7 +9,6 @@ git:
quiet: true
env:
global:
- - ARDUINO_IDE_VERSION="1.8.5"
- PRETTYNAME="Adafruit GFX Library"
before_install:
@@ -24,4 +23,4 @@ script:
# Generate and deploy documentation
after_success:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh)
- - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)
\ No newline at end of file
+ - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Adafruit_GFX.cpp b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp
similarity index 85%
rename from lib/Adafruit-GFX-Library-1.2.9/Adafruit_GFX.cpp
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp
index c431a17c8..8741e6247 100644
--- a/lib/Adafruit-GFX-Library-1.2.9/Adafruit_GFX.cpp
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp
@@ -62,6 +62,30 @@ POSSIBILITY OF SUCH DAMAGE.
#define pgm_read_pointer(addr) ((void *)pgm_read_word(addr))
#endif
+inline GFXglyph * pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c)
+{
+#ifdef __AVR__
+ return &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
+#else
+ // expression in __AVR__ section may generate "dereferencing type-punned pointer will break strict-aliasing rules" warning
+ // In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
+ // So expression may be simplified
+ return gfxFont->glyph + c;
+#endif //__AVR__
+}
+
+inline uint8_t * pgm_read_bitmap_ptr(const GFXfont *gfxFont)
+{
+#ifdef __AVR__
+ return (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);
+#else
+ // expression in __AVR__ section generates "dereferencing type-punned pointer will break strict-aliasing rules" warning
+ // In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
+ // So expression may be simplified
+ return gfxFont->bitmap;
+#endif //__AVR__
+}
+
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
@@ -84,7 +108,7 @@ WIDTH(w), HEIGHT(h)
_height = HEIGHT;
rotation = 0;
cursor_y = cursor_x = 0;
- textsize = 1;
+ textsize_x = textsize_y = 1;
textcolor = textbgcolor = 0xFFFF;
wrap = true;
_cp437 = false;
@@ -103,6 +127,9 @@ WIDTH(w), HEIGHT(h)
/**************************************************************************/
void Adafruit_GFX::writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
uint16_t color) {
+#if defined(ESP8266)
+ yield();
+#endif
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
_swap_int16_t(x0, y0);
@@ -317,6 +344,9 @@ void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
/**************************************************************************/
void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
uint16_t color) {
+#if defined(ESP8266)
+ yield();
+#endif
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
@@ -353,7 +383,7 @@ void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
/**************************************************************************/
/*!
- @brief Quarter-circle drawer, used to do circles and roundrects
+ @brief Quarter-circle drawer, used to do circles and roundrects
@param x0 Center-point x coordinate
@param y0 Center-point y coordinate
@param r Radius of circle
@@ -417,25 +447,29 @@ void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
/**************************************************************************/
/*!
- @brief Quarter-circle drawer with fill, used to do circles and roundrects
- @param x0 Center-point x coordinate
- @param y0 Center-point y coordinate
- @param r Radius of circle
- @param cornername Mask bit #1 or bit #2 to indicate which quarters of the circle we're doing
- @param delta Offset from center-point, used for round-rects
- @param color 16-bit 5-6-5 Color to fill with
+ @brief Quarter-circle drawer with fill, used for circles and roundrects
+ @param x0 Center-point x coordinate
+ @param y0 Center-point y coordinate
+ @param r Radius of circle
+ @param corners Mask bits indicating which quarters we're doing
+ @param delta Offset from center-point, used for round-rects
+ @param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
- uint8_t cornername, int16_t delta, uint16_t color) {
+ uint8_t corners, int16_t delta, uint16_t color) {
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;
+ int16_t px = x;
+ int16_t py = y;
- while (x= 0) {
y--;
ddF_y += 2;
@@ -444,15 +478,18 @@ void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
x++;
ddF_x += 2;
f += ddF_x;
-
- if (cornername & 0x1) {
- writeFastVLine(x0+x, y0-y, 2*y+1+delta, color);
- writeFastVLine(x0+y, y0-x, 2*x+1+delta, color);
+ // These checks avoid double-drawing certain lines, important
+ // for the SSD1306 library which has an INVERT drawing mode.
+ if(x < (y + 1)) {
+ if(corners & 1) writeFastVLine(x0+x, y0-y, 2*y+delta, color);
+ if(corners & 2) writeFastVLine(x0-x, y0-y, 2*y+delta, color);
}
- if (cornername & 0x2) {
- writeFastVLine(x0-x, y0-y, 2*y+1+delta, color);
- writeFastVLine(x0-y, y0-x, 2*x+1+delta, color);
+ if(y != py) {
+ if(corners & 1) writeFastVLine(x0+py, y0-px, 2*px+delta, color);
+ if(corners & 2) writeFastVLine(x0-py, y0-px, 2*px+delta, color);
+ py = y;
}
+ px = x;
}
}
@@ -488,7 +525,9 @@ void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h,
*/
/**************************************************************************/
void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
- int16_t h, int16_t r, uint16_t color) {
+ int16_t h, int16_t r, uint16_t color) {
+ int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis
+ if(r > max_radius) r = max_radius;
// smarter version
startWrite();
writeFastHLine(x+r , y , w-2*r, color); // Top
@@ -515,11 +554,12 @@ void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
*/
/**************************************************************************/
void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
- int16_t h, int16_t r, uint16_t color) {
+ int16_t h, int16_t r, uint16_t color) {
+ int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis
+ if(r > max_radius) r = max_radius;
// smarter version
startWrite();
writeFillRect(x+r, y, w-2*r, h, color);
-
// draw four corners
fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
@@ -620,8 +660,8 @@ void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0,
// For lower part of triangle, find scanline crossings for segments
// 0-2 and 1-2. This loop is skipped if y1=y2.
- sa = dx12 * (y - y1);
- sb = dx02 * (y - y0);
+ sa = (int32_t)dx12 * (y - y1);
+ sb = (int32_t)dx02 * (y - y0);
for(; y<=y2; y++) {
a = x1 + sa / dy12;
b = x0 + sb / dy02;
@@ -646,7 +686,7 @@ void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0,
@param y Top left corner y coordinate
@param bitmap byte array with monochrome bitmap
@param w Width of bitmap in pixels
- @param h Hieght of bitmap in pixels
+ @param h Height of bitmap in pixels
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
@@ -674,7 +714,7 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
@param y Top left corner y coordinate
@param bitmap byte array with monochrome bitmap
@param w Width of bitmap in pixels
- @param h Hieght of bitmap in pixels
+ @param h Height of bitmap in pixels
@param color 16-bit 5-6-5 Color to draw pixels with
@param bg 16-bit 5-6-5 Color to draw background with
*/
@@ -704,7 +744,7 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
@param y Top left corner y coordinate
@param bitmap byte array with monochrome bitmap
@param w Width of bitmap in pixels
- @param h Hieght of bitmap in pixels
+ @param h Height of bitmap in pixels
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
@@ -732,7 +772,7 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
@param y Top left corner y coordinate
@param bitmap byte array with monochrome bitmap
@param w Width of bitmap in pixels
- @param h Hieght of bitmap in pixels
+ @param h Height of bitmap in pixels
@param color 16-bit 5-6-5 Color to draw pixels with
@param bg 16-bit 5-6-5 Color to draw background with
*/
@@ -756,7 +796,7 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
/**************************************************************************/
/*!
- @brief Draw PROGMEM-resident XBitMap Files (*.xbm), exported from GIMP.
+ @brief Draw PROGMEM-resident XBitMap Files (*.xbm), exported from GIMP.
Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor.
C Array can be directly used with this function.
There is no RAM-resident version of this function; if generating bitmaps
@@ -765,7 +805,7 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
@param y Top left corner y coordinate
@param bitmap byte array with monochrome bitmap
@param w Width of bitmap in pixels
- @param h Hieght of bitmap in pixels
+ @param h Height of bitmap in pixels
@param color 16-bit 5-6-5 Color to draw pixels with
*/
/**************************************************************************/
@@ -791,13 +831,13 @@ void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y,
/**************************************************************************/
/*!
- @brief Draw a PROGMEM-resident 8-bit image (grayscale) at the specified (x,y) pos.
+ @brief Draw a PROGMEM-resident 8-bit image (grayscale) at the specified (x,y) pos.
Specifically for 8-bit display devices such as IS31FL3731; no color reduction/expansion is performed.
@param x Top left corner x coordinate
@param y Top left corner y coordinate
@param bitmap byte array with grayscale bitmap
@param w Width of bitmap in pixels
- @param h Hieght of bitmap in pixels
+ @param h Height of bitmap in pixels
*/
/**************************************************************************/
void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y,
@@ -813,13 +853,13 @@ void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y,
/**************************************************************************/
/*!
- @brief Draw a RAM-resident 8-bit image (grayscale) at the specified (x,y) pos.
+ @brief Draw a RAM-resident 8-bit image (grayscale) at the specified (x,y) pos.
Specifically for 8-bit display devices such as IS31FL3731; no color reduction/expansion is performed.
@param x Top left corner x coordinate
@param y Top left corner y coordinate
@param bitmap byte array with grayscale bitmap
@param w Width of bitmap in pixels
- @param h Hieght of bitmap in pixels
+ @param h Height of bitmap in pixels
*/
/**************************************************************************/
void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y,
@@ -900,7 +940,7 @@ void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y,
/**************************************************************************/
/*!
- @brief Draw a PROGMEM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) position.
+ @brief Draw a PROGMEM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) position.
For 16-bit display devices; no color reduction performed.
@param x Top left corner x coordinate
@param y Top left corner y coordinate
@@ -922,7 +962,7 @@ void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y,
/**************************************************************************/
/*!
- @brief Draw a RAM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) position.
+ @brief Draw a RAM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) position.
For 16-bit display devices; no color reduction performed.
@param x Top left corner x coordinate
@param y Top left corner y coordinate
@@ -1016,13 +1056,31 @@ void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y,
/**************************************************************************/
void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
uint16_t color, uint16_t bg, uint8_t size) {
+ drawChar(x, y, c, color, bg, size, size);
+}
+
+// Draw a character
+/**************************************************************************/
+/*!
+ @brief Draw a single character
+ @param x Bottom left corner x coordinate
+ @param y Bottom left corner y coordinate
+ @param c The 8-bit font-indexed character (likely ascii)
+ @param color 16-bit 5-6-5 Color to draw chraracter with
+ @param bg 16-bit 5-6-5 Color to fill background with (if same as color, no background)
+ @param size_x Font magnification level in X-axis, 1 is 'original' size
+ @param size_y Font magnification level in Y-axis, 1 is 'original' size
+*/
+/**************************************************************************/
+void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
+ uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y) {
if(!gfxFont) { // 'Classic' built-in font
if((x >= _width) || // Clip right
(y >= _height) || // Clip bottom
- ((x + 6 * size - 1) < 0) || // Clip left
- ((y + 8 * size - 1) < 0)) // Clip top
+ ((x + 6 * size_x - 1) < 0) || // Clip left
+ ((y + 8 * size_y - 1) < 0)) // Clip top
return;
if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior
@@ -1032,21 +1090,21 @@ void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
uint8_t line = pgm_read_byte(&font[c * 5 + i]);
for(int8_t j=0; j<8; j++, line >>= 1) {
if(line & 1) {
- if(size == 1)
+ if(size_x == 1 && size_y == 1)
writePixel(x+i, y+j, color);
else
- writeFillRect(x+i*size, y+j*size, size, size, color);
+ writeFillRect(x+i*size_x, y+j*size_y, size_x, size_y, color);
} else if(bg != color) {
- if(size == 1)
+ if(size_x == 1 && size_y == 1)
writePixel(x+i, y+j, bg);
else
- writeFillRect(x+i*size, y+j*size, size, size, bg);
+ writeFillRect(x+i*size_x, y+j*size_y, size_x, size_y, bg);
}
}
}
if(bg != color) { // If opaque, draw vertical line for last column
- if(size == 1) writeFastVLine(x+5, y, 8, bg);
- else writeFillRect(x+5*size, y, size, 8*size, bg);
+ if(size_x == 1 && size_y == 1) writeFastVLine(x+5, y, 8, bg);
+ else writeFillRect(x+5*size_x, y, size_x, 8*size_y, bg);
}
endWrite();
@@ -1057,8 +1115,8 @@ void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
// drawChar() directly with 'bad' characters of font may cause mayhem!
c -= (uint8_t)pgm_read_byte(&gfxFont->first);
- GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
- uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);
+ GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c);
+ uint8_t *bitmap = pgm_read_bitmap_ptr(gfxFont);
uint16_t bo = pgm_read_word(&glyph->bitmapOffset);
uint8_t w = pgm_read_byte(&glyph->width),
@@ -1068,7 +1126,7 @@ void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
uint8_t xx, yy, bits = 0, bit = 0;
int16_t xo16 = 0, yo16 = 0;
- if(size > 1) {
+ if(size_x > 1 || size_y > 1) {
xo16 = xo;
yo16 = yo;
}
@@ -1098,11 +1156,11 @@ void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
bits = pgm_read_byte(&bitmap[bo++]);
}
if(bits & 0x80) {
- if(size == 1) {
+ if(size_x == 1 && size_y == 1) {
writePixel(x+xo+xx, y+yo+yy, color);
} else {
- writeFillRect(x+(xo16+xx)*size, y+(yo16+yy)*size,
- size, size, color);
+ writeFillRect(x+(xo16+xx)*size_x, y+(yo16+yy)*size_y,
+ size_x, size_y, color);
}
}
bits <<= 1;
@@ -1123,39 +1181,38 @@ size_t Adafruit_GFX::write(uint8_t c) {
if(c == '\n') { // Newline?
cursor_x = 0; // Reset x to zero,
- cursor_y += textsize * 8; // advance y one line
+ cursor_y += textsize_y * 8; // advance y one line
} else if(c != '\r') { // Ignore carriage returns
- if(wrap && ((cursor_x + textsize * 6) > _width)) { // Off right?
+ if(wrap && ((cursor_x + textsize_x * 6) > _width)) { // Off right?
cursor_x = 0; // Reset x to zero,
- cursor_y += textsize * 8; // advance y one line
+ cursor_y += textsize_y * 8; // advance y one line
}
- drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
- cursor_x += textsize * 6; // Advance x one char
+ drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize_x, textsize_y);
+ cursor_x += textsize_x * 6; // Advance x one char
}
} else { // Custom font
if(c == '\n') {
cursor_x = 0;
- cursor_y += (int16_t)textsize *
+ cursor_y += (int16_t)textsize_y *
(uint8_t)pgm_read_byte(&gfxFont->yAdvance);
} else if(c != '\r') {
uint8_t first = pgm_read_byte(&gfxFont->first);
if((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) {
- GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(
- &gfxFont->glyph))[c - first]);
+ GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first);
uint8_t w = pgm_read_byte(&glyph->width),
h = pgm_read_byte(&glyph->height);
if((w > 0) && (h > 0)) { // Is there an associated bitmap?
int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic
- if(wrap && ((cursor_x + textsize * (xo + w)) > _width)) {
+ if(wrap && ((cursor_x + textsize_x * (xo + w)) > _width)) {
cursor_x = 0;
- cursor_y += (int16_t)textsize *
+ cursor_y += (int16_t)textsize_y *
(uint8_t)pgm_read_byte(&gfxFont->yAdvance);
}
- drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
+ drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize_x, textsize_y);
}
- cursor_x += (uint8_t)pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize;
+ cursor_x += (uint8_t)pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize_x;
}
}
@@ -1163,37 +1220,6 @@ size_t Adafruit_GFX::write(uint8_t c) {
return 1;
}
-/**************************************************************************/
-/*!
- @brief Set text cursor location
- @param x X coordinate in pixels
- @param y Y coordinate in pixels
-*/
-/**************************************************************************/
-void Adafruit_GFX::setCursor(int16_t x, int16_t y) {
- cursor_x = x;
- cursor_y = y;
-}
-
-/**************************************************************************/
-/*!
- @brief Get text cursor X location
- @returns X coordinate in pixels
-*/
-/**************************************************************************/
-int16_t Adafruit_GFX::getCursorX(void) const {
- return cursor_x;
-}
-
-/**************************************************************************/
-/*!
- @brief Get text cursor Y location
- @returns Y coordinate in pixels
-*/
-/**************************************************************************/
-int16_t Adafruit_GFX::getCursorY(void) const {
- return cursor_y;
-}
/**************************************************************************/
/*!
@@ -1202,51 +1228,19 @@ int16_t Adafruit_GFX::getCursorY(void) const {
*/
/**************************************************************************/
void Adafruit_GFX::setTextSize(uint8_t s) {
- textsize = (s > 0) ? s : 1;
+ setTextSize(s, s);
}
/**************************************************************************/
/*!
- @brief Set text font color with transparant background
- @param c 16-bit 5-6-5 Color to draw text with
+ @brief Set text 'magnification' size. Each increase in s makes 1 pixel that much bigger.
+ @param s_x Desired text width magnification level in X-axis. 1 is default
+ @param s_y Desired text width magnification level in Y-axis. 1 is default
*/
/**************************************************************************/
-void Adafruit_GFX::setTextColor(uint16_t c) {
- // For 'transparent' background, we'll set the bg
- // to the same as fg instead of using a flag
- textcolor = textbgcolor = c;
-}
-
-/**************************************************************************/
-/*!
- @brief Set text font color with custom background color
- @param c 16-bit 5-6-5 Color to draw text with
- @param b 16-bit 5-6-5 Color to draw background/fill with
-*/
-/**************************************************************************/
-void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
- textcolor = c;
- textbgcolor = b;
-}
-
-/**************************************************************************/
-/*!
- @brief Whether text that is too long should 'wrap' around to the next line.
- @param w Set true for wrapping, false for clipping
-*/
-/**************************************************************************/
-void Adafruit_GFX::setTextWrap(boolean w) {
- wrap = w;
-}
-
-/**************************************************************************/
-/*!
- @brief Get rotation setting for display
- @returns 0 thru 3 corresponding to 4 cardinal rotations
-*/
-/**************************************************************************/
-uint8_t Adafruit_GFX::getRotation(void) const {
- return rotation;
+void Adafruit_GFX::setTextSize(uint8_t s_x, uint8_t s_y) {
+ textsize_x = (s_x > 0) ? s_x : 1;
+ textsize_y = (s_y > 0) ? s_y : 1;
}
/**************************************************************************/
@@ -1271,22 +1265,6 @@ void Adafruit_GFX::setRotation(uint8_t x) {
}
}
-/**************************************************************************/
-/*!
- @brief Enable (or disable) Code Page 437-compatible charset.
- There was an error in glcdfont.c for the longest time -- one character
- (#176, the 'light shade' block) was missing -- this threw off the index
- of every character that followed it. But a TON of code has been written
- with the erroneous character indices. By default, the library uses the
- original 'wrong' behavior and old sketches will still work. Pass 'true'
- to this function to use correct CP437 character values in your code.
- @param x Whether to enable (True) or not (False)
-*/
-/**************************************************************************/
-void Adafruit_GFX::cp437(boolean x) {
- _cp437 = x;
-}
-
/**************************************************************************/
/*!
@brief Set the font to display when print()ing, either custom or default
@@ -1329,32 +1307,32 @@ void Adafruit_GFX::charBounds(char c, int16_t *x, int16_t *y,
if(c == '\n') { // Newline?
*x = 0; // Reset x to zero, advance y by one line
- *y += textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
+ *y += textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
} else if(c != '\r') { // Not a carriage return; is normal char
uint8_t first = pgm_read_byte(&gfxFont->first),
last = pgm_read_byte(&gfxFont->last);
if((c >= first) && (c <= last)) { // Char present in this font?
- GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(
- &gfxFont->glyph))[c - first]);
+ GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first);
uint8_t gw = pgm_read_byte(&glyph->width),
gh = pgm_read_byte(&glyph->height),
xa = pgm_read_byte(&glyph->xAdvance);
int8_t xo = pgm_read_byte(&glyph->xOffset),
yo = pgm_read_byte(&glyph->yOffset);
- if(wrap && ((*x+(((int16_t)xo+gw)*textsize)) > _width)) {
+ if(wrap && ((*x+(((int16_t)xo+gw)*textsize_x)) > _width)) {
*x = 0; // Reset x to zero, advance y by one line
- *y += textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
+ *y += textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
}
- int16_t ts = (int16_t)textsize,
- x1 = *x + xo * ts,
- y1 = *y + yo * ts,
- x2 = x1 + gw * ts - 1,
- y2 = y1 + gh * ts - 1;
+ int16_t tsx = (int16_t)textsize_x,
+ tsy = (int16_t)textsize_y,
+ x1 = *x + xo * tsx,
+ y1 = *y + yo * tsy,
+ x2 = x1 + gw * tsx - 1,
+ y2 = y1 + gh * tsy - 1;
if(x1 < *minx) *minx = x1;
if(y1 < *miny) *miny = y1;
if(x2 > *maxx) *maxx = x2;
if(y2 > *maxy) *maxy = y2;
- *x += xa * ts;
+ *x += xa * tsx;
}
}
@@ -1362,20 +1340,20 @@ void Adafruit_GFX::charBounds(char c, int16_t *x, int16_t *y,
if(c == '\n') { // Newline?
*x = 0; // Reset x to zero,
- *y += textsize * 8; // advance y one line
+ *y += textsize_y * 8; // advance y one line
// min/max x/y unchaged -- that waits for next 'normal' character
} else if(c != '\r') { // Normal char; ignore carriage returns
- if(wrap && ((*x + textsize * 6) > _width)) { // Off right?
+ if(wrap && ((*x + textsize_x * 6) > _width)) { // Off right?
*x = 0; // Reset x to zero,
- *y += textsize * 8; // advance y one line
+ *y += textsize_y * 8; // advance y one line
}
- int x2 = *x + textsize * 6 - 1, // Lower-right pixel of char
- y2 = *y + textsize * 8 - 1;
+ int x2 = *x + textsize_x * 6 - 1, // Lower-right pixel of char
+ y2 = *y + textsize_y * 8 - 1;
if(x2 > *maxx) *maxx = x2; // Track max x, y
if(y2 > *maxy) *maxy = y2;
if(*x < *minx) *minx = *x; // Track min x, y
if(*y < *miny) *miny = *y;
- *x += textsize * 6; // Advance x one char
+ *x += textsize_x * 6; // Advance x one char
}
}
}
@@ -1470,26 +1448,6 @@ void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str,
}
}
-/**************************************************************************/
-/*!
- @brief Get width of the display, accounting for the current rotation
- @returns Width in pixels
-*/
-/**************************************************************************/
-int16_t Adafruit_GFX::width(void) const {
- return _width;
-}
-
-/**************************************************************************/
-/*!
- @brief Get height of the display, accounting for the current rotation
- @returns Height in pixels
-*/
-/**************************************************************************/
-int16_t Adafruit_GFX::height(void) const {
- return _height;
-}
-
/**************************************************************************/
/*!
@brief Invert the display (ideally using built-in hardware command)
@@ -1537,6 +1495,33 @@ void Adafruit_GFX_Button::initButton(
textcolor, label, textsize);
}
+/**************************************************************************/
+/*!
+ @brief Initialize button with our desired color/size/settings
+ @param gfx Pointer to our display so we can draw to it!
+ @param x The X coordinate of the center of the button
+ @param y The Y coordinate of the center of the button
+ @param w Width of the buttton
+ @param h Height of the buttton
+ @param outline Color of the outline (16-bit 5-6-5 standard)
+ @param fill Color of the button fill (16-bit 5-6-5 standard)
+ @param textcolor Color of the button label (16-bit 5-6-5 standard)
+ @param label Ascii string of the text inside the button
+ @param textsize_x The font magnification in X-axis of the label text
+ @param textsize_y The font magnification in Y-axis of the label text
+*/
+/**************************************************************************/
+// Classic initButton() function: pass center & size
+void Adafruit_GFX_Button::initButton(
+ Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t w, uint16_t h,
+ uint16_t outline, uint16_t fill, uint16_t textcolor,
+ char *label, uint8_t textsize_x, uint8_t textsize_y)
+{
+ // Tweak arguments and pass to the newer initButtonUL() function...
+ initButtonUL(gfx, x - (w / 2), y - (h / 2), w, h, outline, fill,
+ textcolor, label, textsize_x, textsize_y);
+}
+
/**************************************************************************/
/*!
@brief Initialize button with our desired color/size/settings, with upper-left coordinates
@@ -1556,6 +1541,30 @@ void Adafruit_GFX_Button::initButtonUL(
Adafruit_GFX *gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h,
uint16_t outline, uint16_t fill, uint16_t textcolor,
char *label, uint8_t textsize)
+{
+ initButtonUL(gfx, x1, y1, w, h, outline, fill, textcolor, label, textsize, textsize);
+}
+
+/**************************************************************************/
+/*!
+ @brief Initialize button with our desired color/size/settings, with upper-left coordinates
+ @param gfx Pointer to our display so we can draw to it!
+ @param x1 The X coordinate of the Upper-Left corner of the button
+ @param y1 The Y coordinate of the Upper-Left corner of the button
+ @param w Width of the buttton
+ @param h Height of the buttton
+ @param outline Color of the outline (16-bit 5-6-5 standard)
+ @param fill Color of the button fill (16-bit 5-6-5 standard)
+ @param textcolor Color of the button label (16-bit 5-6-5 standard)
+ @param label Ascii string of the text inside the button
+ @param textsize_x The font magnification in X-axis of the label text
+ @param textsize_y The font magnification in Y-axis of the label text
+*/
+/**************************************************************************/
+void Adafruit_GFX_Button::initButtonUL(
+ Adafruit_GFX *gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h,
+ uint16_t outline, uint16_t fill, uint16_t textcolor,
+ char *label, uint8_t textsize_x, uint8_t textsize_y)
{
_x1 = x1;
_y1 = y1;
@@ -1564,7 +1573,8 @@ void Adafruit_GFX_Button::initButtonUL(
_outlinecolor = outline;
_fillcolor = fill;
_textcolor = textcolor;
- _textsize = textsize;
+ _textsize_x = textsize_x;
+ _textsize_y = textsize_y;
_gfx = gfx;
strncpy(_label, label, 9);
}
@@ -1592,19 +1602,20 @@ void Adafruit_GFX_Button::drawButton(boolean inverted) {
_gfx->fillRoundRect(_x1, _y1, _w, _h, r, fill);
_gfx->drawRoundRect(_x1, _y1, _w, _h, r, outline);
- _gfx->setCursor(_x1 + (_w/2) - (strlen(_label) * 3 * _textsize),
- _y1 + (_h/2) - (4 * _textsize));
+ _gfx->setCursor(_x1 + (_w/2) - (strlen(_label) * 3 * _textsize_x),
+ _y1 + (_h/2) - (4 * _textsize_y));
_gfx->setTextColor(text);
- _gfx->setTextSize(_textsize);
+ _gfx->setTextSize(_textsize_x, _textsize_y);
_gfx->print(_label);
+
}
/**************************************************************************/
/*!
- @brief Helper to let us know if a coordinate is within the bounds of the button
+ @brief Helper to let us know if a coordinate is within the bounds of the button
@param x The X coordinate to check
@param y The Y coordinate to check
- @returns True if within button graphics outline
+ @returns True if within button graphics outline
*/
/**************************************************************************/
boolean Adafruit_GFX_Button::contains(int16_t x, int16_t y) {
@@ -1612,25 +1623,6 @@ boolean Adafruit_GFX_Button::contains(int16_t x, int16_t y) {
(y >= _y1) && (y < (int16_t) (_y1 + _h)));
}
-/**************************************************************************/
-/*!
- @brief Sets the state of the button, should be done by some touch function
- @param p True for pressed, false for not.
-*/
-/**************************************************************************/
-void Adafruit_GFX_Button::press(boolean p) {
- laststate = currstate;
- currstate = p;
-}
-
-/**************************************************************************/
-/*!
- @brief Query whether the button is currently pressed
- @returns True if pressed
-*/
-/**************************************************************************/
-boolean Adafruit_GFX_Button::isPressed() { return currstate; }
-
/**************************************************************************/
/*!
@brief Query whether the button was pressed since we last checked state
@@ -1691,20 +1683,10 @@ GFXcanvas1::~GFXcanvas1(void) {
/**************************************************************************/
/*!
- @brief Get a pointer to the internal buffer memory
- @returns A pointer to the allocated buffer
-*/
-/**************************************************************************/
-uint8_t* GFXcanvas1::getBuffer(void) {
- return buffer;
-}
-
-/**************************************************************************/
-/*!
- @brief Draw a pixel to the canvas framebuffer
- @param x x coordinate
- @param y y coordinate
- @param color 16-bit 5-6-5 Color to fill with
+ @brief Draw a pixel to the canvas framebuffer
+ @param x x coordinate
+ @param y y coordinate
+ @param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFXcanvas1::drawPixel(int16_t x, int16_t y, uint16_t color) {
@@ -1749,8 +1731,8 @@ void GFXcanvas1::drawPixel(int16_t x, int16_t y, uint16_t color) {
/**************************************************************************/
/*!
- @brief Fill the framebuffer completely with one color
- @param color 16-bit 5-6-5 Color to fill with
+ @brief Fill the framebuffer completely with one color
+ @param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFXcanvas1::fillScreen(uint16_t color) {
@@ -1783,23 +1765,12 @@ GFXcanvas8::~GFXcanvas8(void) {
if(buffer) free(buffer);
}
-
/**************************************************************************/
/*!
- @brief Get a pointer to the internal buffer memory
- @returns A pointer to the allocated buffer
-*/
-/**************************************************************************/
-uint8_t* GFXcanvas8::getBuffer(void) {
- return buffer;
-}
-
-/**************************************************************************/
-/*!
- @brief Draw a pixel to the canvas framebuffer
- @param x x coordinate
- @param y y coordinate
- @param color 16-bit 5-6-5 Color to fill with
+ @brief Draw a pixel to the canvas framebuffer
+ @param x x coordinate
+ @param y y coordinate
+ @param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFXcanvas8::drawPixel(int16_t x, int16_t y, uint16_t color) {
@@ -1830,8 +1801,8 @@ void GFXcanvas8::drawPixel(int16_t x, int16_t y, uint16_t color) {
/**************************************************************************/
/*!
- @brief Fill the framebuffer completely with one color
- @param color 16-bit 5-6-5 Color to fill with
+ @brief Fill the framebuffer completely with one color
+ @param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFXcanvas8::fillScreen(uint16_t color) {
@@ -1900,20 +1871,10 @@ GFXcanvas16::~GFXcanvas16(void) {
/**************************************************************************/
/*!
- @brief Get a pointer to the internal buffer memory
- @returns A pointer to the allocated buffer
-*/
-/**************************************************************************/
-uint16_t* GFXcanvas16::getBuffer(void) {
- return buffer;
-}
-
-/**************************************************************************/
-/*!
- @brief Draw a pixel to the canvas framebuffer
- @param x x coordinate
- @param y y coordinate
- @param color 16-bit 5-6-5 Color to fill with
+ @brief Draw a pixel to the canvas framebuffer
+ @param x x coordinate
+ @param y y coordinate
+ @param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFXcanvas16::drawPixel(int16_t x, int16_t y, uint16_t color) {
@@ -1944,8 +1905,8 @@ void GFXcanvas16::drawPixel(int16_t x, int16_t y, uint16_t color) {
/**************************************************************************/
/*!
- @brief Fill the framebuffer completely with one color
- @param color 16-bit 5-6-5 Color to fill with
+ @brief Fill the framebuffer completely with one color
+ @param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFXcanvas16::fillScreen(uint16_t color) {
@@ -1960,3 +1921,22 @@ void GFXcanvas16::fillScreen(uint16_t color) {
}
}
+/**************************************************************************/
+/*!
+ @brief Reverses the "endian-ness" of each 16-bit pixel within the
+ canvas; little-endian to big-endian, or big-endian to little.
+ Most microcontrollers (such as SAMD) are little-endian, while
+ most displays tend toward big-endianness. All the drawing
+ functions (including RGB bitmap drawing) take care of this
+ automatically, but some specialized code (usually involving
+ DMA) can benefit from having pixel data already in the
+ display-native order. Note that this does NOT convert to a
+ SPECIFIC endian-ness, it just flips the bytes within each word.
+*/
+/**************************************************************************/
+void GFXcanvas16::byteSwap(void) {
+ if(buffer) {
+ uint32_t i, pixels = WIDTH * HEIGHT;
+ for(i=0; i= 100
virtual size_t write(uint8_t);
#else
virtual void write(uint8_t);
#endif
+ size_t iwrite(uint8_t);
+ /************************************************************************/
+ /*!
+ @brief Get width of the display, accounting for current rotation
+ @returns Width in pixels
+ */
+ /************************************************************************/
+ int16_t width(void) const { return _width; };
- int16_t height(void) const;
- int16_t width(void) const;
+ /************************************************************************/
+ /*!
+ @brief Get height of the display, accounting for current rotation
+ @returns Height in pixels
+ */
+ /************************************************************************/
+ int16_t height(void) const { return _height; }
- uint8_t getRotation(void) const;
+ /************************************************************************/
+ /*!
+ @brief Get rotation setting for display
+ @returns 0 thru 3 corresponding to 4 cardinal rotations
+ */
+ /************************************************************************/
+ uint8_t getRotation(void) const { return rotation; }
- // get current cursor position (get rotation safe maximum values, using: width() for x, height() for y)
- int16_t getCursorX(void) const;
- int16_t getCursorY(void) const;
+ // get current cursor position (get rotation safe maximum values,
+ // using: width() for x, height() for y)
+ /************************************************************************/
+ /*!
+ @brief Get text cursor X location
+ @returns X coordinate in pixels
+ */
+ /************************************************************************/
+ int16_t getCursorX(void) const { return cursor_x; }
+
+ /************************************************************************/
+ /*!
+ @brief Get text cursor Y location
+ @returns Y coordinate in pixels
+ */
+ /************************************************************************/
+ int16_t getCursorY(void) const { return cursor_y; };
+
+ uint16_t
+ textcolor, ///< 16-bit background color for print()
+ textbgcolor; ///< 16-bit text color for print()
protected:
void
charBounds(char c, int16_t *x, int16_t *y,
int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy);
- const int16_t
+ int16_t
WIDTH, ///< This is the 'raw' display width - never changes
HEIGHT; ///< This is the 'raw' display height - never changes
int16_t
@@ -137,11 +229,12 @@ class Adafruit_GFX : public Print {
_height, ///< Display height as modified by current rotation
cursor_x, ///< x location to start print()ing text
cursor_y; ///< y location to start print()ing text
- uint16_t
- textcolor, ///< 16-bit background color for print()
- textbgcolor; ///< 16-bit text color for print()
+ //uint16_t
+ // textcolor, ///< 16-bit background color for print()
+ // textbgcolor; ///< 16-bit text color for print()
uint8_t
- textsize, ///< Desired magnification of text to print()
+ textsize_x, ///< Desired magnification in X-axis of text to print()
+ textsize_y, ///< Desired magnification in Y-axis of text to print()
rotation; ///< Display rotation (0 thru 3)
boolean
wrap, ///< If set, 'wrap' text at right edge of display
@@ -160,23 +253,44 @@ class Adafruit_GFX_Button {
void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y,
uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
uint16_t textcolor, char *label, uint8_t textsize);
+ void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y,
+ uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
+ uint16_t textcolor, char *label, uint8_t textsize_x, uint8_t textsize_y);
// New/alt initButton() uses upper-left corner & size
void initButtonUL(Adafruit_GFX *gfx, int16_t x1, int16_t y1,
uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
uint16_t textcolor, char *label, uint8_t textsize);
+ void initButtonUL(Adafruit_GFX *gfx, int16_t x1, int16_t y1,
+ uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
+ uint16_t textcolor, char *label, uint8_t textsize_x, uint8_t textsize_y);
void drawButton(boolean inverted = false);
boolean contains(int16_t x, int16_t y);
- void press(boolean p);
- boolean isPressed();
+ /**********************************************************************/
+ /*!
+ @brief Sets button state, should be done by some touch function
+ @param p True for pressed, false for not.
+ */
+ /**********************************************************************/
+ void press(boolean p) { laststate = currstate; currstate = p; }
+
boolean justPressed();
boolean justReleased();
+ /**********************************************************************/
+ /*!
+ @brief Query whether the button is currently pressed
+ @returns True if pressed
+ */
+ /**********************************************************************/
+ boolean isPressed(void) { return currstate; };
+
private:
Adafruit_GFX *_gfx;
int16_t _x1, _y1; // Coordinates of top-left corner
uint16_t _w, _h;
- uint8_t _textsize;
+ uint8_t _textsize_x;
+ uint8_t _textsize_y;
uint16_t _outlinecolor, _fillcolor, _textcolor;
char _label[10];
@@ -191,7 +305,13 @@ class GFXcanvas1 : public Adafruit_GFX {
~GFXcanvas1(void);
void drawPixel(int16_t x, int16_t y, uint16_t color),
fillScreen(uint16_t color);
- uint8_t *getBuffer(void);
+ /**********************************************************************/
+ /*!
+ @brief Get a pointer to the internal buffer memory
+ @returns A pointer to the allocated buffer
+ */
+ /**********************************************************************/
+ uint8_t *getBuffer(void) const { return buffer; }
private:
uint8_t *buffer;
};
@@ -205,8 +325,13 @@ class GFXcanvas8 : public Adafruit_GFX {
void drawPixel(int16_t x, int16_t y, uint16_t color),
fillScreen(uint16_t color),
writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
-
- uint8_t *getBuffer(void);
+ /**********************************************************************/
+ /*!
+ @brief Get a pointer to the internal buffer memory
+ @returns A pointer to the allocated buffer
+ */
+ /**********************************************************************/
+ uint8_t *getBuffer(void) const { return buffer; }
private:
uint8_t *buffer;
};
@@ -218,8 +343,15 @@ class GFXcanvas16 : public Adafruit_GFX {
GFXcanvas16(uint16_t w, uint16_t h);
~GFXcanvas16(void);
void drawPixel(int16_t x, int16_t y, uint16_t color),
- fillScreen(uint16_t color);
- uint16_t *getBuffer(void);
+ fillScreen(uint16_t color),
+ byteSwap(void);
+ /**********************************************************************/
+ /*!
+ @brief Get a pointer to the internal buffer memory
+ @returns A pointer to the allocated buffer
+ */
+ /**********************************************************************/
+ uint16_t *getBuffer(void) const { return buffer; }
private:
uint16_t *buffer;
};
diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp
new file mode 100644
index 000000000..945ef41ab
--- /dev/null
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp
@@ -0,0 +1,2217 @@
+/*!
+ * @file Adafruit_SPITFT.cpp
+ *
+ * @mainpage Adafruit SPI TFT Displays (and some others)
+ *
+ * @section intro_sec Introduction
+ *
+ * Part of Adafruit's GFX graphics library. Originally this class was
+ * written to handle a range of color TFT displays connected via SPI,
+ * but over time this library and some display-specific subclasses have
+ * mutated to include some color OLEDs as well as parallel-interfaced
+ * displays. The name's been kept for the sake of older code.
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing
+ * products from Adafruit!
+
+ * @section dependencies Dependencies
+ *
+ * This library depends on
+ * Adafruit_GFX being present on your system. Please make sure you have
+ * installed the latest version before using this library.
+ *
+ * @section author Author
+ *
+ * Written by Limor "ladyada" Fried for Adafruit Industries,
+ * with contributions from the open source community.
+ *
+ * @section license License
+ *
+ * BSD license, all text here must be included in any redistribution.
+ */
+
+#if !defined(__AVR_ATtiny85__) // Not for ATtiny, at all
+
+#include "Adafruit_SPITFT.h"
+
+#if defined(__AVR__)
+#if defined(__AVR_XMEGA__) //only tested with __AVR_ATmega4809__
+#define AVR_WRITESPI(x) for(SPI0_DATA = (x); (!(SPI0_INTFLAGS & _BV(SPI_IF_bp))); )
+#else
+#define AVR_WRITESPI(x) for(SPDR = (x); (!(SPSR & _BV(SPIF))); )
+#endif
+#endif
+
+#if defined(PORT_IOBUS)
+// On SAMD21, redefine digitalPinToPort() to use the slightly-faster
+// PORT_IOBUS rather than PORT (not needed on SAMD51).
+#undef digitalPinToPort
+#define digitalPinToPort(P) (&(PORT_IOBUS->Group[g_APinDescription[P].ulPort]))
+#endif // end PORT_IOBUS
+
+#if defined(USE_SPI_DMA)
+ #include
+ #include "wiring_private.h" // pinPeripheral() function
+ #include // memalign() function
+ #define tcNum 2 // Timer/Counter for parallel write strobe PWM
+ #define wrPeripheral PIO_CCL // Use CCL to invert write strobe
+
+ // DMA transfer-in-progress indicator and callback
+ static volatile bool dma_busy = false;
+ static void dma_callback(Adafruit_ZeroDMA *dma) {
+ dma_busy = false;
+ }
+
+ #if defined(__SAMD51__)
+ // Timer/counter info by index #
+ static const struct {
+ Tc *tc; // -> Timer/Counter base address
+ int gclk; // GCLK ID
+ int evu; // EVSYS user ID
+ } tcList[] = {
+ { TC0, TC0_GCLK_ID, EVSYS_ID_USER_TC0_EVU },
+ { TC1, TC1_GCLK_ID, EVSYS_ID_USER_TC1_EVU },
+ { TC2, TC2_GCLK_ID, EVSYS_ID_USER_TC2_EVU },
+ { TC3, TC3_GCLK_ID, EVSYS_ID_USER_TC3_EVU },
+ #if defined(TC4)
+ { TC4, TC4_GCLK_ID, EVSYS_ID_USER_TC4_EVU },
+ #endif
+ #if defined(TC5)
+ { TC5, TC5_GCLK_ID, EVSYS_ID_USER_TC5_EVU },
+ #endif
+ #if defined(TC6)
+ { TC6, TC6_GCLK_ID, EVSYS_ID_USER_TC6_EVU },
+ #endif
+ #if defined(TC7)
+ { TC7, TC7_GCLK_ID, EVSYS_ID_USER_TC7_EVU }
+ #endif
+ };
+ #define NUM_TIMERS (sizeof tcList / sizeof tcList[0]) ///< # timer/counters
+ #endif // end __SAMD51__
+
+#endif // end USE_SPI_DMA
+
+// Possible values for Adafruit_SPITFT.connection:
+#define TFT_HARD_SPI 0 ///< Display interface = hardware SPI
+#define TFT_SOFT_SPI 1 ///< Display interface = software SPI
+#define TFT_PARALLEL 2 ///< Display interface = 8- or 16-bit parallel
+
+
+// CONSTRUCTORS ------------------------------------------------------------
+
+/*!
+ @brief Adafruit_SPITFT constructor for software (bitbang) SPI.
+ @param w Display width in pixels at default rotation setting (0).
+ @param h Display height in pixels at default rotation setting (0).
+ @param cs Arduino pin # for chip-select (-1 if unused, tie CS low).
+ @param dc Arduino pin # for data/command select (required).
+ @param mosi Arduino pin # for bitbang SPI MOSI signal (required).
+ @param sck Arduino pin # for bitbang SPI SCK signal (required).
+ @param rst Arduino pin # for display reset (optional, display reset
+ can be tied to MCU reset, default of -1 means unused).
+ @param miso Arduino pin # for bitbang SPI MISO signal (optional,
+ -1 default, many displays don't support SPI read).
+ @return Adafruit_SPITFT object.
+ @note Output pins are not initialized; application typically will
+ need to call subclass' begin() function, which in turn calls
+ this library's initSPI() function to initialize pins.
+*/
+Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
+ int8_t cs, int8_t dc, int8_t mosi, int8_t sck, int8_t rst, int8_t miso) :
+ Adafruit_GFX(w, h), connection(TFT_SOFT_SPI), _rst(rst), _cs(cs), _dc(dc) {
+ swspi._sck = sck;
+ swspi._mosi = mosi;
+ swspi._miso = miso;
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(CORE_TEENSY)
+ #if !defined(KINETISK)
+ dcPinMask = digitalPinToBitMask(dc);
+ swspi.sckPinMask = digitalPinToBitMask(sck);
+ swspi.mosiPinMask = digitalPinToBitMask(mosi);
+ #endif
+ dcPortSet = portSetRegister(dc);
+ dcPortClr = portClearRegister(dc);
+ swspi.sckPortSet = portSetRegister(sck);
+ swspi.sckPortClr = portClearRegister(sck);
+ swspi.mosiPortSet = portSetRegister(mosi);
+ swspi.mosiPortClr = portClearRegister(mosi);
+ if(cs >= 0) {
+ #if !defined(KINETISK)
+ csPinMask = digitalPinToBitMask(cs);
+ #endif
+ csPortSet = portSetRegister(cs);
+ csPortClr = portClearRegister(cs);
+ } else {
+ #if !defined(KINETISK)
+ csPinMask = 0;
+ #endif
+ csPortSet = dcPortSet;
+ csPortClr = dcPortClr;
+ }
+ if(miso >= 0) {
+ swspi.misoPort = portInputRegister(miso);
+ #if !defined(KINETISK)
+ swspi.misoPinMask = digitalPinToBitMask(miso);
+ #endif
+ } else {
+ swspi.misoPort = portInputRegister(dc);
+ }
+ #else // !CORE_TEENSY
+ dcPinMask =digitalPinToBitMask(dc);
+ swspi.sckPinMask =digitalPinToBitMask(sck);
+ swspi.mosiPinMask=digitalPinToBitMask(mosi);
+ dcPortSet =&(PORT->Group[g_APinDescription[dc].ulPort].OUTSET.reg);
+ dcPortClr =&(PORT->Group[g_APinDescription[dc].ulPort].OUTCLR.reg);
+ swspi.sckPortSet =&(PORT->Group[g_APinDescription[sck].ulPort].OUTSET.reg);
+ swspi.sckPortClr =&(PORT->Group[g_APinDescription[sck].ulPort].OUTCLR.reg);
+ swspi.mosiPortSet=&(PORT->Group[g_APinDescription[mosi].ulPort].OUTSET.reg);
+ swspi.mosiPortClr=&(PORT->Group[g_APinDescription[mosi].ulPort].OUTCLR.reg);
+ if(cs >= 0) {
+ csPinMask = digitalPinToBitMask(cs);
+ csPortSet = &(PORT->Group[g_APinDescription[cs].ulPort].OUTSET.reg);
+ csPortClr = &(PORT->Group[g_APinDescription[cs].ulPort].OUTCLR.reg);
+ } else {
+ // No chip-select line defined; might be permanently tied to GND.
+ // Assign a valid GPIO register (though not used for CS), and an
+ // empty pin bitmask...the nonsense bit-twiddling might be faster
+ // than checking _cs and possibly branching.
+ csPortSet = dcPortSet;
+ csPortClr = dcPortClr;
+ csPinMask = 0;
+ }
+ if(miso >= 0) {
+ swspi.misoPinMask=digitalPinToBitMask(miso);
+ swspi.misoPort =(PORTreg_t)portInputRegister(digitalPinToPort(miso));
+ } else {
+ swspi.misoPinMask=0;
+ swspi.misoPort =(PORTreg_t)portInputRegister(digitalPinToPort(dc));
+ }
+ #endif // end !CORE_TEENSY
+ #else // !HAS_PORT_SET_CLR
+ dcPort =(PORTreg_t)portOutputRegister(digitalPinToPort(dc));
+ dcPinMaskSet =digitalPinToBitMask(dc);
+ swspi.sckPort =(PORTreg_t)portOutputRegister(digitalPinToPort(sck));
+ swspi.sckPinMaskSet =digitalPinToBitMask(sck);
+ swspi.mosiPort =(PORTreg_t)portOutputRegister(digitalPinToPort(mosi));
+ swspi.mosiPinMaskSet=digitalPinToBitMask(mosi);
+ if(cs >= 0) {
+ csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(cs));
+ csPinMaskSet = digitalPinToBitMask(cs);
+ } else {
+ // No chip-select line defined; might be permanently tied to GND.
+ // Assign a valid GPIO register (though not used for CS), and an
+ // empty pin bitmask...the nonsense bit-twiddling might be faster
+ // than checking _cs and possibly branching.
+ csPort = dcPort;
+ csPinMaskSet = 0;
+ }
+ if(miso >= 0) {
+ swspi.misoPort =(PORTreg_t)portInputRegister(digitalPinToPort(miso));
+ swspi.misoPinMask=digitalPinToBitMask(miso);
+ } else {
+ swspi.misoPort =(PORTreg_t)portInputRegister(digitalPinToPort(dc));
+ swspi.misoPinMask=0;
+ }
+ csPinMaskClr = ~csPinMaskSet;
+ dcPinMaskClr = ~dcPinMaskSet;
+ swspi.sckPinMaskClr = ~swspi.sckPinMaskSet;
+ swspi.mosiPinMaskClr = ~swspi.mosiPinMaskSet;
+ #endif // !end HAS_PORT_SET_CLR
+#endif // end USE_FAST_PINIO
+}
+
+/*!
+ @brief Adafruit_SPITFT constructor for hardware SPI using the board's
+ default SPI peripheral.
+ @param w Display width in pixels at default rotation setting (0).
+ @param h Display height in pixels at default rotation setting (0).
+ @param cs Arduino pin # for chip-select (-1 if unused, tie CS low).
+ @param dc Arduino pin # for data/command select (required).
+ @param rst Arduino pin # for display reset (optional, display reset
+ can be tied to MCU reset, default of -1 means unused).
+ @return Adafruit_SPITFT object.
+ @note Output pins are not initialized; application typically will
+ need to call subclass' begin() function, which in turn calls
+ this library's initSPI() function to initialize pins.
+*/
+#if defined(ESP8266) // See notes below
+Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h, int8_t cs,
+ int8_t dc, int8_t rst) : Adafruit_GFX(w, h),
+ connection(TFT_HARD_SPI), _rst(rst), _cs(cs), _dc(dc) {
+ hwspi._spi = &SPI;
+}
+#else // !ESP8266
+Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h, int8_t cs,
+ int8_t dc, int8_t rst) : Adafruit_SPITFT(w, h, &SPI, cs, dc, rst) {
+ // This just invokes the hardware SPI constructor below,
+ // passing the default SPI device (&SPI).
+}
+#endif // end !ESP8266
+
+#if !defined(ESP8266)
+// ESP8266 compiler freaks out at this constructor -- it can't disambiguate
+// beteween the SPIClass pointer (argument #3) and a regular integer.
+// Solution here it to just not offer this variant on the ESP8266. You can
+// use the default hardware SPI peripheral, or you can use software SPI,
+// but if there's any library out there that creates a 'virtual' SPIClass
+// peripheral and drives it with software bitbanging, that's not supported.
+/*!
+ @brief Adafruit_SPITFT constructor for hardware SPI using a specific
+ SPI peripheral.
+ @param w Display width in pixels at default rotation (0).
+ @param h Display height in pixels at default rotation (0).
+ @param spiClass Pointer to SPIClass type (e.g. &SPI or &SPI1).
+ @param cs Arduino pin # for chip-select (-1 if unused, tie CS low).
+ @param dc Arduino pin # for data/command select (required).
+ @param rst Arduino pin # for display reset (optional, display reset
+ can be tied to MCU reset, default of -1 means unused).
+ @return Adafruit_SPITFT object.
+ @note Output pins are not initialized in constructor; application
+ typically will need to call subclass' begin() function, which
+ in turn calls this library's initSPI() function to initialize
+ pins. EXCEPT...if you have built your own SERCOM SPI peripheral
+ (calling the SPIClass constructor) rather than one of the
+ built-in SPI devices (e.g. &SPI, &SPI1 and so forth), you will
+ need to call the begin() function for your object as well as
+ pinPeripheral() for the MOSI, MISO and SCK pins to configure
+ GPIO manually. Do this BEFORE calling the display-specific
+ begin or init function. Unfortunate but unavoidable.
+*/
+Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h, SPIClass *spiClass,
+ int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(w, h),
+ connection(TFT_HARD_SPI), _rst(rst), _cs(cs), _dc(dc) {
+ hwspi._spi = spiClass;
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(CORE_TEENSY)
+ #if !defined(KINETISK)
+ dcPinMask = digitalPinToBitMask(dc);
+ #endif
+ dcPortSet = portSetRegister(dc);
+ dcPortClr = portClearRegister(dc);
+ if(cs >= 0) {
+ #if !defined(KINETISK)
+ csPinMask = digitalPinToBitMask(cs);
+ #endif
+ csPortSet = portSetRegister(cs);
+ csPortClr = portClearRegister(cs);
+ } else { // see comments below
+ #if !defined(KINETISK)
+ csPinMask = 0;
+ #endif
+ csPortSet = dcPortSet;
+ csPortClr = dcPortClr;
+ }
+ #else // !CORE_TEENSY
+ dcPinMask = digitalPinToBitMask(dc);
+ dcPortSet = &(PORT->Group[g_APinDescription[dc].ulPort].OUTSET.reg);
+ dcPortClr = &(PORT->Group[g_APinDescription[dc].ulPort].OUTCLR.reg);
+ if(cs >= 0) {
+ csPinMask = digitalPinToBitMask(cs);
+ csPortSet = &(PORT->Group[g_APinDescription[cs].ulPort].OUTSET.reg);
+ csPortClr = &(PORT->Group[g_APinDescription[cs].ulPort].OUTCLR.reg);
+ } else {
+ // No chip-select line defined; might be permanently tied to GND.
+ // Assign a valid GPIO register (though not used for CS), and an
+ // empty pin bitmask...the nonsense bit-twiddling might be faster
+ // than checking _cs and possibly branching.
+ csPortSet = dcPortSet;
+ csPortClr = dcPortClr;
+ csPinMask = 0;
+ }
+ #endif // end !CORE_TEENSY
+ #else // !HAS_PORT_SET_CLR
+ dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(dc));
+ dcPinMaskSet = digitalPinToBitMask(dc);
+ if(cs >= 0) {
+ csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(cs));
+ csPinMaskSet = digitalPinToBitMask(cs);
+ } else {
+ // No chip-select line defined; might be permanently tied to GND.
+ // Assign a valid GPIO register (though not used for CS), and an
+ // empty pin bitmask...the nonsense bit-twiddling might be faster
+ // than checking _cs and possibly branching.
+ csPort = dcPort;
+ csPinMaskSet = 0;
+ }
+ csPinMaskClr = ~csPinMaskSet;
+ dcPinMaskClr = ~dcPinMaskSet;
+ #endif // end !HAS_PORT_SET_CLR
+#endif // end USE_FAST_PINIO
+}
+#endif // end !ESP8266
+
+/*!
+ @brief Adafruit_SPITFT constructor for parallel display connection.
+ @param w Display width in pixels at default rotation (0).
+ @param h Display height in pixels at default rotation (0).
+ @param busWidth If tft16 (enumeration in header file), is a 16-bit
+ parallel connection, else 8-bit.
+ 16-bit isn't fully implemented or tested yet so
+ applications should pass "tft8bitbus" for now...needed to
+ stick a required enum argument in there to
+ disambiguate this constructor from the soft-SPI case.
+ Argument is ignored on 8-bit architectures (no 'wide'
+ support there since PORTs are 8 bits anyway).
+ @param d0 Arduino pin # for data bit 0 (1+ are extrapolated).
+ The 8 (or 16) data bits MUST be contiguous and byte-
+ aligned (or word-aligned for wide interface) within
+ the same PORT register (might not correspond to
+ Arduino pin sequence).
+ @param wr Arduino pin # for write strobe (required).
+ @param dc Arduino pin # for data/command select (required).
+ @param cs Arduino pin # for chip-select (optional, -1 if unused,
+ tie CS low).
+ @param rst Arduino pin # for display reset (optional, display reset
+ can be tied to MCU reset, default of -1 means unused).
+ @param rd Arduino pin # for read strobe (optional, -1 if unused).
+ @return Adafruit_SPITFT object.
+ @note Output pins are not initialized; application typically will need
+ to call subclass' begin() function, which in turn calls this
+ library's initSPI() function to initialize pins.
+ Yes, the name is a misnomer...this library originally handled
+ only SPI displays, parallel being a recent addition (but not
+ wanting to break existing code).
+*/
+Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h, tftBusWidth busWidth,
+ int8_t d0, int8_t wr, int8_t dc, int8_t cs, int8_t rst, int8_t rd) :
+ Adafruit_GFX(w, h), connection(TFT_PARALLEL), _rst(rst), _cs(cs), _dc(dc) {
+ tft8._d0 = d0;
+ tft8._wr = wr;
+ tft8._rd = rd;
+ tft8.wide = (busWidth == tft16bitbus);
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(CORE_TEENSY)
+ tft8.wrPortSet = portSetRegister(wr);
+ tft8.wrPortClr = portClearRegister(wr);
+ #if !defined(KINETISK)
+ dcPinMask = digitalPinToBitMask(dc);
+ #endif
+ dcPortSet = portSetRegister(dc);
+ dcPortClr = portClearRegister(dc);
+ if(cs >= 0) {
+ #if !defined(KINETISK)
+ csPinMask = digitalPinToBitMask(cs);
+ #endif
+ csPortSet = portSetRegister(cs);
+ csPortClr = portClearRegister(cs);
+ } else { // see comments below
+ #if !defined(KINETISK)
+ csPinMask = 0;
+ #endif
+ csPortSet = dcPortSet;
+ csPortClr = dcPortClr;
+ }
+ if(rd >= 0) { // if read-strobe pin specified...
+ #if defined(KINETISK)
+ tft8.rdPinMask = 1;
+ #else // !KINETISK
+ tft8.rdPinMask = digitalPinToBitMask(rd);
+ #endif
+ tft8.rdPortSet = portSetRegister(rd);
+ tft8.rdPortClr = portClearRegister(rd);
+ } else {
+ tft8.rdPinMask = 0;
+ tft8.rdPortSet = dcPortSet;
+ tft8.rdPortClr = dcPortClr;
+ }
+ // These are all uint8_t* pointers -- elsewhere they're recast
+ // as necessary if a 'wide' 16-bit interface is in use.
+ tft8.writePort = portOutputRegister(d0);
+ tft8.readPort = portInputRegister(d0);
+ tft8.dirSet = portModeRegister(d0);
+ tft8.dirClr = portModeRegister(d0);
+ #else // !CORE_TEENSY
+ tft8.wrPinMask = digitalPinToBitMask(wr);
+ tft8.wrPortSet = &(PORT->Group[g_APinDescription[wr].ulPort].OUTSET.reg);
+ tft8.wrPortClr = &(PORT->Group[g_APinDescription[wr].ulPort].OUTCLR.reg);
+ dcPinMask = digitalPinToBitMask(dc);
+ dcPortSet = &(PORT->Group[g_APinDescription[dc].ulPort].OUTSET.reg);
+ dcPortClr = &(PORT->Group[g_APinDescription[dc].ulPort].OUTCLR.reg);
+ if(cs >= 0) {
+ csPinMask = digitalPinToBitMask(cs);
+ csPortSet = &(PORT->Group[g_APinDescription[cs].ulPort].OUTSET.reg);
+ csPortClr = &(PORT->Group[g_APinDescription[cs].ulPort].OUTCLR.reg);
+ } else {
+ // No chip-select line defined; might be permanently tied to GND.
+ // Assign a valid GPIO register (though not used for CS), and an
+ // empty pin bitmask...the nonsense bit-twiddling might be faster
+ // than checking _cs and possibly branching.
+ csPortSet = dcPortSet;
+ csPortClr = dcPortClr;
+ csPinMask = 0;
+ }
+ if(rd >= 0) { // if read-strobe pin specified...
+ tft8.rdPinMask =digitalPinToBitMask(rd);
+ tft8.rdPortSet =&(PORT->Group[g_APinDescription[rd].ulPort].OUTSET.reg);
+ tft8.rdPortClr =&(PORT->Group[g_APinDescription[rd].ulPort].OUTCLR.reg);
+ } else {
+ tft8.rdPinMask = 0;
+ tft8.rdPortSet = dcPortSet;
+ tft8.rdPortClr = dcPortClr;
+ }
+ // Get pointers to PORT write/read/dir bytes within 32-bit PORT
+ uint8_t dBit = g_APinDescription[d0].ulPin; // d0 bit # in PORT
+ PortGroup *p = (&(PORT->Group[g_APinDescription[d0].ulPort]));
+ uint8_t offset = dBit / 8; // d[7:0] byte # within PORT
+ if(tft8.wide) offset &= ~1; // d[15:8] byte # within PORT
+ // These are all uint8_t* pointers -- elsewhere they're recast
+ // as necessary if a 'wide' 16-bit interface is in use.
+ tft8.writePort = (volatile uint8_t *)&(p->OUT.reg) + offset;
+ tft8.readPort = (volatile uint8_t *)&(p->IN.reg) + offset;
+ tft8.dirSet = (volatile uint8_t *)&(p->DIRSET.reg) + offset;
+ tft8.dirClr = (volatile uint8_t *)&(p->DIRCLR.reg) + offset;
+ #endif // end !CORE_TEENSY
+ #else // !HAS_PORT_SET_CLR
+ tft8.wrPort = (PORTreg_t)portOutputRegister(digitalPinToPort(wr));
+ tft8.wrPinMaskSet = digitalPinToBitMask(wr);
+ dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(dc));
+ dcPinMaskSet = digitalPinToBitMask(dc);
+ if(cs >= 0) {
+ csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(cs));
+ csPinMaskSet = digitalPinToBitMask(cs);
+ } else {
+ // No chip-select line defined; might be permanently tied to GND.
+ // Assign a valid GPIO register (though not used for CS), and an
+ // empty pin bitmask...the nonsense bit-twiddling might be faster
+ // than checking _cs and possibly branching.
+ csPort = dcPort;
+ csPinMaskSet = 0;
+ }
+ if(rd >= 0) { // if read-strobe pin specified...
+ tft8.rdPort =(PORTreg_t)portOutputRegister(digitalPinToPort(rd));
+ tft8.rdPinMaskSet =digitalPinToBitMask(rd);
+ } else {
+ tft8.rdPort = dcPort;
+ tft8.rdPinMaskSet = 0;
+ }
+ csPinMaskClr = ~csPinMaskSet;
+ dcPinMaskClr = ~dcPinMaskSet;
+ tft8.wrPinMaskClr = ~tft8.wrPinMaskSet;
+ tft8.rdPinMaskClr = ~tft8.rdPinMaskSet;
+ tft8.writePort = (PORTreg_t)portOutputRegister(digitalPinToPort(d0));
+ tft8.readPort = (PORTreg_t)portInputRegister(digitalPinToPort(d0));
+ tft8.portDir = (PORTreg_t)portModeRegister(digitalPinToPort(d0));
+ #endif // end !HAS_PORT_SET_CLR
+#endif // end USE_FAST_PINIO
+}
+
+// end constructors -------
+
+
+// CLASS MEMBER FUNCTIONS --------------------------------------------------
+
+// begin() and setAddrWindow() MUST be declared by any subclass.
+
+/*!
+ @brief Configure microcontroller pins for TFT interfacing. Typically
+ called by a subclass' begin() function.
+ @param freq SPI frequency when using hardware SPI. If default (0)
+ is passed, will fall back on a device-specific value.
+ Value is ignored when using software SPI or parallel
+ connection.
+ @param spiMode SPI mode when using hardware SPI. MUST be one of the
+ values SPI_MODE0, SPI_MODE1, SPI_MODE2 or SPI_MODE3
+ defined in SPI.h. Do NOT attempt to pass '0' for
+ SPI_MODE0 and so forth...the values are NOT the same!
+ Use ONLY the defines! (Pity it's not an enum.)
+ @note Another anachronistically-named function; this is called even
+ when the display connection is parallel (not SPI). Also, this
+ could probably be made private...quite a few class functions
+ were generously put in the public section.
+*/
+void Adafruit_SPITFT::initSPI(uint32_t freq, uint8_t spiMode) {
+
+ if(!freq) freq = DEFAULT_SPI_FREQ; // If no freq specified, use default
+
+ // Init basic control pins common to all connection types
+ if(_cs >= 0) {
+ pinMode(_cs, OUTPUT);
+ digitalWrite(_cs, HIGH); // Deselect
+ }
+ pinMode(_dc, OUTPUT);
+ digitalWrite(_dc, HIGH); // Data mode
+
+ if(connection == TFT_HARD_SPI) {
+
+#if defined(SPI_HAS_TRANSACTION)
+ hwspi.settings = SPISettings(freq, MSBFIRST, spiMode);
+#else
+ hwspi._freq = freq; // Save freq value for later
+#endif
+ hwspi._mode = spiMode; // Save spiMode value for later
+ // Call hwspi._spi->begin() ONLY if this is among the 'established'
+ // SPI interfaces in variant.h. For DIY roll-your-own SERCOM SPIs,
+ // begin() and pinPeripheral() calls MUST be made in one's calling
+ // code, BEFORE the screen-specific begin/init function is called.
+ // Reason for this is that SPI::begin() makes its own calls to
+ // pinPeripheral() based on g_APinDescription[n].ulPinType, which
+ // on non-established SPI interface pins will always be PIO_DIGITAL
+ // or similar, while we need PIO_SERCOM or PIO_SERCOM_ALT...it's
+ // highly unique between devices and variants for each pin or
+ // SERCOM so we can't make those calls ourselves here. And the SPI
+ // device needs to be set up before calling this because it's
+ // immediately followed with initialization commands. Blargh.
+ if(
+#if !defined(SPI_INTERFACES_COUNT)
+ 1
+#endif
+#if SPI_INTERFACES_COUNT > 0
+ (hwspi._spi == &SPI)
+#endif
+#if SPI_INTERFACES_COUNT > 1
+ || (hwspi._spi == &SPI1)
+#endif
+#if SPI_INTERFACES_COUNT > 2
+ || (hwspi._spi == &SPI2)
+#endif
+#if SPI_INTERFACES_COUNT > 3
+ || (hwspi._spi == &SPI3)
+#endif
+#if SPI_INTERFACES_COUNT > 4
+ || (hwspi._spi == &SPI4)
+#endif
+#if SPI_INTERFACES_COUNT > 5
+ || (hwspi._spi == &SPI5)
+#endif
+ ) {
+ hwspi._spi->begin();
+ }
+ } else if(connection == TFT_SOFT_SPI) {
+
+ pinMode(swspi._mosi, OUTPUT);
+ digitalWrite(swspi._mosi, LOW);
+ pinMode(swspi._sck, OUTPUT);
+ digitalWrite(swspi._sck, LOW);
+ if(swspi._miso >= 0) {
+ pinMode(swspi._miso, INPUT);
+ }
+
+ } else { // TFT_PARALLEL
+
+ // Initialize data pins. We were only passed d0, so scan
+ // the pin description list looking for the other pins.
+ // They'll be on the same PORT, and within the next 7 (or 15) bits
+ // (because we need to write to a contiguous PORT byte or word).
+#if defined(__AVR__)
+ // PORT registers are 8 bits wide, so just need a register match...
+ for(uint8_t i=0; i= dBit ) &&
+ (g_APinDescription[i].ulPin <= (uint32_t)lastBit)) {
+ pinMode(i, OUTPUT);
+ digitalWrite(i, LOW);
+ }
+ }
+ #endif // end !CORE_TEENSY
+#endif
+ pinMode(tft8._wr, OUTPUT);
+ digitalWrite(tft8._wr, HIGH);
+ if(tft8._rd >= 0) {
+ pinMode(tft8._rd, OUTPUT);
+ digitalWrite(tft8._rd, HIGH);
+ }
+ }
+
+ if(_rst >= 0) {
+ // Toggle _rst low to reset
+ pinMode(_rst, OUTPUT);
+ digitalWrite(_rst, HIGH);
+ delay(100);
+ digitalWrite(_rst, LOW);
+ delay(100);
+ digitalWrite(_rst, HIGH);
+ delay(200);
+ }
+
+#if defined(USE_SPI_DMA)
+ if(((connection == TFT_HARD_SPI) || (connection == TFT_PARALLEL)) &&
+ (dma.allocate() == DMA_STATUS_OK)) { // Allocate channel
+ // The DMA library needs to alloc at least one valid descriptor,
+ // so we do that here. It's not used in the usual sense though,
+ // just before a transfer we copy descriptor[0] to this address.
+ if(dptr = dma.addDescriptor(NULL, NULL, 42, DMA_BEAT_SIZE_BYTE,
+ false, false)) {
+ // Alloc 2 scanlines worth of pixels on display's major axis,
+ // whichever that is, rounding each up to 2-pixel boundary.
+ int major = (WIDTH > HEIGHT) ? WIDTH : HEIGHT;
+ major += (major & 1); // -> next 2-pixel bound, if needed.
+ maxFillLen = major * 2; // 2 scanlines
+ // Note to future self: if you decide to make the pixel buffer
+ // much larger, remember that DMA transfer descriptors can't
+ // exceed 65,535 bytes (not 65,536), meaning 32,767 pixels max.
+ // Not that we have that kind of RAM to throw around right now.
+ if((pixelBuf[0] =
+ (uint16_t *)malloc(maxFillLen * sizeof(uint16_t)))) {
+ // Alloc OK. Get pointer to start of second scanline.
+ pixelBuf[1] = &pixelBuf[0][major];
+ // Determine number of DMA descriptors needed to cover
+ // entire screen when entire 2-line pixelBuf is used
+ // (round up for fractional last descriptor).
+ int numDescriptors = (WIDTH * HEIGHT + (maxFillLen - 1)) /
+ maxFillLen;
+ // DMA descriptors MUST be 128-bit (16 byte) aligned.
+ // memalign() is considered obsolete but it's replacements
+ // (aligned_alloc() or posix_memalign()) are not currently
+ // available in the version of ARM GCC in use, but this
+ // is, so here we are.
+ if((descriptor = (DmacDescriptor *)memalign(16,
+ numDescriptors * sizeof(DmacDescriptor)))) {
+ int dmac_id;
+ volatile uint32_t *data_reg;
+
+ if(connection == TFT_HARD_SPI) {
+ // THIS IS AN AFFRONT TO NATURE, but I don't know
+ // any "clean" way to get the sercom number from the
+ // the SPIClass pointer (e.g. &SPI or &SPI1), which
+ // is all we have to work with. SPIClass does contain
+ // a SERCOM pointer but it is a PRIVATE member!
+ // Doing an UNSPEAKABLY HORRIBLE THING here, directly
+ // accessing the first 32-bit value in the SPIClass
+ // structure, knowing that's (currently) where the
+ // SERCOM pointer lives, but this ENTIRELY DEPENDS on
+ // that structure not changing nor the compiler
+ // rearranging things. Oh the humanity!
+
+ if(*(SERCOM **)hwspi._spi == &sercom0) {
+ dmac_id = SERCOM0_DMAC_ID_TX;
+ data_reg = &SERCOM0->SPI.DATA.reg;
+#if defined SERCOM1
+ } else if(*(SERCOM **)hwspi._spi == &sercom1) {
+ dmac_id = SERCOM1_DMAC_ID_TX;
+ data_reg = &SERCOM1->SPI.DATA.reg;
+#endif
+#if defined SERCOM2
+ } else if(*(SERCOM **)hwspi._spi == &sercom2) {
+ dmac_id = SERCOM2_DMAC_ID_TX;
+ data_reg = &SERCOM2->SPI.DATA.reg;
+#endif
+#if defined SERCOM3
+ } else if(*(SERCOM **)hwspi._spi == &sercom3) {
+ dmac_id = SERCOM3_DMAC_ID_TX;
+ data_reg = &SERCOM3->SPI.DATA.reg;
+#endif
+#if defined SERCOM4
+ } else if(*(SERCOM **)hwspi._spi == &sercom4) {
+ dmac_id = SERCOM4_DMAC_ID_TX;
+ data_reg = &SERCOM4->SPI.DATA.reg;
+#endif
+#if defined SERCOM5
+ } else if(*(SERCOM **)hwspi._spi == &sercom5) {
+ dmac_id = SERCOM5_DMAC_ID_TX;
+ data_reg = &SERCOM5->SPI.DATA.reg;
+#endif
+#if defined SERCOM6
+ } else if(*(SERCOM **)hwspi._spi == &sercom6) {
+ dmac_id = SERCOM6_DMAC_ID_TX;
+ data_reg = &SERCOM6->SPI.DATA.reg;
+#endif
+#if defined SERCOM7
+ } else if(*(SERCOM **)hwspi._spi == &sercom7) {
+ dmac_id = SERCOM7_DMAC_ID_TX;
+ data_reg = &SERCOM7->SPI.DATA.reg;
+#endif
+ }
+ dma.setPriority(DMA_PRIORITY_3);
+ dma.setTrigger(dmac_id);
+ dma.setAction(DMA_TRIGGER_ACTON_BEAT);
+
+ // Initialize descriptor list.
+ for(int d=0; dChannel[dmaChannel].CHEVCTRL.bit.EVOE = 1;
+ DMAC->Channel[dmaChannel].CHEVCTRL.bit.EVOMODE = 0;
+
+ // CONFIGURE TIMER/COUNTER (for write strobe)
+
+ Tc *timer = tcList[tcNum].tc; // -> Timer struct
+ int id = tcList[tcNum].gclk; // Timer GCLK ID
+ GCLK_PCHCTRL_Type pchctrl;
+
+ // Set up timer clock source from GCLK
+ GCLK->PCHCTRL[id].bit.CHEN = 0; // Stop timer
+ while(GCLK->PCHCTRL[id].bit.CHEN); // Wait for it
+ pchctrl.bit.GEN = GCLK_PCHCTRL_GEN_GCLK0_Val;
+ pchctrl.bit.CHEN = 1; // Enable
+ GCLK->PCHCTRL[id].reg = pchctrl.reg;
+ while(!GCLK->PCHCTRL[id].bit.CHEN); // Wait for it
+
+ // Disable timer/counter before configuring it
+ timer->COUNT8.CTRLA.bit.ENABLE = 0;
+ while(timer->COUNT8.SYNCBUSY.bit.STATUS);
+
+ timer->COUNT8.WAVE.bit.WAVEGEN = 2; // NPWM
+ timer->COUNT8.CTRLA.bit.MODE = 1; // 8-bit
+ timer->COUNT8.CTRLA.bit.PRESCALER = 0; // 1:1
+ while(timer->COUNT8.SYNCBUSY.bit.STATUS);
+
+ timer->COUNT8.CTRLBCLR.bit.DIR = 1; // Count UP
+ while(timer->COUNT8.SYNCBUSY.bit.CTRLB);
+ timer->COUNT8.CTRLBSET.bit.ONESHOT = 1; // One-shot
+ while(timer->COUNT8.SYNCBUSY.bit.CTRLB);
+ timer->COUNT8.PER.reg = 6; // PWM top
+ while(timer->COUNT8.SYNCBUSY.bit.PER);
+ timer->COUNT8.CC[0].reg = 2; // Compare
+ while(timer->COUNT8.SYNCBUSY.bit.CC0);
+ // Enable async input events,
+ // event action = restart.
+ timer->COUNT8.EVCTRL.bit.TCEI = 1;
+ timer->COUNT8.EVCTRL.bit.EVACT = 1;
+
+ // Enable timer
+ timer->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
+ while(timer->COUNT8.SYNCBUSY.bit.STATUS);
+
+#if(wrPeripheral == PIO_CCL)
+ // CONFIGURE CCL (inverts timer/counter output)
+
+ MCLK->APBCMASK.bit.CCL_ = 1; // Enable CCL clock
+ CCL->CTRL.bit.ENABLE = 0; // Disable to config
+ CCL->CTRL.bit.SWRST = 1; // Reset CCL registers
+ CCL->LUTCTRL[tcNum].bit.ENABLE = 0; // Disable LUT
+ CCL->LUTCTRL[tcNum].bit.FILTSEL = 0; // No filter
+ CCL->LUTCTRL[tcNum].bit.INSEL0 = 6; // TC input
+ CCL->LUTCTRL[tcNum].bit.INSEL1 = 0; // MASK
+ CCL->LUTCTRL[tcNum].bit.INSEL2 = 0; // MASK
+ CCL->LUTCTRL[tcNum].bit.TRUTH = 1; // Invert in 0
+ CCL->LUTCTRL[tcNum].bit.ENABLE = 1; // Enable LUT
+ CCL->CTRL.bit.ENABLE = 1; // Enable CCL
+#endif
+
+ // CONFIGURE EVENT SYSTEM
+
+ // Set up event system clock source from GCLK...
+ // Disable EVSYS, wait for disable
+ GCLK->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN = 0;
+ while(GCLK->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN);
+ pchctrl.bit.GEN = GCLK_PCHCTRL_GEN_GCLK0_Val;
+ pchctrl.bit.CHEN = 1; // Re-enable
+ GCLK->PCHCTRL[EVSYS_GCLK_ID_0].reg = pchctrl.reg;
+ // Wait for it, then enable EVSYS clock
+ while(!GCLK->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN);
+ MCLK->APBBMASK.bit.EVSYS_ = 1;
+
+ // Connect Timer EVU to ch 0
+ EVSYS->USER[tcList[tcNum].evu].reg = 1;
+ // Datasheet recommends single write operation;
+ // reg instead of bit. Also datasheet: PATH bits
+ // must be zero when using async!
+ EVSYS_CHANNEL_Type ev;
+ ev.reg = 0;
+ ev.bit.PATH = 2; // Asynchronous
+ ev.bit.EVGEN = 0x22 + dmaChannel; // DMA channel 0+
+ EVSYS->Channel[0].CHANNEL.reg = ev.reg;
+
+ // Initialize descriptor list.
+ for(int d=0; d= 0) SPI_CS_LOW();
+}
+
+/*!
+ @brief Call after issuing command(s) or data to display. Performs
+ chip-deselect (if required) and ends an SPI transaction (if
+ using hardware SPI and transactions are supported). Required
+ for all display types; not an SPI-specific function.
+*/
+void Adafruit_SPITFT::endWrite(void) {
+ if(_cs >= 0) SPI_CS_HIGH();
+ SPI_END_TRANSACTION();
+}
+
+
+// -------------------------------------------------------------------------
+// Lower-level graphics operations. These functions require a chip-select
+// and/or SPI transaction around them (via startWrite(), endWrite() above).
+// Higher-level graphics primitives might start a single transaction and
+// then make multiple calls to these functions (e.g. circle or text
+// rendering might make repeated lines or rects) before ending the
+// transaction. It's more efficient than starting a transaction every time.
+
+/*!
+ @brief Draw a single pixel to the display at requested coordinates.
+ Not self-contained; should follow a startWrite() call.
+ @param x Horizontal position (0 = left).
+ @param y Vertical position (0 = top).
+ @param color 16-bit pixel color in '565' RGB format.
+*/
+void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
+ if((x >= 0) && (x < _width) && (y >= 0) && (y < _height)) {
+ setAddrWindow(x, y, 1, 1);
+ SPI_WRITE16(color);
+ }
+}
+
+/*!
+ @brief Issue a series of pixels from memory to the display. Not self-
+ contained; should follow startWrite() and setAddrWindow() calls.
+ @param colors Pointer to array of 16-bit pixel values in '565' RGB
+ format.
+ @param len Number of elements in 'colors' array.
+ @param block If true (default case if unspecified), function blocks
+ until DMA transfer is complete. This is simply IGNORED
+ if DMA is not enabled. If false, the function returns
+ immediately after the last DMA transfer is started,
+ and one should use the dmaWait() function before
+ doing ANY other display-related activities (or even
+ any SPI-related activities, if using an SPI display
+ that shares the bus with other devices).
+ @param bigEndian If using DMA, and if set true, bitmap in memory is in
+ big-endian order (most significant byte first). By
+ default this is false, as most microcontrollers seem
+ to be little-endian and 16-bit pixel values must be
+ byte-swapped before issuing to the display (which tend
+ to be big-endian when using SPI or 8-bit parallel).
+ If an application can optimize around this -- for
+ example, a bitmap in a uint16_t array having the byte
+ values already reordered big-endian, this can save
+ some processing time here, ESPECIALLY if using this
+ function's non-blocking DMA mode. Not all cases are
+ covered...this is really here only for SAMD DMA and
+ much forethought on the application side.
+*/
+void Adafruit_SPITFT::writePixels(uint16_t *colors, uint32_t len,
+ bool block, bool bigEndian) {
+
+ if(!len) return; // Avoid 0-byte transfers
+
+#if defined(ESP32) // ESP32 has a special SPI pixel-writing function...
+ if(connection == TFT_HARD_SPI) {
+ hwspi._spi->writePixels(colors, len * 2);
+ return;
+ }
+#elif defined(USE_SPI_DMA)
+ if((connection == TFT_HARD_SPI) || (connection == TFT_PARALLEL)) {
+ int maxSpan = maxFillLen / 2; // One scanline max
+ uint8_t pixelBufIdx = 0; // Active pixel buffer number
+ #if defined(__SAMD51__)
+ if(connection == TFT_PARALLEL) {
+ // Switch WR pin to PWM or CCL
+ pinPeripheral(tft8._wr, wrPeripheral);
+ }
+ #endif // end __SAMD51__
+ if(!bigEndian) { // Normal little-endian situation...
+ while(len) {
+ int count = (len < maxSpan) ? len : maxSpan;
+
+ // Because TFT and SAMD endianisms are different, must swap
+ // bytes from the 'colors' array passed into a DMA working
+ // buffer. This can take place while the prior DMA transfer
+ // is in progress, hence the need for two pixelBufs.
+ for(int i=0; isetDataMode(hwspi._mode);
+ } else {
+ pinPeripheral(tft8._wr, PIO_OUTPUT); // Switch WR back to GPIO
+ }
+ #endif // end __SAMD51__ || _SAMD21_
+ }
+ return;
+ }
+#endif // end USE_SPI_DMA
+
+ // All other cases (bitbang SPI or non-DMA hard SPI or parallel),
+ // use a loop with the normal 16-bit data write function:
+ while(len--) {
+ SPI_WRITE16(*colors++);
+ }
+}
+
+/*!
+ @brief Wait for the last DMA transfer in a prior non-blocking
+ writePixels() call to complete. This does nothing if DMA
+ is not enabled, and is not needed if blocking writePixels()
+ was used (as is the default case).
+*/
+void Adafruit_SPITFT::dmaWait(void) {
+#if defined(USE_SPI_DMA)
+ while(dma_busy);
+ #if defined(__SAMD51__) || defined(_SAMD21_)
+ if(connection == TFT_HARD_SPI) {
+ // See SAMD51/21 note in writeColor()
+ hwspi._spi->setDataMode(hwspi._mode);
+ } else {
+ pinPeripheral(tft8._wr, PIO_OUTPUT); // Switch WR back to GPIO
+ }
+ #endif // end __SAMD51__ || _SAMD21_
+#endif
+}
+
+/*!
+ @brief Issue a series of pixels, all the same color. Not self-
+ contained; should follow startWrite() and setAddrWindow() calls.
+ @param color 16-bit pixel color in '565' RGB format.
+ @param len Number of pixels to draw.
+*/
+void Adafruit_SPITFT::writeColor(uint16_t color, uint32_t len) {
+
+ if(!len) return; // Avoid 0-byte transfers
+
+ uint8_t hi = color >> 8, lo = color;
+
+#if defined(ESP32) // ESP32 has a special SPI pixel-writing function...
+ if(connection == TFT_HARD_SPI) {
+ #define SPI_MAX_PIXELS_AT_ONCE 32
+ #define TMPBUF_LONGWORDS (SPI_MAX_PIXELS_AT_ONCE + 1) / 2
+ #define TMPBUF_PIXELS (TMPBUF_LONGWORDS * 2)
+ static uint32_t temp[TMPBUF_LONGWORDS];
+ uint32_t c32 = color * 0x00010001;
+ uint16_t bufLen = (len < TMPBUF_PIXELS) ? len : TMPBUF_PIXELS,
+ xferLen, fillLen;
+ // Fill temp buffer 32 bits at a time
+ fillLen = (bufLen + 1) / 2; // Round up to next 32-bit boundary
+ for(uint32_t t=0; t= 16)) { // Don't bother with DMA on short pixel runs
+ int i, d, numDescriptors;
+ if(hi == lo) { // If high & low bytes are same...
+ onePixelBuf = color;
+ // Can do this with a relatively short descriptor list,
+ // each transferring a max of 32,767 (not 32,768) pixels.
+ // This won't run off the end of the allocated descriptor list,
+ // since we're using much larger chunks per descriptor here.
+ numDescriptors = (len + 32766) / 32767;
+ for(d=0; d lastFillLen) {
+ int fillStart = lastFillLen / 2,
+ fillEnd = (((len < maxFillLen) ?
+ len : maxFillLen) + 1) / 2;
+ for(i=fillStart; isetDataMode(hwspi._mode);
+ } else {
+ pinPeripheral(tft8._wr, PIO_OUTPUT); // Switch WR back to GPIO
+ }
+ #endif // end __SAMD51__
+ return;
+ }
+ #endif // end USE_SPI_DMA
+#endif // end !ESP32
+
+ // All other cases (non-DMA hard SPI, bitbang SPI, parallel)...
+
+ if(connection == TFT_HARD_SPI) {
+#if defined(ESP8266)
+ do {
+ uint32_t pixelsThisPass = len;
+ if(pixelsThisPass > 50000) pixelsThisPass = 50000;
+ len -= pixelsThisPass;
+ yield(); // Periodic yield() on long fills
+ while(pixelsThisPass--) {
+ hwspi._spi->write(hi);
+ hwspi._spi->write(lo);
+ }
+ } while(len);
+#else // !ESP8266
+ while(len--) {
+ #if defined(__AVR__)
+ AVR_WRITESPI(hi);
+ AVR_WRITESPI(lo);
+ #elif defined(ESP32)
+ hwspi._spi->write(hi);
+ hwspi._spi->write(lo);
+ #else
+ hwspi._spi->transfer(hi);
+ hwspi._spi->transfer(lo);
+ #endif
+ }
+#endif // end !ESP8266
+ } else if(connection == TFT_SOFT_SPI) {
+#if defined(ESP8266)
+ do {
+ uint32_t pixelsThisPass = len;
+ if(pixelsThisPass > 20000) pixelsThisPass = 20000;
+ len -= pixelsThisPass;
+ yield(); // Periodic yield() on long fills
+ while(pixelsThisPass--) {
+ for(uint16_t bit=0, x=color; bit<16; bit++) {
+ if(x & 0x8000) SPI_MOSI_HIGH();
+ else SPI_MOSI_LOW();
+ SPI_SCK_HIGH();
+ SPI_SCK_LOW();
+ x <<= 1;
+ }
+ }
+ } while(len);
+#else // !ESP8266
+ while(len--) {
+ #if defined(__AVR__)
+ for(uint8_t bit=0, x=hi; bit<8; bit++) {
+ if(x & 0x80) SPI_MOSI_HIGH();
+ else SPI_MOSI_LOW();
+ SPI_SCK_HIGH();
+ SPI_SCK_LOW();
+ x <<= 1;
+ }
+ for(uint8_t bit=0, x=lo; bit<8; bit++) {
+ if(x & 0x80) SPI_MOSI_HIGH();
+ else SPI_MOSI_LOW();
+ SPI_SCK_HIGH();
+ SPI_SCK_LOW();
+ x <<= 1;
+ }
+ #else // !__AVR__
+ for(uint16_t bit=0, x=color; bit<16; bit++) {
+ if(x & 0x8000) SPI_MOSI_HIGH();
+ else SPI_MOSI_LOW();
+ SPI_SCK_HIGH();
+ x <<= 1;
+ SPI_SCK_LOW();
+ }
+ #endif // end !__AVR__
+ }
+#endif // end !ESP8266
+ } else { // PARALLEL
+ if(hi == lo) {
+#if defined(__AVR__)
+ len *= 2;
+ *tft8.writePort = hi;
+ while(len--) {
+ TFT_WR_STROBE();
+ }
+#elif defined(USE_FAST_PINIO)
+ if(!tft8.wide) {
+ len *= 2;
+ *tft8.writePort = hi;
+ } else {
+ *(volatile uint16_t *)tft8.writePort = color;
+ }
+ while(len--) {
+ TFT_WR_STROBE();
+ }
+#endif
+ } else {
+ while(len--) {
+#if defined(__AVR__)
+ *tft8.writePort = hi;
+ TFT_WR_STROBE();
+ *tft8.writePort = lo;
+#elif defined(USE_FAST_PINIO)
+ if(!tft8.wide) {
+ *tft8.writePort = hi;
+ TFT_WR_STROBE();
+ *tft8.writePort = lo;
+ } else {
+ *(volatile uint16_t *)tft8.writePort = color;
+ }
+#endif
+ TFT_WR_STROBE();
+ }
+ }
+ }
+}
+
+/*!
+ @brief Draw a filled rectangle to the display. Not self-contained;
+ should follow startWrite(). Typically used by higher-level
+ graphics primitives; user code shouldn't need to call this and
+ is likely to use the self-contained fillRect() instead.
+ writeFillRect() performs its own edge clipping and rejection;
+ see writeFillRectPreclipped() for a more 'raw' implementation.
+ @param x Horizontal position of first corner.
+ @param y Vertical position of first corner.
+ @param w Rectangle width in pixels (positive = right of first
+ corner, negative = left of first corner).
+ @param h Rectangle height in pixels (positive = below first
+ corner, negative = above first corner).
+ @param color 16-bit fill color in '565' RGB format.
+ @note Written in this deep-nested way because C by definition will
+ optimize for the 'if' case, not the 'else' -- avoids branches
+ and rejects clipped rectangles at the least-work possibility.
+*/
+void Adafruit_SPITFT::writeFillRect(int16_t x, int16_t y,
+ int16_t w, int16_t h, uint16_t color) {
+ if(w && h) { // Nonzero width and height?
+ if(w < 0) { // If negative width...
+ x += w + 1; // Move X to left edge
+ w = -w; // Use positive width
+ }
+ if(x < _width) { // Not off right
+ if(h < 0) { // If negative height...
+ y += h + 1; // Move Y to top edge
+ h = -h; // Use positive height
+ }
+ if(y < _height) { // Not off bottom
+ int16_t x2 = x + w - 1;
+ if(x2 >= 0) { // Not off left
+ int16_t y2 = y + h - 1;
+ if(y2 >= 0) { // Not off top
+ // Rectangle partly or fully overlaps screen
+ if(x < 0) { x = 0; w = x2 + 1; } // Clip left
+ if(y < 0) { y = 0; h = y2 + 1; } // Clip top
+ if(x2 >= _width) { w = _width - x; } // Clip right
+ if(y2 >= _height) { h = _height - y; } // Clip bottom
+ writeFillRectPreclipped(x, y, w, h, color);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*!
+ @brief Draw a horizontal line on the display. Performs edge clipping
+ and rejection. Not self-contained; should follow startWrite().
+ Typically used by higher-level graphics primitives; user code
+ shouldn't need to call this and is likely to use the self-
+ contained drawFastHLine() instead.
+ @param x Horizontal position of first point.
+ @param y Vertical position of first point.
+ @param w Line width in pixels (positive = right of first point,
+ negative = point of first corner).
+ @param color 16-bit line color in '565' RGB format.
+*/
+void inline Adafruit_SPITFT::writeFastHLine(int16_t x, int16_t y, int16_t w,
+ uint16_t color) {
+ if((y >= 0) && (y < _height) && w) { // Y on screen, nonzero width
+ if(w < 0) { // If negative width...
+ x += w + 1; // Move X to left edge
+ w = -w; // Use positive width
+ }
+ if(x < _width) { // Not off right
+ int16_t x2 = x + w - 1;
+ if(x2 >= 0) { // Not off left
+ // Line partly or fully overlaps screen
+ if(x < 0) { x = 0; w = x2 + 1; } // Clip left
+ if(x2 >= _width) { w = _width - x; } // Clip right
+ writeFillRectPreclipped(x, y, w, 1, color);
+ }
+ }
+ }
+}
+
+/*!
+ @brief Draw a vertical line on the display. Performs edge clipping and
+ rejection. Not self-contained; should follow startWrite().
+ Typically used by higher-level graphics primitives; user code
+ shouldn't need to call this and is likely to use the self-
+ contained drawFastVLine() instead.
+ @param x Horizontal position of first point.
+ @param y Vertical position of first point.
+ @param h Line height in pixels (positive = below first point,
+ negative = above first point).
+ @param color 16-bit line color in '565' RGB format.
+*/
+void inline Adafruit_SPITFT::writeFastVLine(int16_t x, int16_t y, int16_t h,
+ uint16_t color) {
+ if((x >= 0) && (x < _width) && h) { // X on screen, nonzero height
+ if(h < 0) { // If negative height...
+ y += h + 1; // Move Y to top edge
+ h = -h; // Use positive height
+ }
+ if(y < _height) { // Not off bottom
+ int16_t y2 = y + h - 1;
+ if(y2 >= 0) { // Not off top
+ // Line partly or fully overlaps screen
+ if(y < 0) { y = 0; h = y2 + 1; } // Clip top
+ if(y2 >= _height) { h = _height - y; } // Clip bottom
+ writeFillRectPreclipped(x, y, 1, h, color);
+ }
+ }
+ }
+}
+
+/*!
+ @brief A lower-level version of writeFillRect(). This version requires
+ all inputs are in-bounds, that width and height are positive,
+ and no part extends offscreen. NO EDGE CLIPPING OR REJECTION IS
+ PERFORMED. If higher-level graphics primitives are written to
+ handle their own clipping earlier in the drawing process, this
+ can avoid unnecessary function calls and repeated clipping
+ operations in the lower-level functions.
+ @param x Horizontal position of first corner. MUST BE WITHIN
+ SCREEN BOUNDS.
+ @param y Vertical position of first corner. MUST BE WITHIN SCREEN
+ BOUNDS.
+ @param w Rectangle width in pixels. MUST BE POSITIVE AND NOT
+ EXTEND OFF SCREEN.
+ @param h Rectangle height in pixels. MUST BE POSITIVE AND NOT
+ EXTEND OFF SCREEN.
+ @param color 16-bit fill color in '565' RGB format.
+ @note This is a new function, no graphics primitives besides rects
+ and horizontal/vertical lines are written to best use this yet.
+*/
+inline void Adafruit_SPITFT::writeFillRectPreclipped(int16_t x, int16_t y,
+ int16_t w, int16_t h, uint16_t color) {
+ setAddrWindow(x, y, w, h);
+ writeColor(color, (uint32_t)w * h);
+}
+
+
+// -------------------------------------------------------------------------
+// Ever-so-slightly higher-level graphics operations. Similar to the 'write'
+// functions above, but these contain their own chip-select and SPI
+// transactions as needed (via startWrite(), endWrite()). They're typically
+// used solo -- as graphics primitives in themselves, not invoked by higher-
+// level primitives (which should use the functions above for better
+// performance).
+
+/*!
+ @brief Draw a single pixel to the display at requested coordinates.
+ Self-contained and provides its own transaction as needed
+ (see writePixel(x,y,color) for a lower-level variant).
+ Edge clipping is performed here.
+ @param x Horizontal position (0 = left).
+ @param y Vertical position (0 = top).
+ @param color 16-bit pixel color in '565' RGB format.
+*/
+void Adafruit_SPITFT::drawPixel(int16_t x, int16_t y, uint16_t color) {
+ // Clip first...
+ if((x >= 0) && (x < _width) && (y >= 0) && (y < _height)) {
+ // THEN set up transaction (if needed) and draw...
+ startWrite();
+ setAddrWindow(x, y, 1, 1);
+ SPI_WRITE16(color);
+ endWrite();
+ }
+}
+
+/*!
+ @brief Draw a filled rectangle to the display. Self-contained and
+ provides its own transaction as needed (see writeFillRect() or
+ writeFillRectPreclipped() for lower-level variants). Edge
+ clipping and rejection is performed here.
+ @param x Horizontal position of first corner.
+ @param y Vertical position of first corner.
+ @param w Rectangle width in pixels (positive = right of first
+ corner, negative = left of first corner).
+ @param h Rectangle height in pixels (positive = below first
+ corner, negative = above first corner).
+ @param color 16-bit fill color in '565' RGB format.
+ @note This repeats the writeFillRect() function almost in its entirety,
+ with the addition of a transaction start/end. It's done this way
+ (rather than starting the transaction and calling writeFillRect()
+ to handle clipping and so forth) so that the transaction isn't
+ performed at all if the rectangle is rejected. It's really not
+ that much code.
+*/
+void Adafruit_SPITFT::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
+ uint16_t color) {
+ if(w && h) { // Nonzero width and height?
+ if(w < 0) { // If negative width...
+ x += w + 1; // Move X to left edge
+ w = -w; // Use positive width
+ }
+ if(x < _width) { // Not off right
+ if(h < 0) { // If negative height...
+ y += h + 1; // Move Y to top edge
+ h = -h; // Use positive height
+ }
+ if(y < _height) { // Not off bottom
+ int16_t x2 = x + w - 1;
+ if(x2 >= 0) { // Not off left
+ int16_t y2 = y + h - 1;
+ if(y2 >= 0) { // Not off top
+ // Rectangle partly or fully overlaps screen
+ if(x < 0) { x = 0; w = x2 + 1; } // Clip left
+ if(y < 0) { y = 0; h = y2 + 1; } // Clip top
+ if(x2 >= _width) { w = _width - x; } // Clip right
+ if(y2 >= _height) { h = _height - y; } // Clip bottom
+ startWrite();
+ writeFillRectPreclipped(x, y, w, h, color);
+ endWrite();
+ }
+ }
+ }
+ }
+ }
+}
+
+/*!
+ @brief Draw a horizontal line on the display. Self-contained and
+ provides its own transaction as needed (see writeFastHLine() for
+ a lower-level variant). Edge clipping and rejection is performed
+ here.
+ @param x Horizontal position of first point.
+ @param y Vertical position of first point.
+ @param w Line width in pixels (positive = right of first point,
+ negative = point of first corner).
+ @param color 16-bit line color in '565' RGB format.
+ @note This repeats the writeFastHLine() function almost in its
+ entirety, with the addition of a transaction start/end. It's
+ done this way (rather than starting the transaction and calling
+ writeFastHLine() to handle clipping and so forth) so that the
+ transaction isn't performed at all if the line is rejected.
+*/
+void Adafruit_SPITFT::drawFastHLine(int16_t x, int16_t y, int16_t w,
+ uint16_t color) {
+ if((y >= 0) && (y < _height) && w) { // Y on screen, nonzero width
+ if(w < 0) { // If negative width...
+ x += w + 1; // Move X to left edge
+ w = -w; // Use positive width
+ }
+ if(x < _width) { // Not off right
+ int16_t x2 = x + w - 1;
+ if(x2 >= 0) { // Not off left
+ // Line partly or fully overlaps screen
+ if(x < 0) { x = 0; w = x2 + 1; } // Clip left
+ if(x2 >= _width) { w = _width - x; } // Clip right
+ startWrite();
+ writeFillRectPreclipped(x, y, w, 1, color);
+ endWrite();
+ }
+ }
+ }
+}
+
+/*!
+ @brief Draw a vertical line on the display. Self-contained and provides
+ its own transaction as needed (see writeFastHLine() for a lower-
+ level variant). Edge clipping and rejection is performed here.
+ @param x Horizontal position of first point.
+ @param y Vertical position of first point.
+ @param h Line height in pixels (positive = below first point,
+ negative = above first point).
+ @param color 16-bit line color in '565' RGB format.
+ @note This repeats the writeFastVLine() function almost in its
+ entirety, with the addition of a transaction start/end. It's
+ done this way (rather than starting the transaction and calling
+ writeFastVLine() to handle clipping and so forth) so that the
+ transaction isn't performed at all if the line is rejected.
+*/
+void Adafruit_SPITFT::drawFastVLine(int16_t x, int16_t y, int16_t h,
+ uint16_t color) {
+ if((x >= 0) && (x < _width) && h) { // X on screen, nonzero height
+ if(h < 0) { // If negative height...
+ y += h + 1; // Move Y to top edge
+ h = -h; // Use positive height
+ }
+ if(y < _height) { // Not off bottom
+ int16_t y2 = y + h - 1;
+ if(y2 >= 0) { // Not off top
+ // Line partly or fully overlaps screen
+ if(y < 0) { y = 0; h = y2 + 1; } // Clip top
+ if(y2 >= _height) { h = _height - y; } // Clip bottom
+ startWrite();
+ writeFillRectPreclipped(x, y, 1, h, color);
+ endWrite();
+ }
+ }
+ }
+}
+
+/*!
+ @brief Essentially writePixel() with a transaction around it. I don't
+ think this is in use by any of our code anymore (believe it was
+ for some older BMP-reading examples), but is kept here in case
+ any user code relies on it. Consider it DEPRECATED.
+ @param color 16-bit pixel color in '565' RGB format.
+*/
+void Adafruit_SPITFT::pushColor(uint16_t color) {
+ startWrite();
+ SPI_WRITE16(color);
+ endWrite();
+}
+
+/*!
+ @brief Draw a 16-bit image (565 RGB) at the specified (x,y) position.
+ For 16-bit display devices; no color reduction performed.
+ Adapted from https://github.com/PaulStoffregen/ILI9341_t3
+ by Marc MERLIN. See examples/pictureEmbed to use this.
+ 5/6/2017: function name and arguments have changed for
+ compatibility with current GFX library and to avoid naming
+ problems in prior implementation. Formerly drawBitmap() with
+ arguments in different order. Handles its own transaction and
+ edge clipping/rejection.
+ @param x Top left corner horizontal coordinate.
+ @param y Top left corner vertical coordinate.
+ @param pcolors Pointer to 16-bit array of pixel values.
+ @param w Width of bitmap in pixels.
+ @param h Height of bitmap in pixels.
+*/
+void Adafruit_SPITFT::drawRGBBitmap(int16_t x, int16_t y,
+ uint16_t *pcolors, int16_t w, int16_t h) {
+
+ int16_t x2, y2; // Lower-right coord
+ if(( x >= _width ) || // Off-edge right
+ ( y >= _height) || // " top
+ ((x2 = (x+w-1)) < 0 ) || // " left
+ ((y2 = (y+h-1)) < 0) ) return; // " bottom
+
+ int16_t bx1=0, by1=0, // Clipped top-left within bitmap
+ saveW=w; // Save original bitmap width value
+ if(x < 0) { // Clip left
+ w += x;
+ bx1 = -x;
+ x = 0;
+ }
+ if(y < 0) { // Clip top
+ h += y;
+ by1 = -y;
+ y = 0;
+ }
+ if(x2 >= _width ) w = _width - x; // Clip right
+ if(y2 >= _height) h = _height - y; // Clip bottom
+
+ pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
+ startWrite();
+ setAddrWindow(x, y, w, h); // Clipped area
+ while(h--) { // For each (clipped) scanline...
+ writePixels(pcolors, w); // Push one (clipped) row
+ pcolors += saveW; // Advance pointer by one full (unclipped) line
+ }
+ endWrite();
+}
+
+
+// -------------------------------------------------------------------------
+// Miscellaneous class member functions that don't draw anything.
+
+/*!
+ @brief Invert the colors of the display (if supported by hardware).
+ Self-contained, no transaction setup required.
+ @param i true = inverted display, false = normal display.
+*/
+void Adafruit_SPITFT::invertDisplay(bool i) {
+ startWrite();
+ writeCommand(i ? invertOnCommand : invertOffCommand);
+ endWrite();
+}
+
+/*!
+ @brief Given 8-bit red, green and blue values, return a 'packed'
+ 16-bit color value in '565' RGB format (5 bits red, 6 bits
+ green, 5 bits blue). This is just a mathematical operation,
+ no hardware is touched.
+ @param red 8-bit red brightnesss (0 = off, 255 = max).
+ @param green 8-bit green brightnesss (0 = off, 255 = max).
+ @param blue 8-bit blue brightnesss (0 = off, 255 = max).
+ @return 'Packed' 16-bit color value (565 format).
+*/
+uint16_t Adafruit_SPITFT::color565(uint8_t red, uint8_t green, uint8_t blue) {
+ return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
+}
+
+/*!
+ @brief Adafruit_SPITFT Send Command handles complete sending of commands and data
+ @param commandByte The Command Byte
+ @param dataBytes A pointer to the Data bytes to send
+ @param numDataBytes The number of bytes we should send
+ */
+void Adafruit_SPITFT::sendCommand(uint8_t commandByte, uint8_t *dataBytes, uint8_t numDataBytes) {
+ SPI_BEGIN_TRANSACTION();
+ if(_cs >= 0) SPI_CS_LOW();
+
+ SPI_DC_LOW(); // Command mode
+ spiWrite(commandByte); // Send the command byte
+
+ SPI_DC_HIGH();
+ for (int i=0; i= 0) SPI_CS_HIGH();
+ SPI_END_TRANSACTION();
+}
+
+/*!
+ @brief Adafruit_SPITFT Send Command handles complete sending of commands and const data
+ @param commandByte The Command Byte
+ @param dataBytes A pointer to the Data bytes to send
+ @param numDataBytes The number of bytes we should send
+ */
+void Adafruit_SPITFT::sendCommand(uint8_t commandByte, const uint8_t *dataBytes, uint8_t numDataBytes) {
+ SPI_BEGIN_TRANSACTION();
+ if(_cs >= 0) SPI_CS_LOW();
+
+ SPI_DC_LOW(); // Command mode
+ spiWrite(commandByte); // Send the command byte
+
+ SPI_DC_HIGH();
+ for (int i=0; i= 0) SPI_CS_HIGH();
+ SPI_END_TRANSACTION();
+}
+
+/*!
+ @brief Read 8 bits of data from display configuration memory (not RAM).
+ This is highly undocumented/supported and should be avoided,
+ function is only included because some of the examples use it.
+ @param commandByte
+ The command register to read data from.
+ @param index
+ The byte index into the command to read from.
+ @return Unsigned 8-bit data read from display register.
+ */
+/**************************************************************************/
+uint8_t Adafruit_SPITFT::readcommand8(uint8_t commandByte, uint8_t index) {
+ uint8_t result;
+ startWrite();
+ SPI_DC_LOW(); // Command mode
+ spiWrite(commandByte);
+ SPI_DC_HIGH(); // Data mode
+ do {
+ result = spiRead();
+ } while(index--); // Discard bytes up to index'th
+ endWrite();
+ return result;
+}
+
+// -------------------------------------------------------------------------
+// Lowest-level hardware-interfacing functions. Many of these are inline and
+// compile to different things based on #defines -- typically just a few
+// instructions. Others, not so much, those are not inlined.
+
+/*!
+ @brief Start an SPI transaction if using the hardware SPI interface to
+ the display. If using an earlier version of the Arduino platform
+ (before the addition of SPI transactions), this instead attempts
+ to set up the SPI clock and mode. No action is taken if the
+ connection is not hardware SPI-based. This does NOT include a
+ chip-select operation -- see startWrite() for a function that
+ encapsulated both actions.
+*/
+inline void Adafruit_SPITFT::SPI_BEGIN_TRANSACTION(void) {
+ if(connection == TFT_HARD_SPI) {
+#if defined(SPI_HAS_TRANSACTION)
+ hwspi._spi->beginTransaction(hwspi.settings);
+#else // No transactions, configure SPI manually...
+ #if defined(__AVR__) || defined(TEENSYDUINO) || defined(ARDUINO_ARCH_STM32F1)
+ hwspi._spi->setClockDivider(SPI_CLOCK_DIV2);
+ #elif defined(__arm__)
+ hwspi._spi->setClockDivider(11);
+ #elif defined(ESP8266) || defined(ESP32)
+ hwspi._spi->setFrequency(hwspi._freq);
+ #elif defined(RASPI) || defined(ARDUINO_ARCH_STM32F1)
+ hwspi._spi->setClock(hwspi._freq);
+ #endif
+ hwspi._spi->setBitOrder(MSBFIRST);
+ hwspi._spi->setDataMode(hwspi._mode);
+#endif // end !SPI_HAS_TRANSACTION
+ }
+}
+
+/*!
+ @brief End an SPI transaction if using the hardware SPI interface to
+ the display. No action is taken if the connection is not
+ hardware SPI-based or if using an earlier version of the Arduino
+ platform (before the addition of SPI transactions). This does
+ NOT include a chip-deselect operation -- see endWrite() for a
+ function that encapsulated both actions.
+*/
+inline void Adafruit_SPITFT::SPI_END_TRANSACTION(void) {
+#if defined(SPI_HAS_TRANSACTION)
+ if(connection == TFT_HARD_SPI) {
+ hwspi._spi->endTransaction();
+ }
+#endif
+}
+
+/*!
+ @brief Issue a single 8-bit value to the display. Chip-select,
+ transaction and data/command selection must have been
+ previously set -- this ONLY issues the byte. This is another of
+ those functions in the library with a now-not-accurate name
+ that's being maintained for compatibility with outside code.
+ This function is used even if display connection is parallel.
+ @param b 8-bit value to write.
+*/
+void Adafruit_SPITFT::spiWrite(uint8_t b) {
+ if(connection == TFT_HARD_SPI) {
+#if defined(__AVR__)
+ AVR_WRITESPI(b);
+#elif defined(ESP8266) || defined(ESP32)
+ hwspi._spi->write(b);
+#else
+ hwspi._spi->transfer(b);
+#endif
+ } else if(connection == TFT_SOFT_SPI) {
+ for(uint8_t bit=0; bit<8; bit++) {
+ if(b & 0x80) SPI_MOSI_HIGH();
+ else SPI_MOSI_LOW();
+ SPI_SCK_HIGH();
+ b <<= 1;
+ SPI_SCK_LOW();
+ }
+ } else { // TFT_PARALLEL
+#if defined(__AVR__)
+ *tft8.writePort = b;
+#elif defined(USE_FAST_PINIO)
+ if(!tft8.wide) *tft8.writePort = b;
+ else *(volatile uint16_t *)tft8.writePort = b;
+#endif
+ TFT_WR_STROBE();
+ }
+}
+
+/*!
+ @brief Write a single command byte to the display. Chip-select and
+ transaction must have been previously set -- this ONLY sets
+ the device to COMMAND mode, issues the byte and then restores
+ DATA mode. There is no corresponding explicit writeData()
+ function -- just use spiWrite().
+ @param cmd 8-bit command to write.
+*/
+void Adafruit_SPITFT::writeCommand(uint8_t cmd) {
+ SPI_DC_LOW();
+ spiWrite(cmd);
+ SPI_DC_HIGH();
+}
+
+/*!
+ @brief Read a single 8-bit value from the display. Chip-select and
+ transaction must have been previously set -- this ONLY reads
+ the byte. This is another of those functions in the library
+ with a now-not-accurate name that's being maintained for
+ compatibility with outside code. This function is used even if
+ display connection is parallel.
+ @return Unsigned 8-bit value read (always zero if USE_FAST_PINIO is
+ not supported by the MCU architecture).
+*/
+uint8_t Adafruit_SPITFT::spiRead(void) {
+ uint8_t b = 0;
+ uint16_t w = 0;
+ if(connection == TFT_HARD_SPI) {
+ return hwspi._spi->transfer((uint8_t)0);
+ } else if(connection == TFT_SOFT_SPI) {
+ if(swspi._miso >= 0) {
+ for(uint8_t i=0; i<8; i++) {
+ SPI_SCK_HIGH();
+ b <<= 1;
+ if(SPI_MISO_READ()) b++;
+ SPI_SCK_LOW();
+ }
+ }
+ return b;
+ } else { // TFT_PARALLEL
+ if(tft8._rd >= 0) {
+#if defined(USE_FAST_PINIO)
+ TFT_RD_LOW(); // Read line LOW
+ #if defined(__AVR__)
+ *tft8.portDir = 0x00; // Set port to input state
+ w = *tft8.readPort; // Read value from port
+ *tft8.portDir = 0xFF; // Restore port to output
+ #else // !__AVR__
+ if(!tft8.wide) { // 8-bit TFT connection
+ #if defined(HAS_PORT_SET_CLR)
+ *tft8.dirClr = 0xFF; // Set port to input state
+ w = *tft8.readPort; // Read value from port
+ *tft8.dirSet = 0xFF; // Restore port to output
+ #else // !HAS_PORT_SET_CLR
+ *tft8.portDir = 0x00; // Set port to input state
+ w = *tft8.readPort; // Read value from port
+ *tft8.portDir = 0xFF; // Restore port to output
+ #endif // end HAS_PORT_SET_CLR
+ } else { // 16-bit TFT connection
+ #if defined(HAS_PORT_SET_CLR)
+ *(volatile uint16_t *)tft8.dirClr = 0xFFFF; // Input state
+ w = *(volatile uint16_t *)tft8.readPort; // 16-bit read
+ *(volatile uint16_t *)tft8.dirSet = 0xFFFF; // Output state
+ #else // !HAS_PORT_SET_CLR
+ *(volatile uint16_t *)tft8.portDir = 0x0000; // Input state
+ w = *(volatile uint16_t *)tft8.readPort; // 16-bit read
+ *(volatile uint16_t *)tft8.portDir = 0xFFFF; // Output state
+ #endif // end !HAS_PORT_SET_CLR
+ }
+ TFT_RD_HIGH(); // Read line HIGH
+ #endif // end !__AVR__
+#else // !USE_FAST_PINIO
+ w = 0; // Parallel TFT is NOT SUPPORTED without USE_FAST_PINIO
+#endif // end !USE_FAST_PINIO
+ }
+ return w;
+ }
+}
+
+/*!
+ @brief Set the software (bitbang) SPI MOSI line HIGH.
+*/
+inline void Adafruit_SPITFT::SPI_MOSI_HIGH(void) {
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(KINETISK)
+ *swspi.mosiPortSet = 1;
+ #else // !KINETISK
+ *swspi.mosiPortSet = swspi.mosiPinMask;
+ #endif
+ #else // !HAS_PORT_SET_CLR
+ *swspi.mosiPort |= swspi.mosiPinMaskSet;
+ #endif // end !HAS_PORT_SET_CLR
+#else // !USE_FAST_PINIO
+ digitalWrite(swspi._mosi, HIGH);
+ #if defined(ESP32)
+ for(volatile uint8_t i=0; i<1; i++);
+ #endif // end ESP32
+#endif // end !USE_FAST_PINIO
+}
+
+/*!
+ @brief Set the software (bitbang) SPI MOSI line LOW.
+*/
+inline void Adafruit_SPITFT::SPI_MOSI_LOW(void) {
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(KINETISK)
+ *swspi.mosiPortClr = 1;
+ #else // !KINETISK
+ *swspi.mosiPortClr = swspi.mosiPinMask;
+ #endif
+ #else // !HAS_PORT_SET_CLR
+ *swspi.mosiPort &= swspi.mosiPinMaskClr;
+ #endif // end !HAS_PORT_SET_CLR
+#else // !USE_FAST_PINIO
+ digitalWrite(swspi._mosi, LOW);
+ #if defined(ESP32)
+ for(volatile uint8_t i=0; i<1; i++);
+ #endif // end ESP32
+#endif // end !USE_FAST_PINIO
+}
+
+/*!
+ @brief Set the software (bitbang) SPI SCK line HIGH.
+*/
+inline void Adafruit_SPITFT::SPI_SCK_HIGH(void) {
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(KINETISK)
+ *swspi.sckPortSet = 1;
+ #else // !KINETISK
+ *swspi.sckPortSet = swspi.sckPinMask;
+ #if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
+ for(volatile uint8_t i=0; i<1; i++);
+ #endif
+ #endif
+ #else // !HAS_PORT_SET_CLR
+ *swspi.sckPort |= swspi.sckPinMaskSet;
+ #endif // end !HAS_PORT_SET_CLR
+#else // !USE_FAST_PINIO
+ digitalWrite(swspi._sck, HIGH);
+ #if defined(ESP32)
+ for(volatile uint8_t i=0; i<1; i++);
+ #endif // end ESP32
+#endif // end !USE_FAST_PINIO
+}
+
+/*!
+ @brief Set the software (bitbang) SPI SCK line LOW.
+*/
+inline void Adafruit_SPITFT::SPI_SCK_LOW(void) {
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(KINETISK)
+ *swspi.sckPortClr = 1;
+ #else // !KINETISK
+ *swspi.sckPortClr = swspi.sckPinMask;
+ #if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
+ for(volatile uint8_t i=0; i<1; i++);
+ #endif
+ #endif
+ #else // !HAS_PORT_SET_CLR
+ *swspi.sckPort &= swspi.sckPinMaskClr;
+ #endif // end !HAS_PORT_SET_CLR
+#else // !USE_FAST_PINIO
+ digitalWrite(swspi._sck, LOW);
+ #if defined(ESP32)
+ for(volatile uint8_t i=0; i<1; i++);
+ #endif // end ESP32
+#endif // end !USE_FAST_PINIO
+}
+
+/*!
+ @brief Read the state of the software (bitbang) SPI MISO line.
+ @return true if HIGH, false if LOW.
+*/
+inline bool Adafruit_SPITFT::SPI_MISO_READ(void) {
+#if defined(USE_FAST_PINIO)
+ #if defined(KINETISK)
+ return *swspi.misoPort;
+ #else // !KINETISK
+ return *swspi.misoPort & swspi.misoPinMask;
+ #endif // end !KINETISK
+#else // !USE_FAST_PINIO
+ return digitalRead(swspi._miso);
+#endif // end !USE_FAST_PINIO
+}
+
+/*!
+ @brief Issue a single 16-bit value to the display. Chip-select,
+ transaction and data/command selection must have been
+ previously set -- this ONLY issues the word. Despite the name,
+ this function is used even if display connection is parallel;
+ name was maintaned for backward compatibility. Naming is also
+ not consistent with the 8-bit version, spiWrite(). Sorry about
+ that. Again, staying compatible with outside code.
+ @param w 16-bit value to write.
+*/
+void Adafruit_SPITFT::SPI_WRITE16(uint16_t w) {
+ if(connection == TFT_HARD_SPI) {
+#if defined(__AVR__)
+ AVR_WRITESPI(w >> 8);
+ AVR_WRITESPI(w);
+#elif defined(ESP8266) || defined(ESP32)
+ hwspi._spi->write16(w);
+#else
+ hwspi._spi->transfer(w >> 8);
+ hwspi._spi->transfer(w);
+#endif
+ } else if(connection == TFT_SOFT_SPI) {
+ for(uint8_t bit=0; bit<16; bit++) {
+ if(w & 0x8000) SPI_MOSI_HIGH();
+ else SPI_MOSI_LOW();
+ SPI_SCK_HIGH();
+ SPI_SCK_LOW();
+ w <<= 1;
+ }
+ } else { // TFT_PARALLEL
+#if defined(__AVR__)
+ *tft8.writePort = w >> 8;
+ TFT_WR_STROBE();
+ *tft8.writePort = w;
+#elif defined(USE_FAST_PINIO)
+ if(!tft8.wide) {
+ *tft8.writePort = w >> 8;
+ TFT_WR_STROBE();
+ *tft8.writePort = w;
+ } else {
+ *(volatile uint16_t *)tft8.writePort = w;
+ }
+#endif
+ TFT_WR_STROBE();
+ }
+}
+
+/*!
+ @brief Issue a single 32-bit value to the display. Chip-select,
+ transaction and data/command selection must have been
+ previously set -- this ONLY issues the longword. Despite the
+ name, this function is used even if display connection is
+ parallel; name was maintaned for backward compatibility. Naming
+ is also not consistent with the 8-bit version, spiWrite().
+ Sorry about that. Again, staying compatible with outside code.
+ @param l 32-bit value to write.
+*/
+void Adafruit_SPITFT::SPI_WRITE32(uint32_t l) {
+ if(connection == TFT_HARD_SPI) {
+#if defined(__AVR__)
+ AVR_WRITESPI(l >> 24);
+ AVR_WRITESPI(l >> 16);
+ AVR_WRITESPI(l >> 8);
+ AVR_WRITESPI(l );
+#elif defined(ESP8266) || defined(ESP32)
+ hwspi._spi->write32(l);
+#else
+ hwspi._spi->transfer(l >> 24);
+ hwspi._spi->transfer(l >> 16);
+ hwspi._spi->transfer(l >> 8);
+ hwspi._spi->transfer(l);
+#endif
+ } else if(connection == TFT_SOFT_SPI) {
+ for(uint8_t bit=0; bit<32; bit++) {
+ if(l & 0x80000000) SPI_MOSI_HIGH();
+ else SPI_MOSI_LOW();
+ SPI_SCK_HIGH();
+ SPI_SCK_LOW();
+ l <<= 1;
+ }
+ } else { // TFT_PARALLEL
+#if defined(__AVR__)
+ *tft8.writePort = l >> 24;
+ TFT_WR_STROBE();
+ *tft8.writePort = l >> 16;
+ TFT_WR_STROBE();
+ *tft8.writePort = l >> 8;
+ TFT_WR_STROBE();
+ *tft8.writePort = l;
+#elif defined(USE_FAST_PINIO)
+ if(!tft8.wide) {
+ *tft8.writePort = l >> 24;
+ TFT_WR_STROBE();
+ *tft8.writePort = l >> 16;
+ TFT_WR_STROBE();
+ *tft8.writePort = l >> 8;
+ TFT_WR_STROBE();
+ *tft8.writePort = l;
+ } else {
+ *(volatile uint16_t *)tft8.writePort = l >> 16;
+ TFT_WR_STROBE();
+ *(volatile uint16_t *)tft8.writePort = l;
+ }
+#endif
+ TFT_WR_STROBE();
+ }
+}
+
+/*!
+ @brief Set the WR line LOW, then HIGH. Used for parallel-connected
+ interfaces when writing data.
+*/
+inline void Adafruit_SPITFT::TFT_WR_STROBE(void) {
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(KINETISK)
+ *tft8.wrPortClr = 1;
+ *tft8.wrPortSet = 1;
+ #else // !KINETISK
+ *tft8.wrPortClr = tft8.wrPinMask;
+ *tft8.wrPortSet = tft8.wrPinMask;
+ #endif // end !KINETISK
+ #else // !HAS_PORT_SET_CLR
+ *tft8.wrPort &= tft8.wrPinMaskClr;
+ *tft8.wrPort |= tft8.wrPinMaskSet;
+ #endif // end !HAS_PORT_SET_CLR
+#else // !USE_FAST_PINIO
+ digitalWrite(tft8._wr, LOW);
+ digitalWrite(tft8._wr, HIGH);
+#endif // end !USE_FAST_PINIO
+}
+
+/*!
+ @brief Set the RD line HIGH. Used for parallel-connected interfaces
+ when reading data.
+*/
+inline void Adafruit_SPITFT::TFT_RD_HIGH(void) {
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ *tft8.rdPortSet = tft8.rdPinMask;
+ #else // !HAS_PORT_SET_CLR
+ *tft8.rdPort |= tft8.rdPinMaskSet;
+ #endif // end !HAS_PORT_SET_CLR
+#else // !USE_FAST_PINIO
+ digitalWrite(tft8._rd, HIGH);
+#endif // end !USE_FAST_PINIO
+}
+
+/*!
+ @brief Set the RD line LOW. Used for parallel-connected interfaces
+ when reading data.
+*/
+inline void Adafruit_SPITFT::TFT_RD_LOW(void) {
+#if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ *tft8.rdPortClr = tft8.rdPinMask;
+ #else // !HAS_PORT_SET_CLR
+ *tft8.rdPort &= tft8.rdPinMaskClr;
+ #endif // end !HAS_PORT_SET_CLR
+#else // !USE_FAST_PINIO
+ digitalWrite(tft8._rd, LOW);
+#endif // end !USE_FAST_PINIO
+}
+
+#endif // end __AVR_ATtiny85__
diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h
new file mode 100644
index 000000000..33a911774
--- /dev/null
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h
@@ -0,0 +1,519 @@
+/*!
+ * @file Adafruit_SPITFT.h
+ *
+ * Part of Adafruit's GFX graphics library. Originally this class was
+ * written to handle a range of color TFT displays connected via SPI,
+ * but over time this library and some display-specific subclasses have
+ * mutated to include some color OLEDs as well as parallel-interfaced
+ * displays. The name's been kept for the sake of older code.
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing
+ * products from Adafruit!
+ *
+ * Written by Limor "ladyada" Fried for Adafruit Industries,
+ * with contributions from the open source community.
+ *
+ * BSD license, all text here must be included in any redistribution.
+ */
+
+#ifndef _ADAFRUIT_SPITFT_H_
+#define _ADAFRUIT_SPITFT_H_
+
+#if !defined(__AVR_ATtiny85__) // Not for ATtiny, at all
+
+#include
+#include "Adafruit_GFX.h"
+
+// HARDWARE CONFIG ---------------------------------------------------------
+
+#if defined(__AVR__)
+ typedef uint8_t ADAGFX_PORT_t; ///< PORT values are 8-bit
+ #define USE_FAST_PINIO ///< Use direct PORT register access
+#elif defined(ARDUINO_STM32_FEATHER) // WICED
+ typedef class HardwareSPI SPIClass; ///< SPI is a bit odd on WICED
+ typedef uint32_t ADAGFX_PORT_t; ///< PORT values are 32-bit
+#elif defined(__arm__)
+ #if defined(ARDUINO_ARCH_SAMD)
+ // Adafruit M0, M4
+ typedef uint32_t ADAGFX_PORT_t; ///< PORT values are 32-bit
+ #define USE_FAST_PINIO ///< Use direct PORT register access
+ #define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
+ #elif defined(CORE_TEENSY)
+ // PJRC Teensy 4.x
+ #if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
+ typedef uint32_t ADAGFX_PORT_t; ///< PORT values are 32-bit
+ // PJRC Teensy 3.x
+ #else
+ typedef uint8_t ADAGFX_PORT_t; ///< PORT values are 8-bit
+ #endif
+ #define USE_FAST_PINIO ///< Use direct PORT register access
+ #define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
+ #else
+ // Arduino Due?
+ typedef uint32_t ADAGFX_PORT_t; ///< PORT values are 32-bit
+ // USE_FAST_PINIO not available here (yet)...Due has a totally different
+ // GPIO register set and will require some changes elsewhere (e.g. in
+ // constructors especially).
+ #endif
+#else // !ARM
+ // Probably ESP8266 or ESP32. USE_FAST_PINIO is not available here (yet)
+ // but don't worry about it too much...the digitalWrite() implementation
+ // on these platforms is reasonably efficient and already RAM-resident,
+ // only gotcha then is no parallel connection support for now.
+ typedef uint32_t ADAGFX_PORT_t; ///< PORT values are 32-bit
+#endif // end !ARM
+typedef volatile ADAGFX_PORT_t* PORTreg_t; ///< PORT register type
+
+#if defined(__AVR__)
+ #define DEFAULT_SPI_FREQ 8000000L ///< Hardware SPI default speed
+#else
+ #define DEFAULT_SPI_FREQ 16000000L ///< Hardware SPI default speed
+#endif
+
+#if defined(ADAFRUIT_PYPORTAL) || defined(ADAFRUIT_PYBADGE_M4_EXPRESS) || defined(ADAFRUIT_PYGAMER_M4_EXPRESS)
+ #define USE_SPI_DMA ///< Auto DMA if using PyPortal
+#else
+ //#define USE_SPI_DMA ///< If set, use DMA if available
+#endif
+// Another "oops" name -- this now also handles parallel DMA.
+// If DMA is enabled, Arduino sketch MUST #include
+// Estimated RAM usage:
+// 4 bytes/pixel on display major axis + 8 bytes/pixel on minor axis,
+// e.g. 320x240 pixels = 320 * 4 + 240 * 8 = 3,200 bytes.
+
+#if !defined(ARDUINO_ARCH_SAMD)
+ #undef USE_SPI_DMA ///< DMA currently for SAMD chips only
+#endif
+
+#if defined(USE_SPI_DMA)
+ #pragma message ("GFX DMA IS ENABLED. HIGHLY EXPERIMENTAL.")
+ #include
+#endif
+
+// This is kind of a kludge. Needed a way to disambiguate the software SPI
+// and parallel constructors via their argument lists. Originally tried a
+// bool as the first argument to the parallel constructor (specifying 8-bit
+// vs 16-bit interface) but the compiler regards this as equivalent to an
+// integer and thus still ambiguous. SO...the parallel constructor requires
+// an enumerated type as the first argument: tft8 (for 8-bit parallel) or
+// tft16 (for 16-bit)...even though 16-bit isn't fully implemented or tested
+// and might never be, still needed that disambiguation from soft SPI.
+enum tftBusWidth { tft8bitbus, tft16bitbus }; ///< For first arg to parallel constructor
+
+// CLASS DEFINITION --------------------------------------------------------
+
+/*!
+ @brief Adafruit_SPITFT is an intermediary class between Adafruit_GFX
+ and various hardware-specific subclasses for different displays.
+ It handles certain operations that are common to a range of
+ displays (address window, area fills, etc.). Originally these were
+ all color TFT displays interfaced via SPI, but it's since expanded
+ to include color OLEDs and parallel-interfaced TFTs. THE NAME HAS
+ BEEN KEPT TO AVOID BREAKING A LOT OF SUBCLASSES AND EXAMPLE CODE.
+ Many of the class member functions similarly live on with names
+ that don't necessarily accurately describe what they're doing,
+ again to avoid breaking a lot of other code. If in doubt, read
+ the comments.
+*/
+class Adafruit_SPITFT : public Adafruit_GFX {
+
+ public:
+
+ // CONSTRUCTORS --------------------------------------------------------
+
+ // Software SPI constructor: expects width & height (at default rotation
+ // setting 0), 4 signal pins (cs, dc, mosi, sclk), 2 optional pins
+ // (reset, miso). cs argument is required but can be -1 if unused --
+ // rather than moving it to the optional arguments, it was done this way
+ // to avoid breaking existing code (-1 option was a later addition).
+ Adafruit_SPITFT(uint16_t w, uint16_t h,
+ int8_t cs, int8_t dc, int8_t mosi, int8_t sck,
+ int8_t rst = -1, int8_t miso = -1);
+
+ // Hardware SPI constructor using the default SPI port: expects width &
+ // height (at default rotation setting 0), 2 signal pins (cs, dc),
+ // optional reset pin. cs is required but can be -1 if unused -- rather
+ // than moving it to the optional arguments, it was done this way to
+ // avoid breaking existing code (-1 option was a later addition).
+ Adafruit_SPITFT(uint16_t w, uint16_t h,
+ int8_t cs, int8_t dc, int8_t rst = -1);
+
+#if !defined(ESP8266) // See notes in .cpp
+ // Hardware SPI constructor using an arbitrary SPI peripheral: expects
+ // width & height (rotation 0), SPIClass pointer, 2 signal pins (cs, dc)
+ // and optional reset pin. cs is required but can be -1 if unused.
+ Adafruit_SPITFT(uint16_t w, uint16_t h, SPIClass *spiClass,
+ int8_t cs, int8_t dc, int8_t rst = -1);
+#endif // end !ESP8266
+
+ // Parallel constructor: expects width & height (rotation 0), flag
+ // indicating whether 16-bit (true) or 8-bit (false) interface, 3 signal
+ // pins (d0, wr, dc), 3 optional pins (cs, rst, rd). 16-bit parallel
+ // isn't even fully implemented but the 'wide' flag was added as a
+ // required argument to avoid ambiguity with other constructors.
+ Adafruit_SPITFT(uint16_t w, uint16_t h, tftBusWidth busWidth,
+ int8_t d0, int8_t wr, int8_t dc,
+ int8_t cs = -1, int8_t rst = -1, int8_t rd = -1);
+
+ // CLASS MEMBER FUNCTIONS ----------------------------------------------
+
+ // These first two functions MUST be declared by subclasses:
+
+ /*!
+ @brief Display-specific initialization function.
+ @param freq SPI frequency, in hz (or 0 for default or unused).
+ */
+ virtual void begin(uint32_t freq) = 0;
+
+ /*!
+ @brief Set up the specific display hardware's "address window"
+ for subsequent pixel-pushing operations.
+ @param x Leftmost pixel of area to be drawn (MUST be within
+ display bounds at current rotation setting).
+ @param y Topmost pixel of area to be drawn (MUST be within
+ display bounds at current rotation setting).
+ @param w Width of area to be drawn, in pixels (MUST be >0 and,
+ added to x, within display bounds at current rotation).
+ @param h Height of area to be drawn, in pixels (MUST be >0 and,
+ added to x, within display bounds at current rotation).
+ */
+ virtual void setAddrWindow(
+ uint16_t x, uint16_t y, uint16_t w, uint16_t h) = 0;
+
+ // Remaining functions do not need to be declared in subclasses
+ // unless they wish to provide hardware-specific optimizations.
+ // Brief comments here...documented more thoroughly in .cpp file.
+
+ // Subclass' begin() function invokes this to initialize hardware.
+ // freq=0 to use default SPI speed. spiMode must be one of the SPI_MODEn
+ // values defined in SPI.h, which are NOT the same as 0 for SPI_MODE0,
+ // 1 for SPI_MODE1, etc...use ONLY the SPI_MODEn defines! Only!
+ // Name is outdated (interface may be parallel) but for compatibility:
+ void initSPI(uint32_t freq = 0, uint8_t spiMode = SPI_MODE0);
+ // Chip select and/or hardware SPI transaction start as needed:
+ void startWrite(void);
+ // Chip deselect and/or hardware SPI transaction end as needed:
+ void endWrite(void);
+ void sendCommand(uint8_t commandByte, uint8_t *dataBytes = NULL, uint8_t numDataBytes = 0);
+ void sendCommand(uint8_t commandByte, const uint8_t *dataBytes, uint8_t numDataBytes);
+ uint8_t readcommand8(uint8_t commandByte, uint8_t index = 0);
+
+ // These functions require a chip-select and/or SPI transaction
+ // around them. Higher-level graphics primitives might start a
+ // single transaction and then make multiple calls to these functions
+ // (e.g. circle or text rendering might make repeated lines or rects)
+ // before ending the transaction. It's more efficient than starting a
+ // transaction every time.
+ void writePixel(int16_t x, int16_t y, uint16_t color);
+ void writePixels(uint16_t *colors, uint32_t len,
+ bool block=true, bool bigEndian=false);
+ void writeColor(uint16_t color, uint32_t len);
+ void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h,
+ uint16_t color);
+ void writeFastHLine(int16_t x, int16_t y, int16_t w,
+ uint16_t color);
+ void writeFastVLine(int16_t x, int16_t y, int16_t h,
+ uint16_t color);
+ // This is a new function, similar to writeFillRect() except that
+ // all arguments MUST be onscreen, sorted and clipped. If higher-level
+ // primitives can handle their own sorting/clipping, it avoids repeating
+ // such operations in the low-level code, making it potentially faster.
+ // CALLING THIS WITH UNCLIPPED OR NEGATIVE VALUES COULD BE DISASTROUS.
+ inline void writeFillRectPreclipped(int16_t x, int16_t y,
+ int16_t w, int16_t h, uint16_t color);
+ // Another new function, companion to the new non-blocking
+ // writePixels() variant.
+ void dmaWait(void);
+
+
+ // These functions are similar to the 'write' functions above, but with
+ // a chip-select and/or SPI transaction built-in. They're typically used
+ // solo -- that is, as graphics primitives in themselves, not invoked by
+ // higher-level primitives (which should use the functions above).
+ void drawPixel(int16_t x, int16_t y, uint16_t color);
+ void fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
+ uint16_t color);
+ void drawFastHLine(int16_t x, int16_t y, int16_t w,
+ uint16_t color);
+ void drawFastVLine(int16_t x, int16_t y, int16_t h,
+ uint16_t color);
+ // A single-pixel push encapsulated in a transaction. I don't think
+ // this is used anymore (BMP demos might've used it?) but is provided
+ // for backward compatibility, consider it deprecated:
+ void pushColor(uint16_t color);
+
+ using Adafruit_GFX::drawRGBBitmap; // Check base class first
+ void drawRGBBitmap(int16_t x, int16_t y,
+ uint16_t *pcolors, int16_t w, int16_t h);
+
+ void invertDisplay(bool i);
+ uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
+
+ // Despite parallel additions, function names kept for compatibility:
+ void spiWrite(uint8_t b); // Write single byte as DATA
+ void writeCommand(uint8_t cmd); // Write single byte as COMMAND
+ uint8_t spiRead(void); // Read single byte of data
+
+ // Most of these low-level functions were formerly macros in
+ // Adafruit_SPITFT_Macros.h. Some have been made into inline functions
+ // to avoid macro mishaps. Despite the addition of code for a parallel
+ // display interface, the names have been kept for backward
+ // compatibility (some subclasses may be invoking these):
+ void SPI_WRITE16(uint16_t w); // Not inline
+ void SPI_WRITE32(uint32_t l); // Not inline
+ // Old code had both a spiWrite16() function and SPI_WRITE16 macro
+ // in addition to the SPI_WRITE32 macro. The latter two have been
+ // made into functions here, and spiWrite16() removed (use SPI_WRITE16()
+ // instead). It looks like most subclasses had gotten comfortable with
+ // SPI_WRITE16 and SPI_WRITE32 anyway so those names were kept rather
+ // than the less-obnoxious camelcase variants, oh well.
+
+ // Placing these functions entirely in the class definition inlines
+ // them implicitly them while allowing their use in other code:
+
+ /*!
+ @brief Set the chip-select line HIGH. Does NOT check whether CS pin
+ is set (>=0), that should be handled in calling function.
+ Despite function name, this is used even if the display
+ connection is parallel.
+ */
+ void SPI_CS_HIGH(void) {
+ #if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(KINETISK)
+ *csPortSet = 1;
+ #else // !KINETISK
+ *csPortSet = csPinMask;
+ #endif // end !KINETISK
+ #else // !HAS_PORT_SET_CLR
+ *csPort |= csPinMaskSet;
+ #endif // end !HAS_PORT_SET_CLR
+ #else // !USE_FAST_PINIO
+ digitalWrite(_cs, HIGH);
+ #endif // end !USE_FAST_PINIO
+ }
+
+ /*!
+ @brief Set the chip-select line LOW. Does NOT check whether CS pin
+ is set (>=0), that should be handled in calling function.
+ Despite function name, this is used even if the display
+ connection is parallel.
+ */
+ void SPI_CS_LOW(void) {
+ #if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(KINETISK)
+ *csPortClr = 1;
+ #else // !KINETISK
+ *csPortClr = csPinMask;
+ #endif // end !KINETISK
+ #else // !HAS_PORT_SET_CLR
+ *csPort &= csPinMaskClr;
+ #endif // end !HAS_PORT_SET_CLR
+ #else // !USE_FAST_PINIO
+ digitalWrite(_cs, LOW);
+ #endif // end !USE_FAST_PINIO
+ }
+
+ /*!
+ @brief Set the data/command line HIGH (data mode).
+ */
+ void SPI_DC_HIGH(void) {
+ #if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(KINETISK)
+ *dcPortSet = 1;
+ #else // !KINETISK
+ *dcPortSet = dcPinMask;
+ #endif // end !KINETISK
+ #else // !HAS_PORT_SET_CLR
+ *dcPort |= dcPinMaskSet;
+ #endif // end !HAS_PORT_SET_CLR
+ #else // !USE_FAST_PINIO
+ digitalWrite(_dc, HIGH);
+ #endif // end !USE_FAST_PINIO
+ }
+
+ /*!
+ @brief Set the data/command line LOW (command mode).
+ */
+ void SPI_DC_LOW(void) {
+ #if defined(USE_FAST_PINIO)
+ #if defined(HAS_PORT_SET_CLR)
+ #if defined(KINETISK)
+ *dcPortClr = 1;
+ #else // !KINETISK
+ *dcPortClr = dcPinMask;
+ #endif // end !KINETISK
+ #else // !HAS_PORT_SET_CLR
+ *dcPort &= dcPinMaskClr;
+ #endif // end !HAS_PORT_SET_CLR
+ #else // !USE_FAST_PINIO
+ digitalWrite(_dc, LOW);
+ #endif // end !USE_FAST_PINIO
+ }
+
+ protected:
+
+ // A few more low-level member functions -- some may have previously
+ // been macros. Shouldn't have a need to access these externally, so
+ // they've been moved to the protected section. Additionally, they're
+ // declared inline here and the code is in the .cpp file, since outside
+ // code doesn't need to see these.
+ inline void SPI_MOSI_HIGH(void);
+ inline void SPI_MOSI_LOW(void);
+ inline void SPI_SCK_HIGH(void);
+ inline void SPI_SCK_LOW(void);
+ inline bool SPI_MISO_READ(void);
+ inline void SPI_BEGIN_TRANSACTION(void);
+ inline void SPI_END_TRANSACTION(void);
+ inline void TFT_WR_STROBE(void); // Parallel interface write strobe
+ inline void TFT_RD_HIGH(void); // Parallel interface read high
+ inline void TFT_RD_LOW(void); // Parallel interface read low
+
+ // CLASS INSTANCE VARIABLES --------------------------------------------
+
+ // Here be dragons! There's a big union of three structures here --
+ // one each for hardware SPI, software (bitbang) SPI, and parallel
+ // interfaces. This is to save some memory, since a display's connection
+ // will be only one of these. The order of some things is a little weird
+ // in an attempt to get values to align and pack better in RAM.
+
+#if defined(USE_FAST_PINIO)
+#if defined(HAS_PORT_SET_CLR)
+ PORTreg_t csPortSet; ///< PORT register for chip select SET
+ PORTreg_t csPortClr; ///< PORT register for chip select CLEAR
+ PORTreg_t dcPortSet; ///< PORT register for data/command SET
+ PORTreg_t dcPortClr; ///< PORT register for data/command CLEAR
+#else // !HAS_PORT_SET_CLR
+ PORTreg_t csPort; ///< PORT register for chip select
+ PORTreg_t dcPort; ///< PORT register for data/command
+#endif // end HAS_PORT_SET_CLR
+#endif // end USE_FAST_PINIO
+#if defined(__cplusplus) && (__cplusplus >= 201100)
+ union {
+#endif
+ struct { // Values specific to HARDWARE SPI:
+ SPIClass *_spi; ///< SPI class pointer
+#if defined(SPI_HAS_TRANSACTION)
+ SPISettings settings; ///< SPI transaction settings
+#else
+ uint32_t _freq; ///< SPI bitrate (if no SPI transactions)
+#endif
+ uint32_t _mode; ///< SPI data mode (transactions or no)
+ } hwspi; ///< Hardware SPI values
+ struct { // Values specific to SOFTWARE SPI:
+#if defined(USE_FAST_PINIO)
+ PORTreg_t misoPort; ///< PORT (PIN) register for MISO
+#if defined(HAS_PORT_SET_CLR)
+ PORTreg_t mosiPortSet; ///< PORT register for MOSI SET
+ PORTreg_t mosiPortClr; ///< PORT register for MOSI CLEAR
+ PORTreg_t sckPortSet; ///< PORT register for SCK SET
+ PORTreg_t sckPortClr; ///< PORT register for SCK CLEAR
+ #if !defined(KINETISK)
+ ADAGFX_PORT_t mosiPinMask; ///< Bitmask for MOSI
+ ADAGFX_PORT_t sckPinMask; ///< Bitmask for SCK
+ #endif // end !KINETISK
+#else // !HAS_PORT_SET_CLR
+ PORTreg_t mosiPort; ///< PORT register for MOSI
+ PORTreg_t sckPort; ///< PORT register for SCK
+ ADAGFX_PORT_t mosiPinMaskSet; ///< Bitmask for MOSI SET (OR)
+ ADAGFX_PORT_t mosiPinMaskClr; ///< Bitmask for MOSI CLEAR (AND)
+ ADAGFX_PORT_t sckPinMaskSet; ///< Bitmask for SCK SET (OR bitmask)
+ ADAGFX_PORT_t sckPinMaskClr; ///< Bitmask for SCK CLEAR (AND)
+#endif // end HAS_PORT_SET_CLR
+ #if !defined(KINETISK)
+ ADAGFX_PORT_t misoPinMask; ///< Bitmask for MISO
+ #endif // end !KINETISK
+#endif // end USE_FAST_PINIO
+ int8_t _mosi; ///< MOSI pin #
+ int8_t _miso; ///< MISO pin #
+ int8_t _sck; ///< SCK pin #
+ } swspi; ///< Software SPI values
+ struct { // Values specific to 8-bit parallel:
+#if defined(USE_FAST_PINIO)
+
+ #if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
+ volatile uint32_t *writePort; ///< PORT register for DATA WRITE
+ volatile uint32_t *readPort; ///< PORT (PIN) register for DATA READ
+ #else
+ volatile uint8_t *writePort; ///< PORT register for DATA WRITE
+ volatile uint8_t *readPort; ///< PORT (PIN) register for DATA READ
+ #endif
+#if defined(HAS_PORT_SET_CLR)
+ // Port direction register pointers are always 8-bit regardless of
+ // PORTreg_t -- even if 32-bit port, we modify a byte-aligned 8 bits.
+ #if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
+ volatile uint32_t *dirSet; ///< PORT byte data direction SET
+ volatile uint32_t *dirClr; ///< PORT byte data direction CLEAR
+ #else
+ volatile uint8_t *dirSet; ///< PORT byte data direction SET
+ volatile uint8_t *dirClr; ///< PORT byte data direction CLEAR
+ #endif
+ PORTreg_t wrPortSet; ///< PORT register for write strobe SET
+ PORTreg_t wrPortClr; ///< PORT register for write strobe CLEAR
+ PORTreg_t rdPortSet; ///< PORT register for read strobe SET
+ PORTreg_t rdPortClr; ///< PORT register for read strobe CLEAR
+ #if !defined(KINETISK)
+ ADAGFX_PORT_t wrPinMask; ///< Bitmask for write strobe
+ #endif // end !KINETISK
+ ADAGFX_PORT_t rdPinMask; ///< Bitmask for read strobe
+#else // !HAS_PORT_SET_CLR
+ // Port direction register pointer is always 8-bit regardless of
+ // PORTreg_t -- even if 32-bit port, we modify a byte-aligned 8 bits.
+ volatile uint8_t *portDir; ///< PORT direction register
+ PORTreg_t wrPort; ///< PORT register for write strobe
+ PORTreg_t rdPort; ///< PORT register for read strobe
+ ADAGFX_PORT_t wrPinMaskSet; ///< Bitmask for write strobe SET (OR)
+ ADAGFX_PORT_t wrPinMaskClr; ///< Bitmask for write strobe CLEAR (AND)
+ ADAGFX_PORT_t rdPinMaskSet; ///< Bitmask for read strobe SET (OR)
+ ADAGFX_PORT_t rdPinMaskClr; ///< Bitmask for read strobe CLEAR (AND)
+#endif // end HAS_PORT_SET_CLR
+#endif // end USE_FAST_PINIO
+ int8_t _d0; ///< Data pin 0 #
+ int8_t _wr; ///< Write strobe pin #
+ int8_t _rd; ///< Read strobe pin # (or -1)
+ bool wide = 0; ///< If true, is 16-bit interface
+ } tft8; ///< Parallel interface settings
+#if defined(__cplusplus) && (__cplusplus >= 201100)
+ }; ///< Only one interface is active
+#endif
+#if defined(USE_SPI_DMA) // Used by hardware SPI and tft8
+ Adafruit_ZeroDMA dma; ///< DMA instance
+ DmacDescriptor *dptr = NULL; ///< 1st descriptor
+ DmacDescriptor *descriptor = NULL; ///< Allocated descriptor list
+ uint16_t *pixelBuf[2]; ///< Working buffers
+ uint16_t maxFillLen; ///< Max pixels per DMA xfer
+ uint16_t lastFillColor = 0; ///< Last color used w/fill
+ uint32_t lastFillLen = 0; ///< # of pixels w/last fill
+ uint8_t onePixelBuf; ///< For hi==lo fill
+#endif
+#if defined(USE_FAST_PINIO)
+#if defined(HAS_PORT_SET_CLR)
+ #if !defined(KINETISK)
+ ADAGFX_PORT_t csPinMask; ///< Bitmask for chip select
+ ADAGFX_PORT_t dcPinMask; ///< Bitmask for data/command
+ #endif // end !KINETISK
+#else // !HAS_PORT_SET_CLR
+ ADAGFX_PORT_t csPinMaskSet; ///< Bitmask for chip select SET (OR)
+ ADAGFX_PORT_t csPinMaskClr; ///< Bitmask for chip select CLEAR (AND)
+ ADAGFX_PORT_t dcPinMaskSet; ///< Bitmask for data/command SET (OR)
+ ADAGFX_PORT_t dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
+#endif // end HAS_PORT_SET_CLR
+#endif // end USE_FAST_PINIO
+ uint8_t connection; ///< TFT_HARD_SPI, TFT_SOFT_SPI, etc.
+ int8_t _rst; ///< Reset pin # (or -1)
+ int8_t _cs; ///< Chip select pin # (or -1)
+ int8_t _dc; ///< Data/command pin #
+
+ int16_t _xstart = 0; ///< Internal framebuffer X offset
+ int16_t _ystart = 0; ///< Internal framebuffer Y offset
+ uint8_t invertOnCommand = 0; ///< Command to enable invert mode
+ uint8_t invertOffCommand = 0; ///< Command to disable invert mode
+
+ uint32_t _freq = 0; ///< Dummy var to keep subclasses happy
+};
+
+#endif // end __AVR_ATtiny85__
+#endif // end _ADAFRUIT_SPITFT_H_
diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h
new file mode 100644
index 000000000..fcd6253e6
--- /dev/null
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h
@@ -0,0 +1,6 @@
+// THIS FILE INTENTIONALLY LEFT BLANK.
+
+// Macros previously #defined here have been made into (mostly) inline
+// functions in the Adafruit_SPITFT class. Other libraries might still
+// contain code trying to #include this header file, so until everything's
+// updated this file still exists (but doing nothing) to avoid trouble.
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMono12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMono12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMono18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMono18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMono24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMono24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMono9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMono9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBold12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBold12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBold18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBold18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBold24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBold24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBold9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBold9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBoldOblique12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBoldOblique12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBoldOblique18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBoldOblique18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBoldOblique24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBoldOblique24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBoldOblique9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoBoldOblique9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoOblique12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoOblique12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoOblique18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoOblique18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoOblique24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoOblique24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoOblique9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeMonoOblique9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSans12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSans12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSans18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSans18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSans24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSans24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSans9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSans9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBold12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBold12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBold18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBold18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBold24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBold24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBold9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBold9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBoldOblique12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBoldOblique12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBoldOblique18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBoldOblique18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBoldOblique24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBoldOblique24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBoldOblique9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansBoldOblique9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansOblique12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansOblique12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansOblique18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansOblique18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansOblique24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansOblique24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansOblique9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSansOblique9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerif12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerif12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerif18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerif18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerif24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerif24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerif9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerif9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBold12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBold12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBold18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBold18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBold24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBold24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBold9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBold9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBoldItalic12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBoldItalic12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBoldItalic18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBoldItalic18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBoldItalic24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBoldItalic24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBoldItalic9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifBoldItalic9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifItalic12pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifItalic12pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifItalic18pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifItalic18pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifItalic24pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifItalic24pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifItalic9pt7b.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/FreeSerifItalic9pt7b.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/Org_01.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/Org_01.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/Picopixel.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/Picopixel.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/Tiny3x3a2pt7b b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/Tiny3x3a2pt7b
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/Fonts/TomThumb.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/Fonts/TomThumb.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/README.md b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md
similarity index 94%
rename from lib/Adafruit-GFX-Library-1.2.9/README.md
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md
index cd27c33b6..37751c734 100644
--- a/lib/Adafruit-GFX-Library-1.2.9/README.md
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md
@@ -1,4 +1,4 @@
-# Adafruit GFX Library # [](https://travis-ci.org/adafruit/Adafruit_GFX)
+# Adafruit GFX Library [](https://travis-ci.com/adafruit/Adafruit-GFX-Library)
This is the core graphics library for all our displays, providing a common set of graphics primitives (points, lines, circles, etc.). It needs to be paired with a hardware-specific library for each display device we carry (to handle the lower-level functions).
diff --git a/lib/Adafruit-GFX-Library-1.2.9/examples/mock_ili9341/mock_ili9341.ino b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino
similarity index 99%
rename from lib/Adafruit-GFX-Library-1.2.9/examples/mock_ili9341/mock_ili9341.ino
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino
index 3154d4095..d14183904 100644
--- a/lib/Adafruit-GFX-Library-1.2.9/examples/mock_ili9341/mock_ili9341.ino
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino
@@ -362,4 +362,4 @@ unsigned long testFilledRoundRects() {
}
return micros() - start;
-}
\ No newline at end of file
+}
diff --git a/lib/Adafruit-GFX-Library-1.2.9/fontconvert/Makefile b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/fontconvert/Makefile
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile
diff --git a/lib/Adafruit-GFX-Library-1.2.9/fontconvert/fontconvert.c b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c
similarity index 94%
rename from lib/Adafruit-GFX-Library-1.2.9/fontconvert/fontconvert.c
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c
index bfd21103c..b8a6ac944 100644
--- a/lib/Adafruit-GFX-Library-1.2.9/fontconvert/fontconvert.c
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c
@@ -16,12 +16,14 @@ Keep 7-bit fonts around as an option in that case, more compact.
See notes at end for glyph nomenclature & other tidbits.
*/
+#ifndef ARDUINO
#include
#include
#include
#include
#include FT_GLYPH_H
+#include FT_TRUETYPE_DRIVER_H
#include "../gfxfont.h" // Adafruit_GFX font structures
#define DPI 141 // Approximate res. of Adafruit 2.8" TFT
@@ -116,6 +118,16 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "FreeType init error: %d", err);
return err;
}
+
+ // Use TrueType engine version 35, without subpixel rendering.
+ // This improves clarity of fonts since this library does not
+ // support rendering multiple levels of gray in a glyph.
+ // See https://github.com/adafruit/Adafruit-GFX-Library/issues/103
+ FT_UInt interpreter_version = TT_INTERPRETER_VERSION_35;
+ FT_Property_Set( library, "truetype",
+ "interpreter-version",
+ &interpreter_version );
+
if((err = FT_New_Face(library, argv[1], 0, &face))) {
fprintf(stderr, "Font load error: %d", err);
FT_Done_FreeType(library);
@@ -282,3 +294,5 @@ the cursor on the X axis after drawing the corresponding symbol.
There's also some changes with regard to 'background' color and new GFX
fonts (classic fonts unchanged). See Adafruit_GFX.cpp for explanation.
*/
+
+#endif /* !ARDUINO */
diff --git a/lib/Adafruit-GFX-Library-1.2.9/fontconvert/fontconvert_win.md b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/fontconvert/fontconvert_win.md
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md
diff --git a/lib/Adafruit-GFX-Library-1.2.9/fontconvert/makefonts.sh b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/fontconvert/makefonts.sh
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh
diff --git a/lib/Adafruit-GFX-Library-1.2.9/gfxfont.h b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/gfxfont.h
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h
diff --git a/lib/Adafruit-GFX-Library-1.2.9/glcdfont.c b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c
similarity index 98%
rename from lib/Adafruit-GFX-Library-1.2.9/glcdfont.c
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c
index 6f88bd23a..50245933c 100644
--- a/lib/Adafruit-GFX-Library-1.2.9/glcdfont.c
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c
@@ -9,6 +9,10 @@
#include
#elif defined(ESP8266)
#include
+#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
+// PROGMEM is defefind for T4 to place data in specific memory section
+ #undef PROGMEM
+ #define PROGMEM
#else
#define PROGMEM
#endif
diff --git a/lib/Adafruit-GFX-Library-1.2.9/library.properties b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties
similarity index 96%
rename from lib/Adafruit-GFX-Library-1.2.9/library.properties
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties
index eea478015..78bbdbafa 100644
--- a/lib/Adafruit-GFX-Library-1.2.9/library.properties
+++ b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties
@@ -1,5 +1,5 @@
name=Adafruit GFX Library
-version=1.2.9
+version=1.5.6
author=Adafruit
maintainer=Adafruit
sentence=Adafruit GFX graphics core library, this is the 'core' class that all our other graphics libraries derive from.
diff --git a/lib/Adafruit-GFX-Library-1.2.9/license.txt b/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt
similarity index 100%
rename from lib/Adafruit-GFX-Library-1.2.9/license.txt
rename to lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt
diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp b/lib/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp
new file mode 100644
index 000000000..984e5572a
--- /dev/null
+++ b/lib/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp
@@ -0,0 +1,286 @@
+/***************************************************
+ This is a library for the Adafruit PT100/P1000 RTD Sensor w/MAX31865
+
+ Designed specifically to work with the Adafruit RTD Sensor
+ ----> https://www.adafruit.com/products/3328
+
+ This sensor uses SPI to communicate, 4 pins are required to
+ interface
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries.
+ BSD license, all text above must be included in any redistribution
+ ****************************************************/
+
+#include "Adafruit_MAX31865.h"
+#ifdef __AVR
+ #include
+#elif defined(ESP8266)
+ #include
+#endif
+
+#include
+#include
+
+static SPISettings max31865_spisettings = SPISettings(500000, MSBFIRST, SPI_MODE1);
+
+
+
+// Software (bitbang) SPI
+Adafruit_MAX31865::Adafruit_MAX31865(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso, int8_t spi_clk) {
+ setPins( spi_cs, spi_mosi, spi_miso, spi_clk);
+}
+
+void Adafruit_MAX31865::setPins(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso, int8_t spi_clk) {
+ _sclk = spi_clk;
+ _cs = spi_cs;
+ _miso = spi_miso;
+ _mosi = spi_mosi;
+}
+
+// Hardware SPI init
+Adafruit_MAX31865::Adafruit_MAX31865(int8_t spi_cs) {
+ _cs = spi_cs;
+ _sclk = _miso = _mosi = -1;
+}
+
+// Default constructor
+Adafruit_MAX31865::Adafruit_MAX31865(void) {
+ _cs = _sclk = _miso = _mosi = -1;
+}
+
+boolean Adafruit_MAX31865::begin(max31865_numwires_t wires) {
+ pinMode(_cs, OUTPUT);
+ digitalWrite(_cs, HIGH);
+
+ if (_sclk != -1) {
+ //define pin modes
+ pinMode(_sclk, OUTPUT);
+ digitalWrite(_sclk, LOW);
+ pinMode(_mosi, OUTPUT);
+ pinMode(_miso, INPUT);
+ } else {
+ //start and configure hardware SPI
+ SPI.begin();
+ }
+
+ for (uint8_t i=0; i<16; i++) {
+ // readRegister8(i);
+ }
+
+ setWires(wires);
+ enableBias(false);
+ autoConvert(false);
+ clearFault();
+
+ //Serial.print("config: "); Serial.println(readRegister8(MAX31856_CONFIG_REG), HEX);
+ return true;
+}
+
+
+uint8_t Adafruit_MAX31865::readFault(void) {
+ return readRegister8(MAX31856_FAULTSTAT_REG);
+}
+
+void Adafruit_MAX31865::clearFault(void) {
+ uint8_t t = readRegister8(MAX31856_CONFIG_REG);
+ t &= ~0x2C;
+ t |= MAX31856_CONFIG_FAULTSTAT;
+ writeRegister8(MAX31856_CONFIG_REG, t);
+}
+
+void Adafruit_MAX31865::enableBias(boolean b) {
+ uint8_t t = readRegister8(MAX31856_CONFIG_REG);
+ if (b) {
+ t |= MAX31856_CONFIG_BIAS; // enable bias
+ } else {
+ t &= ~MAX31856_CONFIG_BIAS; // disable bias
+ }
+ writeRegister8(MAX31856_CONFIG_REG, t);
+}
+
+void Adafruit_MAX31865::autoConvert(boolean b) {
+ uint8_t t = readRegister8(MAX31856_CONFIG_REG);
+ if (b) {
+ t |= MAX31856_CONFIG_MODEAUTO; // enable autoconvert
+ } else {
+ t &= ~MAX31856_CONFIG_MODEAUTO; // disable autoconvert
+ }
+ writeRegister8(MAX31856_CONFIG_REG, t);
+}
+
+void Adafruit_MAX31865::setWires(max31865_numwires_t wires ) {
+ uint8_t t = readRegister8(MAX31856_CONFIG_REG);
+ if (wires == MAX31865_3WIRE) {
+ t |= MAX31856_CONFIG_3WIRE;
+ } else {
+ // 2 or 4 wire
+ t &= ~MAX31856_CONFIG_3WIRE;
+ }
+ writeRegister8(MAX31856_CONFIG_REG, t);
+}
+
+float Adafruit_MAX31865::rtd_to_temperature(uint16_t rtd, float RTDnominal, float refResistor) {
+//float Adafruit_MAX31865::temperature(float RTDnominal, float refResistor) {
+ // http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
+
+ float Z1, Z2, Z3, Z4, Rt, temp;
+
+ Rt = rtd;
+ Rt /= 32768;
+ Rt *= refResistor;
+
+ // Serial.print("\nResistance: "); Serial.println(Rt, 8);
+
+ Z1 = -RTD_A;
+ Z2 = RTD_A * RTD_A - (4 * RTD_B);
+ Z3 = (4 * RTD_B) / RTDnominal;
+ Z4 = 2 * RTD_B;
+
+ temp = Z2 + (Z3 * Rt);
+ temp = (sqrt(temp) + Z1) / Z4;
+
+ if (temp >= 0) return temp;
+
+ // ugh.
+ Rt /= RTDnominal;
+ Rt *= 100; // normalize to 100 ohm
+
+ float rpoly = Rt;
+
+ temp = -242.02;
+ temp += 2.2228 * rpoly;
+ rpoly *= Rt; // square
+ temp += 2.5859e-3 * rpoly;
+ rpoly *= Rt; // ^3
+ temp -= 4.8260e-6 * rpoly;
+ rpoly *= Rt; // ^4
+ temp -= 2.8183e-8 * rpoly;
+ rpoly *= Rt; // ^5
+ temp += 1.5243e-10 * rpoly;
+
+ return temp;
+}
+
+float Adafruit_MAX31865::rtd_to_resistance(uint16_t rtd, float refResistor) {
+ float Rt;
+
+ Rt = rtd;
+ Rt /= 32768;
+ Rt *= refResistor;
+
+ return Rt;
+}
+
+float Adafruit_MAX31865::temperature(float RTDnominal, float refResistor) {
+ uint16_t rtd = readRTD();
+ return rtd_to_temperature(rtd, RTDnominal, refResistor);
+}
+
+uint16_t Adafruit_MAX31865::readRTD (void) {
+ clearFault();
+ enableBias(true);
+ delay(10);
+ uint8_t t = readRegister8(MAX31856_CONFIG_REG);
+ t |= MAX31856_CONFIG_1SHOT;
+ writeRegister8(MAX31856_CONFIG_REG, t);
+ delay(65);
+
+ uint16_t rtd = readRegister16(MAX31856_RTDMSB_REG);
+
+ // remove fault
+ rtd >>= 1;
+
+ return rtd;
+}
+
+/**********************************************/
+
+uint8_t Adafruit_MAX31865::readRegister8(uint8_t addr) {
+ uint8_t ret = 0;
+ readRegisterN(addr, &ret, 1);
+
+ return ret;
+}
+
+uint16_t Adafruit_MAX31865::readRegister16(uint8_t addr) {
+ uint8_t buffer[2] = {0, 0};
+ readRegisterN(addr, buffer, 2);
+
+ uint16_t ret = buffer[0];
+ ret <<= 8;
+ ret |= buffer[1];
+
+ return ret;
+}
+
+
+void Adafruit_MAX31865::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
+ addr &= 0x7F; // make sure top bit is not set
+
+ if (_sclk == -1)
+ SPI.beginTransaction(max31865_spisettings);
+ else
+ digitalWrite(_sclk, LOW);
+
+ digitalWrite(_cs, LOW);
+
+ spixfer(addr);
+
+ //Serial.print("$"); Serial.print(addr, HEX); Serial.print(": ");
+ while (n--) {
+ buffer[0] = spixfer(0xFF);
+ //Serial.print(" 0x"); Serial.print(buffer[0], HEX);
+ buffer++;
+ }
+ //Serial.println();
+
+ if (_sclk == -1)
+ SPI.endTransaction();
+
+ digitalWrite(_cs, HIGH);
+}
+
+
+void Adafruit_MAX31865::writeRegister8(uint8_t addr, uint8_t data) {
+ if (_sclk == -1)
+ SPI.beginTransaction(max31865_spisettings);
+ else
+ digitalWrite(_sclk, LOW);
+
+ digitalWrite(_cs, LOW);
+
+ spixfer(addr | 0x80); // make sure top bit is set
+ spixfer(data);
+
+ //Serial.print("$"); Serial.print(addr, HEX); Serial.print(" = 0x"); Serial.println(data, HEX);
+
+ if (_sclk == -1)
+ SPI.endTransaction();
+
+ digitalWrite(_cs, HIGH);
+}
+
+
+
+uint8_t Adafruit_MAX31865::spixfer(uint8_t x) {
+ if (_sclk == -1)
+ return SPI.transfer(x);
+
+ // software spi
+ //Serial.println("Software SPI");
+ uint8_t reply = 0;
+
+ for (int i=7; i>=0; i--) {
+ reply <<= 1;
+ digitalWrite(_sclk, HIGH);
+ digitalWrite(_mosi, x & (1< https://www.adafruit.com/products/3328
+
+ This sensor uses SPI to communicate, 4 pins are required to
+ interface
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries.
+ BSD license, all text above must be included in any redistribution
+ ****************************************************/
+
+#ifndef ADAFRUIT_MAX31865_H
+#define ADAFRUIT_MAX31865_H
+
+#define MAX31856_CONFIG_REG 0x00
+#define MAX31856_CONFIG_BIAS 0x80
+#define MAX31856_CONFIG_MODEAUTO 0x40
+#define MAX31856_CONFIG_MODEOFF 0x00
+#define MAX31856_CONFIG_1SHOT 0x20
+#define MAX31856_CONFIG_3WIRE 0x10
+#define MAX31856_CONFIG_24WIRE 0x00
+#define MAX31856_CONFIG_FAULTSTAT 0x02
+#define MAX31856_CONFIG_FILT50HZ 0x01
+#define MAX31856_CONFIG_FILT60HZ 0x00
+
+#define MAX31856_RTDMSB_REG 0x01
+#define MAX31856_RTDLSB_REG 0x02
+#define MAX31856_HFAULTMSB_REG 0x03
+#define MAX31856_HFAULTLSB_REG 0x04
+#define MAX31856_LFAULTMSB_REG 0x05
+#define MAX31856_LFAULTLSB_REG 0x06
+#define MAX31856_FAULTSTAT_REG 0x07
+
+
+#define MAX31865_FAULT_HIGHTHRESH 0x80
+#define MAX31865_FAULT_LOWTHRESH 0x40
+#define MAX31865_FAULT_REFINLOW 0x20
+#define MAX31865_FAULT_REFINHIGH 0x10
+#define MAX31865_FAULT_RTDINLOW 0x08
+#define MAX31865_FAULT_OVUV 0x04
+
+
+#define RTD_A 3.9083e-3
+#define RTD_B -5.775e-7
+
+#if (ARDUINO >= 100)
+ #include "Arduino.h"
+#else
+ #include "WProgram.h"
+#endif
+
+typedef enum max31865_numwires {
+ MAX31865_2WIRE = 0,
+ MAX31865_3WIRE = 1,
+ MAX31865_4WIRE = 0
+} max31865_numwires_t;
+
+
+class Adafruit_MAX31865 {
+ public:
+ Adafruit_MAX31865(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso, int8_t spi_clk);
+ Adafruit_MAX31865(int8_t spi_cs);
+ Adafruit_MAX31865(void);
+
+ void setPins(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso, int8_t spi_clk);
+ boolean begin(max31865_numwires_t x = MAX31865_2WIRE);
+
+ uint8_t readFault(void);
+ void clearFault(void);
+ uint16_t readRTD();
+
+
+ void setWires(max31865_numwires_t wires);
+ void autoConvert(boolean b);
+ void enableBias(boolean b);
+
+ float temperature(float RTDnominal, float refResistor);
+ float rtd_to_temperature(uint16_t rtd, float RTDnominal, float refResistor);
+ float rtd_to_resistance(uint16_t rtd, float refResistor);
+
+ private:
+ int8_t _sclk, _miso, _mosi, _cs;
+
+ void readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n);
+
+ uint8_t readRegister8(uint8_t addr);
+ uint16_t readRegister16(uint8_t addr);
+
+ void writeRegister8(uint8_t addr, uint8_t reg);
+ uint8_t spixfer(uint8_t addr);
+};
+
+
+#endif
diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/README.md b/lib/Adafruit_MAX31865-1.1.0-custom/README.md
new file mode 100644
index 000000000..d3b9d2369
--- /dev/null
+++ b/lib/Adafruit_MAX31865-1.1.0-custom/README.md
@@ -0,0 +1,2 @@
+# Adafruit_MAX31865
+Arduino Library for Adafruit MAX31865 RTD Sensor
diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/README.txt b/lib/Adafruit_MAX31865-1.1.0-custom/README.txt
new file mode 100644
index 000000000..edace57fd
--- /dev/null
+++ b/lib/Adafruit_MAX31865-1.1.0-custom/README.txt
@@ -0,0 +1,16 @@
+This is the Adafruit MAX31856 Arduino Library
+
+Tested and works great with the Adafruit Thermocouple Breakout w/MAX31856
+
+ * http://www.adafruit.com/products/3328
+
+These sensors use SPI to communicate, 4 pins are required to
+interface
+
+Adafruit invests time and resources providing this open source code,
+please support Adafruit and open-source hardware by purchasing
+products from Adafruit!
+
+Written by Limor Fried/Ladyada for Adafruit Industries.
+BSD license, check license.txt for more information
+All text above must be included in any redistribution
\ No newline at end of file
diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino b/lib/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino
new file mode 100644
index 000000000..5fc872f54
--- /dev/null
+++ b/lib/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino
@@ -0,0 +1,74 @@
+/***************************************************
+ This is a library for the Adafruit PT100/P1000 RTD Sensor w/MAX31865
+
+ Designed specifically to work with the Adafruit RTD Sensor
+ ----> https://www.adafruit.com/products/3328
+
+ This sensor uses SPI to communicate, 4 pins are required to
+ interface
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries.
+ BSD license, all text above must be included in any redistribution
+ ****************************************************/
+
+#include
+
+// Use software SPI: CS, DI, DO, CLK
+Adafruit_MAX31865 max = Adafruit_MAX31865(10, 11, 12, 13);
+// use hardware SPI, just pass in the CS pin
+//Adafruit_MAX31865 max = Adafruit_MAX31865(10);
+
+// The value of the Rref resistor. Use 430.0 for PT100 and 4300.0 for PT1000
+#define RREF 430.0
+// The 'nominal' 0-degrees-C resistance of the sensor
+// 100.0 for PT100, 1000.0 for PT1000
+#define RNOMINAL 100.0
+
+void setup() {
+ Serial.begin(115200);
+ Serial.println("Adafruit MAX31865 PT100 Sensor Test!");
+
+ max.begin(MAX31865_3WIRE); // set to 2WIRE or 4WIRE as necessary
+}
+
+
+void loop() {
+ uint16_t rtd = max.readRTD();
+
+ Serial.print("RTD value: "); Serial.println(rtd);
+ float ratio = rtd;
+ ratio /= 32768;
+ Serial.print("Ratio = "); Serial.println(ratio,8);
+ Serial.print("Resistance = "); Serial.println(RREF*ratio,8);
+ Serial.print("Temperature = "); Serial.println(max.temperature(RNOMINAL, RREF));
+
+ // Check and print any faults
+ uint8_t fault = max.readFault();
+ if (fault) {
+ Serial.print("Fault 0x"); Serial.println(fault, HEX);
+ if (fault & MAX31865_FAULT_HIGHTHRESH) {
+ Serial.println("RTD High Threshold");
+ }
+ if (fault & MAX31865_FAULT_LOWTHRESH) {
+ Serial.println("RTD Low Threshold");
+ }
+ if (fault & MAX31865_FAULT_REFINLOW) {
+ Serial.println("REFIN- > 0.85 x Bias");
+ }
+ if (fault & MAX31865_FAULT_REFINHIGH) {
+ Serial.println("REFIN- < 0.85 x Bias - FORCE- open");
+ }
+ if (fault & MAX31865_FAULT_RTDINLOW) {
+ Serial.println("RTDIN- < 0.85 x Bias - FORCE- open");
+ }
+ if (fault & MAX31865_FAULT_OVUV) {
+ Serial.println("Under/Over voltage");
+ }
+ max.clearFault();
+ }
+ Serial.println();
+ delay(1000);
+}
diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/library.properties b/lib/Adafruit_MAX31865-1.1.0-custom/library.properties
new file mode 100644
index 000000000..f132a890a
--- /dev/null
+++ b/lib/Adafruit_MAX31865-1.1.0-custom/library.properties
@@ -0,0 +1,9 @@
+name=Adafruit MAX31865 library
+version=1.0.1
+author=Adafruit
+maintainer=Adafruit
+sentence=Library for the Adafruit RTD Amplifier breakout with MAX31865
+paragraph=Library for the Adafruit RTD Amplifier breakout with MAX31865
+category=Sensors
+url=https://github.com/adafruit/Adafruit_MAX31865
+architectures=*
diff --git a/lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp b/lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp
new file mode 100644
index 000000000..fac803b53
--- /dev/null
+++ b/lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp
@@ -0,0 +1,291 @@
+/*********************************************************************
+This is a library for our Monochrome OLEDs based on SSD1306 drivers
+
+ Pick one up today in the adafruit shop!
+ ------> http://www.adafruit.com/category/63_98
+
+These displays use SPI to communicate, 4 or 5 pins are required to
+interface
+
+Adafruit invests time and resources providing this open source code,
+please support Adafruit and open-source hardware by purchasing
+products from Adafruit!
+
+Written by Limor Fried/Ladyada for Adafruit Industries.
+BSD license, check license.txt for more information
+All text above, and the splash screen below must be included in any redistribution
+*********************************************************************/
+
+/*********************************************************************
+I change the adafruit SSD1306 to SH1106
+
+SH1106 driver similar to SSD1306 so, just change the display() method.
+
+However, SH1106 driver don't provide several functions such as scroll commands.
+
+
+*********************************************************************/
+
+//#include
+#ifndef __SAM3X8E__
+// #include
+#endif
+#include
+#include
+//#include <../../sonoff/settings.h>
+
+#include "Adafruit_SH1106.h"
+#define DISPLAY_INIT_MODE 0
+
+// the memory buffer for the LCD
+extern uint8_t *buffer;
+
+Adafruit_SH1106::Adafruit_SH1106(int16_t width, int16_t height) :
+Renderer(width,height) {
+}
+
+void Adafruit_SH1106::DisplayOnff(int8_t on) {
+ if (on) {
+ SH1106_command(SH1106_DISPLAYON);
+ } else {
+ SH1106_command(SH1106_DISPLAYOFF);
+ }
+}
+
+void Adafruit_SH1106::Updateframe() {
+ display();
+}
+
+void Adafruit_SH1106::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
+// ignore update mode
+ //if (p==DISPLAY_INIT_MODE) {
+ setRotation(rot);
+ invertDisplay(false);
+ setTextWrap(false); // Allow text to run off edges
+ cp437(true);
+ setTextFont(font);
+ setTextSize(size);
+ setTextColor(WHITE,BLACK);
+ setCursor(0,0);
+ fillScreen(BLACK);
+ Updateframe();
+ //}
+}
+
+int16_t Adafruit_SH1106::Begin(int16_t p1,int16_t p2,int16_t p3) {
+ begin(p1,p2,p3);
+}
+
+
+void Adafruit_SH1106::begin(uint8_t vccstate, uint8_t i2caddr, bool reset) {
+ _vccstate = vccstate;
+ _i2caddr = i2caddr;
+ // I2C Init
+ Wire.begin();
+
+ #if defined SH1106_128_32
+ // Init sequence for 128x32 OLED module
+ SH1106_command(SH1106_DISPLAYOFF); // 0xAE
+ SH1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
+ SH1106_command(0x80); // the suggested ratio 0x80
+ SH1106_command(SH1106_SETMULTIPLEX); // 0xA8
+ SH1106_command(0x1F);
+ SH1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
+ SH1106_command(0x0); // no offset
+ SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
+ SH1106_command(SH1106_CHARGEPUMP); // 0x8D
+ if (vccstate == SH1106_EXTERNALVCC)
+ { SH1106_command(0x10); }
+ else
+ { SH1106_command(0x14); }
+ SH1106_command(SH1106_MEMORYMODE); // 0x20
+ SH1106_command(0x00); // 0x0 act like ks0108
+ SH1106_command(SH1106_SEGREMAP | 0x1);
+ SH1106_command(SH1106_COMSCANDEC);
+ SH1106_command(SH1106_SETCOMPINS); // 0xDA
+ SH1106_command(0x02);
+ SH1106_command(SH1106_SETCONTRAST); // 0x81
+ SH1106_command(0x8F);
+ SH1106_command(SH1106_SETPRECHARGE); // 0xd9
+ if (vccstate == SH1106_EXTERNALVCC)
+ { SH1106_command(0x22); }
+ else
+ { SH1106_command(0xF1); }
+ SH1106_command(SH1106_SETVCOMDETECT); // 0xDB
+ SH1106_command(0x40);
+ SH1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
+ SH1106_command(SH1106_NORMALDISPLAY); // 0xA6
+ #endif
+
+ #if defined SH1106_128_64
+ // Init sequence for 128x64 OLED module
+ SH1106_command(SH1106_DISPLAYOFF); // 0xAE
+ SH1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
+ SH1106_command(0x80); // the suggested ratio 0x80
+ SH1106_command(SH1106_SETMULTIPLEX); // 0xA8
+ SH1106_command(0x3F);
+ SH1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
+ SH1106_command(0x00); // no offset
+
+ SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0 0x40
+ SH1106_command(SH1106_CHARGEPUMP); // 0x8D
+ if (vccstate == SH1106_EXTERNALVCC)
+ { SH1106_command(0x10); }
+ else
+ { SH1106_command(0x14); }
+ SH1106_command(SH1106_MEMORYMODE); // 0x20
+ SH1106_command(0x00); // 0x0 act like ks0108
+ SH1106_command(SH1106_SEGREMAP | 0x1);
+ SH1106_command(SH1106_COMSCANDEC);
+ SH1106_command(SH1106_SETCOMPINS); // 0xDA
+ SH1106_command(0x12);
+ SH1106_command(SH1106_SETCONTRAST); // 0x81
+ if (vccstate == SH1106_EXTERNALVCC)
+ { SH1106_command(0x9F); }
+ else
+ { SH1106_command(0xCF); }
+ SH1106_command(SH1106_SETPRECHARGE); // 0xd9
+ if (vccstate == SH1106_EXTERNALVCC)
+ { SH1106_command(0x22); }
+ else
+ { SH1106_command(0xF1); }
+ SH1106_command(SH1106_SETVCOMDETECT); // 0xDB
+ SH1106_command(0x40);
+ SH1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
+ SH1106_command(SH1106_NORMALDISPLAY); // 0xA6
+ #endif
+
+ #if defined SH1106_96_16
+ // Init sequence for 96x16 OLED module
+ SH1106_command(SH1106_DISPLAYOFF); // 0xAE
+ SH1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
+ SH1106_command(0x80); // the suggested ratio 0x80
+ SH1106_command(SH1106_SETMULTIPLEX); // 0xA8
+ SH1106_command(0x0F);
+ SH1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
+ SH1106_command(0x00); // no offset
+ SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
+ SH1106_command(SH1106_CHARGEPUMP); // 0x8D
+ if (vccstate == SH1106_EXTERNALVCC)
+ { SH1106_command(0x10); }
+ else
+ { SH1106_command(0x14); }
+ SH1106_command(SH1106_MEMORYMODE); // 0x20
+ SH1106_command(0x00); // 0x0 act like ks0108
+ SH1106_command(SH1106_SEGREMAP | 0x1);
+ SH1106_command(SH1106_COMSCANDEC);
+ SH1106_command(SH1106_SETCOMPINS); // 0xDA
+ SH1106_command(0x2); //ada x12
+ SH1106_command(SH1106_SETCONTRAST); // 0x81
+ if (vccstate == SH1106_EXTERNALVCC)
+ { SH1106_command(0x10); }
+ else
+ { SH1106_command(0xAF); }
+ SH1106_command(SH1106_SETPRECHARGE); // 0xd9
+ if (vccstate == SH1106_EXTERNALVCC)
+ { SH1106_command(0x22); }
+ else
+ { SH1106_command(0xF1); }
+ SH1106_command(SH1106_SETVCOMDETECT); // 0xDB
+ SH1106_command(0x40);
+ SH1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
+ SH1106_command(SH1106_NORMALDISPLAY); // 0xA6
+ #endif
+
+ SH1106_command(SH1106_DISPLAYON);//--turn on oled panel
+}
+
+
+void Adafruit_SH1106::invertDisplay(uint8_t i) {
+ if (i) {
+ SH1106_command(SH1106_INVERTDISPLAY);
+ } else {
+ SH1106_command(SH1106_NORMALDISPLAY);
+ }
+}
+
+void Adafruit_SH1106::SH1106_command(uint8_t c) {
+
+ // I2C
+ uint8_t control = 0x00; // Co = 0, D/C = 0
+ Wire.beginTransmission(_i2caddr);
+ WIRE_WRITE(control);
+ WIRE_WRITE(c);
+ Wire.endTransmission();
+
+}
+
+// Dim the display
+// dim = true: display is dimmed
+// dim = false: display is normal
+void Adafruit_SH1106::dim(uint8_t dim) {
+ uint8_t contrast;
+
+ if (dim) {
+ contrast = 0; // Dimmed display
+ } else {
+ if (_vccstate == SH1106_EXTERNALVCC) {
+ contrast = 0x9F;
+ } else {
+ contrast = 0xCF;
+ }
+ }
+ // the range of contrast to too small to be really useful
+ // it is useful to dim the display
+ SH1106_command(SH1106_SETCONTRAST);
+ SH1106_command(contrast);
+}
+
+void Adafruit_SH1106::SH1106_data(uint8_t c) {
+ // I2C
+ uint8_t control = 0x40; // Co = 0, D/C = 1
+ Wire.beginTransmission(_i2caddr);
+ WIRE_WRITE(control);
+ WIRE_WRITE(c);
+ Wire.endTransmission();
+}
+
+void Adafruit_SH1106::display(void) {
+ SH1106_command(SH1106_SETLOWCOLUMN | 0x0); // low col = 0
+ SH1106_command(SH1106_SETHIGHCOLUMN | 0x0); // hi col = 0
+ SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
+ // I2C
+ //height >>= 3;
+ //width >>= 3;
+ byte height=64;
+ byte width=132;
+ byte m_row = 0;
+ byte m_col = 2;
+
+
+ height >>= 3;
+ width >>= 3;
+ //Serial.println(width);
+
+ int p = 0;
+
+ byte i, j, k =0;
+
+ for ( i = 0; i < height; i++) {
+
+ // send a bunch of data in one xmission
+ SH1106_command(0xB0 + i + m_row);//set page address
+ SH1106_command(m_col & 0xf);//set lower column address
+ SH1106_command(0x10 | (m_col >> 4));//set higher column address
+
+ for( j = 0; j < 8; j++){
+ Wire.beginTransmission(_i2caddr);
+ Wire.write(0x40);
+ for ( k = 0; k < width; k++, p++) {
+ Wire.write(buffer[p]);
+ }
+ Wire.endTransmission();
+ }
+ }
+
+}
+
+// clear everything
+void Adafruit_SH1106::clearDisplay(void) {
+ memset(buffer, 0, (SH1106_LCDWIDTH*SH1106_LCDHEIGHT/8));
+}
diff --git a/lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h b/lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h
new file mode 100644
index 000000000..b0562629b
--- /dev/null
+++ b/lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h
@@ -0,0 +1,154 @@
+/*********************************************************************
+This is a library for our Monochrome OLEDs based on SSD1306 drivers
+
+ Pick one up today in the adafruit shop!
+ ------> http://www.adafruit.com/category/63_98
+
+These displays use SPI to communicate, 4 or 5 pins are required to
+interface
+
+Adafruit invests time and resources providing this open source code,
+please support Adafruit and open-source hardware by purchasing
+products from Adafruit!
+
+Written by Limor Fried/Ladyada for Adafruit Industries.
+BSD license, check license.txt for more information
+All text above, and the splash screen must be included in any redistribution
+*********************************************************************/
+
+/*********************************************************************
+I change the adafruit SSD1306 to SH1106
+
+SH1106 driver similar to SSD1306 so, just change the display() method.
+
+However, SH1106 driver don't provide several functions such as scroll commands.
+
+
+*********************************************************************/
+
+#if ARDUINO >= 100
+ #include "Arduino.h"
+ #define WIRE_WRITE Wire.write
+#else
+ #include "WProgram.h"
+ #define WIRE_WRITE Wire.send
+#endif
+
+#include
+
+#define BLACK 0
+#define WHITE 1
+#define INVERSE 2
+
+#define SH1106_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D
+// Address for 128x32 is 0x3C
+// Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded)
+
+/*=========================================================================
+ SH1106 Displays
+ -----------------------------------------------------------------------
+ The driver is used in multiple displays (128x64, 128x32, etc.).
+ Select the appropriate display below to create an appropriately
+ sized framebuffer, etc.
+
+ SH1106_128_64 128x64 pixel display
+
+ SH1106_128_32 128x32 pixel display
+
+ SH1106_96_16
+
+ -----------------------------------------------------------------------*/
+ #define SH1106_128_64
+// #define SH1106_128_32
+// #define SH1106_96_16
+/*=========================================================================*/
+
+#if defined SH1106_128_64 && defined SH1106_128_32
+ #error "Only one SH1106 display can be specified at once in SH1106.h"
+#endif
+#if !defined SH1106_128_64 && !defined SH1106_128_32 && !defined SH1106_96_16
+ #error "At least one SH1106 display must be specified in SH1106.h"
+#endif
+
+#if defined SH1106_128_64
+ #define SH1106_LCDWIDTH 128
+ #define SH1106_LCDHEIGHT 64
+#endif
+#if defined SH1106_128_32
+ #define SH1106_LCDWIDTH 128
+ #define SH1106_LCDHEIGHT 32
+#endif
+#if defined SH1106_96_16
+ #define SH1106_LCDWIDTH 96
+ #define SH1106_LCDHEIGHT 16
+#endif
+
+#define SH1106_SETCONTRAST 0x81
+#define SH1106_DISPLAYALLON_RESUME 0xA4
+#define SH1106_DISPLAYALLON 0xA5
+#define SH1106_NORMALDISPLAY 0xA6
+#define SH1106_INVERTDISPLAY 0xA7
+#define SH1106_DISPLAYOFF 0xAE
+#define SH1106_DISPLAYON 0xAF
+
+#define SH1106_SETDISPLAYOFFSET 0xD3
+#define SH1106_SETCOMPINS 0xDA
+
+#define SH1106_SETVCOMDETECT 0xDB
+
+#define SH1106_SETDISPLAYCLOCKDIV 0xD5
+#define SH1106_SETPRECHARGE 0xD9
+
+#define SH1106_SETMULTIPLEX 0xA8
+
+#define SH1106_SETLOWCOLUMN 0x00
+#define SH1106_SETHIGHCOLUMN 0x10
+
+#define SH1106_SETSTARTLINE 0x40
+
+#define SH1106_MEMORYMODE 0x20
+#define SH1106_COLUMNADDR 0x21
+#define SH1106_PAGEADDR 0x22
+
+#define SH1106_COMSCANINC 0xC0
+#define SH1106_COMSCANDEC 0xC8
+
+#define SH1106_SEGREMAP 0xA0
+
+#define SH1106_CHARGEPUMP 0x8D
+
+#define SH1106_EXTERNALVCC 0x1
+#define SH1106_SWITCHCAPVCC 0x2
+
+// Scrolling #defines
+#define SH1106_ACTIVATE_SCROLL 0x2F
+#define SH1106_DEACTIVATE_SCROLL 0x2E
+#define SH1106_SET_VERTICAL_SCROLL_AREA 0xA3
+#define SH1106_RIGHT_HORIZONTAL_SCROLL 0x26
+#define SH1106_LEFT_HORIZONTAL_SCROLL 0x27
+#define SH1106_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
+#define SH1106_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A
+
+class Adafruit_SH1106 : public Renderer {
+ public:
+ Adafruit_SH1106(int16_t width, int16_t height);
+
+ void begin(uint8_t switchvcc = SH1106_SWITCHCAPVCC, uint8_t i2caddr = SH1106_I2C_ADDRESS, bool reset=true);
+ void SH1106_command(uint8_t c);
+ void SH1106_data(uint8_t c);
+
+ void clearDisplay(void);
+ void invertDisplay(uint8_t i);
+ void display();
+
+
+ void DisplayOnff(int8_t on);
+ void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
+ int16_t Begin(int16_t p1,int16_t p2,int16_t p3);
+ void Updateframe();
+ void dim(uint8_t contrast);
+
+ private:
+ int8_t _i2caddr, _vccstate, rst;
+
+};
diff --git a/lib/Adafruit_SSD1306-1.1.2/license.txt b/lib/Adafruit_SH1106-gemu-1.0/LICENSE.txt
similarity index 100%
rename from lib/Adafruit_SSD1306-1.1.2/license.txt
rename to lib/Adafruit_SH1106-gemu-1.0/LICENSE.txt
diff --git a/lib/Adafruit_SH1106-gemu-1.0/README.md b/lib/Adafruit_SH1106-gemu-1.0/README.md
new file mode 100644
index 000000000..c457a3cc8
--- /dev/null
+++ b/lib/Adafruit_SH1106-gemu-1.0/README.md
@@ -0,0 +1,16 @@
+Adafruit_SH1106
+===============
+
+Adafruit graphic library for SH1106 driver lcds.
+
+some small oled lcd use SH1106 driver.
+
+I change the adafruit SSD1306 to SH1106
+
+SH1106 driver similar to SSD1306. thus, just change the display() method.
+
+However, SH1106 driver don't provide several functions such as scroll commands.
+
+
+ Adafruit-GFX-Library
+ https://github.com/adafruit/Adafruit-GFX-Library
diff --git a/lib/Adafruit_SSD1306-1.1.2/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino b/lib/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino
similarity index 90%
rename from lib/Adafruit_SSD1306-1.1.2/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino
rename to lib/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino
index c44701ed0..2b2c90368 100644
--- a/lib/Adafruit_SSD1306-1.1.2/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino
+++ b/lib/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino
@@ -16,13 +16,20 @@ BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/
+/*********************************************************************
+I change the adafruit SSD1306 to SH1106
+
+SH1106 driver don't provide several functions such as scroll commands.
+
+*********************************************************************/
+
#include
#include
#include
-#include
+#include
#define OLED_RESET 4
-Adafruit_SSD1306 display(OLED_RESET);
+Adafruit_SH1106 display(OLED_RESET);
#define NUMFLAKES 10
#define XPOS 0
@@ -50,15 +57,15 @@ static const unsigned char PROGMEM logo16_glcd_bmp[] =
B01110000, B01110000,
B00000000, B00110000 };
-#if (SSD1306_LCDHEIGHT != 64)
-#error("Height incorrect, please fix Adafruit_SSD1306.h!");
+#if (SH1106_LCDHEIGHT != 64)
+#error("Height incorrect, please fix Adafruit_SH1106.h!");
#endif
void setup() {
Serial.begin(9600);
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
- display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // initialize with the I2C addr 0x3D (for the 128x64)
+ display.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
// init done
// Show image buffer on the display hardware.
@@ -132,9 +139,9 @@ void setup() {
display.clearDisplay();
// draw scrolling text
- testscrolltext();
+ /* testscrolltext();
delay(2000);
- display.clearDisplay();
+ display.clearDisplay();*/
// text display tests
display.setTextSize(1);
@@ -148,19 +155,17 @@ void setup() {
display.print("0x"); display.println(0xDEADBEEF, HEX);
display.display();
delay(2000);
- display.clearDisplay();
// miniature bitmap display
+ display.clearDisplay();
display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1);
display.display();
- delay(1);
// invert the display
display.invertDisplay(true);
delay(1000);
display.invertDisplay(false);
delay(1000);
- display.clearDisplay();
// draw a bitmap icon and 'animate' movement
testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
@@ -192,21 +197,21 @@ void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
while (1) {
// draw each icon
for (uint8_t f=0; f< NUMFLAKES; f++) {
- display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
+ display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE);
}
display.display();
delay(200);
// then erase it + move it
for (uint8_t f=0; f< NUMFLAKES; f++) {
- display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK);
+ display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, BLACK);
// move it
icons[f][YPOS] += icons[f][DELTAY];
// if its gone, reinit
if (icons[f][YPOS] > display.height()) {
- icons[f][XPOS] = random(display.width());
- icons[f][YPOS] = 0;
- icons[f][DELTAY] = random(5) + 1;
+ icons[f][XPOS] = random(display.width());
+ icons[f][YPOS] = 0;
+ icons[f][DELTAY] = random(5) + 1;
}
}
}
@@ -225,14 +230,12 @@ void testdrawchar(void) {
display.println();
}
display.display();
- delay(1);
}
void testdrawcircle(void) {
for (int16_t i=0; i=0; i-=4) {
display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
display.display();
- delay(1);
}
delay(250);
@@ -327,12 +320,10 @@ void testdrawline() {
for (int16_t i=display.width()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
display.display();
- delay(1);
}
for (int16_t i=display.height()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
display.display();
- delay(1);
}
delay(250);
@@ -340,24 +331,21 @@ void testdrawline() {
for (int16_t i=0; i http://www.adafruit.com/category/63_98
@@ -19,7 +19,7 @@ All text above, and the splash screen must be included in any redistribution
#include
#include
#include
-#include
+#include
// If using software SPI (the default case):
#define OLED_MOSI 9
@@ -27,13 +27,13 @@ All text above, and the splash screen must be included in any redistribution
#define OLED_DC 11
#define OLED_CS 12
#define OLED_RESET 13
-Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
+Adafruit_SH1106 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
/* Uncomment this block to use hardware SPI
#define OLED_DC 6
#define OLED_CS 7
#define OLED_RESET 8
-Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);
+Adafruit_SH1106 display(OLED_DC, OLED_RESET, OLED_CS);
*/
#define NUMFLAKES 10
@@ -61,15 +61,15 @@ static const unsigned char PROGMEM logo16_glcd_bmp[] =
B01110000, B01110000,
B00000000, B00110000 };
-#if (SSD1306_LCDHEIGHT != 64)
-#error("Height incorrect, please fix Adafruit_SSD1306.h!");
+#if (SH1106_LCDHEIGHT != 64)
+#error("Height incorrect, please fix Adafruit_SH1106.h!");
#endif
void setup() {
Serial.begin(9600);
-
+
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
- display.begin(SSD1306_SWITCHCAPVCC);
+ display.begin(SH1106_SWITCHCAPVCC);
// init done
// Show image buffer on the display hardware.
@@ -143,10 +143,10 @@ void setup() {
display.clearDisplay();
// draw scrolling text
- testscrolltext();
+ /*testscrolltext();
delay(2000);
- display.clearDisplay();
-
+ display.clearDisplay();*/
+
// text display tests
display.setTextSize(1);
display.setTextColor(WHITE);
@@ -159,9 +159,9 @@ void setup() {
display.print("0x"); display.println(0xDEADBEEF, HEX);
display.display();
delay(2000);
- display.clearDisplay();
// miniature bitmap display
+ display.clearDisplay();
display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1);
display.display();
@@ -170,7 +170,6 @@ void setup() {
delay(1000);
display.invertDisplay(false);
delay(1000);
- display.clearDisplay();
// draw a bitmap icon and 'animate' movement
testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
@@ -202,21 +201,21 @@ void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
while (1) {
// draw each icon
for (uint8_t f=0; f< NUMFLAKES; f++) {
- display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
+ display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE);
}
display.display();
delay(200);
// then erase it + move it
for (uint8_t f=0; f< NUMFLAKES; f++) {
- display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK);
+ display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, BLACK);
// move it
icons[f][YPOS] += icons[f][DELTAY];
// if its gone, reinit
if (icons[f][YPOS] > display.height()) {
- icons[f][XPOS] = random(display.width());
- icons[f][YPOS] = 0;
- icons[f][DELTAY] = random(5) + 1;
+ icons[f][XPOS] = random(display.width());
+ icons[f][YPOS] = 0;
+ icons[f][DELTAY] = random(5) + 1;
}
}
}
@@ -344,6 +343,7 @@ void testdrawline() {
delay(250);
}
+/*
void testscrolltext(void) {
display.setTextSize(2);
display.setTextColor(WHITE);
@@ -366,3 +366,4 @@ void testscrolltext(void) {
delay(2000);
display.stopscroll();
}
+*/
diff --git a/lib/Adafruit_SSD1306-1.1.2/Adafruit_SSD1306.cpp b/lib/Adafruit_SSD1306-1.1.2/Adafruit_SSD1306.cpp
deleted file mode 100644
index 570a33584..000000000
--- a/lib/Adafruit_SSD1306-1.1.2/Adafruit_SSD1306.cpp
+++ /dev/null
@@ -1,729 +0,0 @@
-/*********************************************************************
-This is a library for our Monochrome OLEDs based on SSD1306 drivers
-
- Pick one up today in the adafruit shop!
- ------> http://www.adafruit.com/category/63_98
-
-These displays use SPI to communicate, 4 or 5 pins are required to
-interface
-
-Adafruit invests time and resources providing this open source code,
-please support Adafruit and open-source hardware by purchasing
-products from Adafruit!
-
-Written by Limor Fried/Ladyada for Adafruit Industries.
-BSD license, check license.txt for more information
-All text above, and the splash screen below must be included in any redistribution
-*********************************************************************/
-
-#ifdef __AVR__
- #include
-#elif defined(ESP8266) || defined(ESP32)
- #include
-#else
- #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
-#endif
-
-#if !defined(__ARM_ARCH) && !defined(ENERGIA) && !defined(ESP8266) && !defined(ESP32) && !defined(__arc__)
- #include
-#endif
-
-#include
-
-#include
-#include
-#include "Adafruit_GFX.h"
-#include "Adafruit_SSD1306.h"
-
-// the memory buffer for the LCD
-
-static uint8_t buffer[SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH / 8] = {
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x80, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
-0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xFF,
-#if (SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH > 96*16)
-0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
-0x80, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x8C, 0x8E, 0x84, 0x00, 0x00, 0x80, 0xF8,
-0xF8, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80,
-0x00, 0xE0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0x01, 0x01,
-0x01, 0x01, 0x83, 0xFF, 0xFF, 0x00, 0x00, 0x7C, 0xFE, 0xC7, 0x01, 0x01, 0x01, 0x01, 0x83, 0xFF,
-0xFF, 0xFF, 0x00, 0x38, 0xFE, 0xC7, 0x83, 0x01, 0x01, 0x01, 0x83, 0xC7, 0xFF, 0xFF, 0x00, 0x00,
-0x01, 0xFF, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x7F, 0xFF,
-0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF,
-0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x03, 0x0F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x8F,
-0x8F, 0x9F, 0xBF, 0xFF, 0xFF, 0xC3, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC,
-0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x01, 0x03, 0x03, 0x03,
-0x03, 0x03, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01,
-0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00,
-0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x03,
-0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-#if (SSD1306_LCDHEIGHT == 64)
-0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x0F,
-0x87, 0xC7, 0xF7, 0xFF, 0xFF, 0x1F, 0x1F, 0x3D, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0x7C, 0x7D, 0xFF,
-0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x00, 0x30, 0x30, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F,
-0x0F, 0x07, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0,
-0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00,
-0x00, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xF0, 0xF8, 0x1C, 0x0E,
-0x06, 0x06, 0x06, 0x0C, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFC,
-0xFE, 0xFC, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0xE6, 0xCE, 0x84, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0x06,
-0x06, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xC0, 0xF8,
-0xFC, 0x4E, 0x46, 0x46, 0x46, 0x4E, 0x7C, 0x78, 0x40, 0x18, 0x3C, 0x76, 0xE6, 0xCE, 0xCC, 0x80,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
-0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x0C,
-0x18, 0x18, 0x0C, 0x06, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0E, 0x0C, 0x18, 0x0C, 0x0F,
-0x07, 0x01, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
-0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x07,
-0x07, 0x0C, 0x0C, 0x18, 0x1C, 0x0C, 0x06, 0x06, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-#endif
-#endif
-};
-
-#define ssd1306_swap(a, b) { int16_t t = a; a = b; b = t; }
-
-// the most basic function, set a single pixel
-void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) {
- if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
- return;
-
- // check rotation, move pixel around if necessary
- switch (getRotation()) {
- case 1:
- ssd1306_swap(x, y);
- x = WIDTH - x - 1;
- break;
- case 2:
- x = WIDTH - x - 1;
- y = HEIGHT - y - 1;
- break;
- case 3:
- ssd1306_swap(x, y);
- y = HEIGHT - y - 1;
- break;
- }
-
- // x is which column
- switch (color)
- {
- case WHITE: buffer[x+ (y/8)*SSD1306_LCDWIDTH] |= (1 << (y&7)); break;
- case BLACK: buffer[x+ (y/8)*SSD1306_LCDWIDTH] &= ~(1 << (y&7)); break;
- case INVERSE: buffer[x+ (y/8)*SSD1306_LCDWIDTH] ^= (1 << (y&7)); break;
- }
-
-}
-
-Adafruit_SSD1306::Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
- cs = CS;
- rst = RST;
- dc = DC;
- sclk = SCLK;
- sid = SID;
- hwSPI = false;
-}
-
-// constructor for hardware SPI - we indicate DataCommand, ChipSelect, Reset
-Adafruit_SSD1306::Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
- dc = DC;
- rst = RST;
- cs = CS;
- hwSPI = true;
-}
-
-// initializer for I2C - we only indicate the reset pin!
-Adafruit_SSD1306::Adafruit_SSD1306(int8_t reset) :
-Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
- sclk = dc = cs = sid = -1;
- rst = reset;
-}
-
-
-void Adafruit_SSD1306::begin(uint8_t vccstate, uint8_t i2caddr, bool reset) {
- _vccstate = vccstate;
- _i2caddr = i2caddr;
-
- // set pin directions
- if (sid != -1){
- pinMode(dc, OUTPUT);
- pinMode(cs, OUTPUT);
-#ifdef HAVE_PORTREG
- csport = portOutputRegister(digitalPinToPort(cs));
- cspinmask = digitalPinToBitMask(cs);
- dcport = portOutputRegister(digitalPinToPort(dc));
- dcpinmask = digitalPinToBitMask(dc);
-#endif
- if (!hwSPI){
- // set pins for software-SPI
- pinMode(sid, OUTPUT);
- pinMode(sclk, OUTPUT);
-#ifdef HAVE_PORTREG
- clkport = portOutputRegister(digitalPinToPort(sclk));
- clkpinmask = digitalPinToBitMask(sclk);
- mosiport = portOutputRegister(digitalPinToPort(sid));
- mosipinmask = digitalPinToBitMask(sid);
-#endif
- }
- if (hwSPI){
- SPI.begin();
-#ifdef SPI_HAS_TRANSACTION
- SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
-#else
- SPI.setClockDivider (4);
-#endif
- }
- }
- else
- {
- // I2C Init
- Wire.begin();
-#ifdef __SAM3X8E__
- // Force 400 KHz I2C, rawr! (Uses pins 20, 21 for SDA, SCL)
- TWI1->TWI_CWGR = 0;
- TWI1->TWI_CWGR = ((VARIANT_MCK / (2 * 400000)) - 4) * 0x101;
-#endif
- }
- if ((reset) && (rst >= 0)) {
- // Setup reset pin direction (used by both SPI and I2C)
- pinMode(rst, OUTPUT);
- digitalWrite(rst, HIGH);
- // VDD (3.3V) goes high at start, lets just chill for a ms
- delay(1);
- // bring reset low
- digitalWrite(rst, LOW);
- // wait 10ms
- delay(10);
- // bring out of reset
- digitalWrite(rst, HIGH);
- // turn on VCC (9V?)
- }
-
- // Init sequence
- ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
- ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
- ssd1306_command(0x80); // the suggested ratio 0x80
-
- ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
- ssd1306_command(SSD1306_LCDHEIGHT - 1);
-
- ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
- ssd1306_command(0x0); // no offset
- ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
- ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
- if (vccstate == SSD1306_EXTERNALVCC)
- { ssd1306_command(0x10); }
- else
- { ssd1306_command(0x14); }
- ssd1306_command(SSD1306_MEMORYMODE); // 0x20
- ssd1306_command(0x00); // 0x0 act like ks0108
- ssd1306_command(SSD1306_SEGREMAP | 0x1);
- ssd1306_command(SSD1306_COMSCANDEC);
-
- #if defined SSD1306_128_32
- ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
- ssd1306_command(0x02);
- ssd1306_command(SSD1306_SETCONTRAST); // 0x81
- ssd1306_command(0x8F);
-
-#elif defined SSD1306_128_64
- ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
- ssd1306_command(0x12);
- ssd1306_command(SSD1306_SETCONTRAST); // 0x81
- if (vccstate == SSD1306_EXTERNALVCC)
- { ssd1306_command(0x9F); }
- else
- { ssd1306_command(0xCF); }
-
-#elif defined SSD1306_96_16
- ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
- ssd1306_command(0x2); //ada x12
- ssd1306_command(SSD1306_SETCONTRAST); // 0x81
- if (vccstate == SSD1306_EXTERNALVCC)
- { ssd1306_command(0x10); }
- else
- { ssd1306_command(0xAF); }
-
-#endif
-
- ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
- if (vccstate == SSD1306_EXTERNALVCC)
- { ssd1306_command(0x22); }
- else
- { ssd1306_command(0xF1); }
- ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
- ssd1306_command(0x40);
- ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
- ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
-
- ssd1306_command(SSD1306_DEACTIVATE_SCROLL);
-
- ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel
-}
-
-
-void Adafruit_SSD1306::invertDisplay(uint8_t i) {
- if (i) {
- ssd1306_command(SSD1306_INVERTDISPLAY);
- } else {
- ssd1306_command(SSD1306_NORMALDISPLAY);
- }
-}
-
-void Adafruit_SSD1306::ssd1306_command(uint8_t c) {
- if (sid != -1)
- {
- // SPI
-#ifdef HAVE_PORTREG
- *csport |= cspinmask;
- *dcport &= ~dcpinmask;
- *csport &= ~cspinmask;
-#else
- digitalWrite(cs, HIGH);
- digitalWrite(dc, LOW);
- digitalWrite(cs, LOW);
-#endif
- fastSPIwrite(c);
-#ifdef HAVE_PORTREG
- *csport |= cspinmask;
-#else
- digitalWrite(cs, HIGH);
-#endif
- }
- else
- {
- // I2C
- uint8_t control = 0x00; // Co = 0, D/C = 0
- Wire.beginTransmission(_i2caddr);
- Wire.write(control);
- Wire.write(c);
- Wire.endTransmission();
- }
-}
-
-// startscrollright
-// Activate a right handed scroll for rows start through stop
-// Hint, the display is 16 rows tall. To scroll the whole display, run:
-// display.scrollright(0x00, 0x0F)
-void Adafruit_SSD1306::startscrollright(uint8_t start, uint8_t stop){
- ssd1306_command(SSD1306_RIGHT_HORIZONTAL_SCROLL);
- ssd1306_command(0X00);
- ssd1306_command(start);
- ssd1306_command(0X00);
- ssd1306_command(stop);
- ssd1306_command(0X00);
- ssd1306_command(0XFF);
- ssd1306_command(SSD1306_ACTIVATE_SCROLL);
-}
-
-// startscrollleft
-// Activate a right handed scroll for rows start through stop
-// Hint, the display is 16 rows tall. To scroll the whole display, run:
-// display.scrollright(0x00, 0x0F)
-void Adafruit_SSD1306::startscrollleft(uint8_t start, uint8_t stop){
- ssd1306_command(SSD1306_LEFT_HORIZONTAL_SCROLL);
- ssd1306_command(0X00);
- ssd1306_command(start);
- ssd1306_command(0X00);
- ssd1306_command(stop);
- ssd1306_command(0X00);
- ssd1306_command(0XFF);
- ssd1306_command(SSD1306_ACTIVATE_SCROLL);
-}
-
-// startscrolldiagright
-// Activate a diagonal scroll for rows start through stop
-// Hint, the display is 16 rows tall. To scroll the whole display, run:
-// display.scrollright(0x00, 0x0F)
-void Adafruit_SSD1306::startscrolldiagright(uint8_t start, uint8_t stop){
- ssd1306_command(SSD1306_SET_VERTICAL_SCROLL_AREA);
- ssd1306_command(0X00);
- ssd1306_command(SSD1306_LCDHEIGHT);
- ssd1306_command(SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL);
- ssd1306_command(0X00);
- ssd1306_command(start);
- ssd1306_command(0X00);
- ssd1306_command(stop);
- ssd1306_command(0X01);
- ssd1306_command(SSD1306_ACTIVATE_SCROLL);
-}
-
-// startscrolldiagleft
-// Activate a diagonal scroll for rows start through stop
-// Hint, the display is 16 rows tall. To scroll the whole display, run:
-// display.scrollright(0x00, 0x0F)
-void Adafruit_SSD1306::startscrolldiagleft(uint8_t start, uint8_t stop){
- ssd1306_command(SSD1306_SET_VERTICAL_SCROLL_AREA);
- ssd1306_command(0X00);
- ssd1306_command(SSD1306_LCDHEIGHT);
- ssd1306_command(SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL);
- ssd1306_command(0X00);
- ssd1306_command(start);
- ssd1306_command(0X00);
- ssd1306_command(stop);
- ssd1306_command(0X01);
- ssd1306_command(SSD1306_ACTIVATE_SCROLL);
-}
-
-void Adafruit_SSD1306::stopscroll(void){
- ssd1306_command(SSD1306_DEACTIVATE_SCROLL);
-}
-
-// Dim the display
-// dim = true: display is dimmed
-// dim = false: display is normal
-void Adafruit_SSD1306::dim(boolean dim) {
- uint8_t contrast;
-
- if (dim) {
- contrast = 0; // Dimmed display
- } else {
- if (_vccstate == SSD1306_EXTERNALVCC) {
- contrast = 0x9F;
- } else {
- contrast = 0xCF;
- }
- }
- // the range of contrast to too small to be really useful
- // it is useful to dim the display
- ssd1306_command(SSD1306_SETCONTRAST);
- ssd1306_command(contrast);
-}
-
-void Adafruit_SSD1306::display(void) {
- ssd1306_command(SSD1306_COLUMNADDR);
- ssd1306_command(0); // Column start address (0 = reset)
- ssd1306_command(SSD1306_LCDWIDTH-1); // Column end address (127 = reset)
-
- ssd1306_command(SSD1306_PAGEADDR);
- ssd1306_command(0); // Page start address (0 = reset)
- #if SSD1306_LCDHEIGHT == 64
- ssd1306_command(7); // Page end address
- #endif
- #if SSD1306_LCDHEIGHT == 32
- ssd1306_command(3); // Page end address
- #endif
- #if SSD1306_LCDHEIGHT == 16
- ssd1306_command(1); // Page end address
- #endif
-
- if (sid != -1)
- {
- // SPI
-#ifdef HAVE_PORTREG
- *csport |= cspinmask;
- *dcport |= dcpinmask;
- *csport &= ~cspinmask;
-#else
- digitalWrite(cs, HIGH);
- digitalWrite(dc, HIGH);
- digitalWrite(cs, LOW);
-#endif
-
- for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) {
- fastSPIwrite(buffer[i]);
- }
-#ifdef HAVE_PORTREG
- *csport |= cspinmask;
-#else
- digitalWrite(cs, HIGH);
-#endif
- }
- else
- {
- // save I2C bitrate
-#ifdef TWBR
- uint8_t twbrbackup = TWBR;
- TWBR = 12; // upgrade to 400KHz!
-#endif
-
- //Serial.println(TWBR, DEC);
- //Serial.println(TWSR & 0x3, DEC);
-
- // I2C
- for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) {
- // send a bunch of data in one xmission
- Wire.beginTransmission(_i2caddr);
- WIRE_WRITE(0x40);
- for (uint8_t x=0; x<16; x++) {
- WIRE_WRITE(buffer[i]);
- i++;
- }
- i--;
- Wire.endTransmission();
- }
-#ifdef TWBR
- TWBR = twbrbackup;
-#endif
- }
-}
-
-// clear everything
-void Adafruit_SSD1306::clearDisplay(void) {
- memset(buffer, 0, (SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8));
-}
-
-
-inline void Adafruit_SSD1306::fastSPIwrite(uint8_t d) {
-
- if(hwSPI) {
- (void)SPI.transfer(d);
- } else {
- for(uint8_t bit = 0x80; bit; bit >>= 1) {
-#ifdef HAVE_PORTREG
- *clkport &= ~clkpinmask;
- if(d & bit) *mosiport |= mosipinmask;
- else *mosiport &= ~mosipinmask;
- *clkport |= clkpinmask;
-#else
- digitalWrite(sclk, LOW);
- if(d & bit) digitalWrite(sid, HIGH);
- else digitalWrite(sid, LOW);
- digitalWrite(sclk, HIGH);
-#endif
- }
- }
-}
-
-void Adafruit_SSD1306::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
- boolean bSwap = false;
- switch(rotation) {
- case 0:
- // 0 degree rotation, do nothing
- break;
- case 1:
- // 90 degree rotation, swap x & y for rotation, then invert x
- bSwap = true;
- ssd1306_swap(x, y);
- x = WIDTH - x - 1;
- break;
- case 2:
- // 180 degree rotation, invert x and y - then shift y around for height.
- x = WIDTH - x - 1;
- y = HEIGHT - y - 1;
- x -= (w-1);
- break;
- case 3:
- // 270 degree rotation, swap x & y for rotation, then invert y and adjust y for w (not to become h)
- bSwap = true;
- ssd1306_swap(x, y);
- y = HEIGHT - y - 1;
- y -= (w-1);
- break;
- }
-
- if(bSwap) {
- drawFastVLineInternal(x, y, w, color);
- } else {
- drawFastHLineInternal(x, y, w, color);
- }
-}
-
-void Adafruit_SSD1306::drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) {
- // Do bounds/limit checks
- if(y < 0 || y >= HEIGHT) { return; }
-
- // make sure we don't try to draw below 0
- if(x < 0) {
- w += x;
- x = 0;
- }
-
- // make sure we don't go off the edge of the display
- if( (x + w) > WIDTH) {
- w = (WIDTH - x);
- }
-
- // if our width is now negative, punt
- if(w <= 0) { return; }
-
- // set up the pointer for movement through the buffer
- register uint8_t *pBuf = buffer;
- // adjust the buffer pointer for the current row
- pBuf += ((y/8) * SSD1306_LCDWIDTH);
- // and offset x columns in
- pBuf += x;
-
- register uint8_t mask = 1 << (y&7);
-
- switch (color)
- {
- case WHITE: while(w--) { *pBuf++ |= mask; }; break;
- case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
- case INVERSE: while(w--) { *pBuf++ ^= mask; }; break;
- }
-}
-
-void Adafruit_SSD1306::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
- bool bSwap = false;
- switch(rotation) {
- case 0:
- break;
- case 1:
- // 90 degree rotation, swap x & y for rotation, then invert x and adjust x for h (now to become w)
- bSwap = true;
- ssd1306_swap(x, y);
- x = WIDTH - x - 1;
- x -= (h-1);
- break;
- case 2:
- // 180 degree rotation, invert x and y - then shift y around for height.
- x = WIDTH - x - 1;
- y = HEIGHT - y - 1;
- y -= (h-1);
- break;
- case 3:
- // 270 degree rotation, swap x & y for rotation, then invert y
- bSwap = true;
- ssd1306_swap(x, y);
- y = HEIGHT - y - 1;
- break;
- }
-
- if(bSwap) {
- drawFastHLineInternal(x, y, h, color);
- } else {
- drawFastVLineInternal(x, y, h, color);
- }
-}
-
-
-void Adafruit_SSD1306::drawFastVLineInternal(int16_t x, int16_t __y, int16_t __h, uint16_t color) {
-
- // do nothing if we're off the left or right side of the screen
- if(x < 0 || x >= WIDTH) { return; }
-
- // make sure we don't try to draw below 0
- if(__y < 0) {
- // __y is negative, this will subtract enough from __h to account for __y being 0
- __h += __y;
- __y = 0;
-
- }
-
- // make sure we don't go past the height of the display
- if( (__y + __h) > HEIGHT) {
- __h = (HEIGHT - __y);
- }
-
- // if our height is now negative, punt
- if(__h <= 0) {
- return;
- }
-
- // this display doesn't need ints for coordinates, use local byte registers for faster juggling
- register uint8_t y = __y;
- register uint8_t h = __h;
-
-
- // set up the pointer for fast movement through the buffer
- register uint8_t *pBuf = buffer;
- // adjust the buffer pointer for the current row
- pBuf += ((y/8) * SSD1306_LCDWIDTH);
- // and offset x columns in
- pBuf += x;
-
- // do the first partial byte, if necessary - this requires some masking
- register uint8_t mod = (y&7);
- if(mod) {
- // mask off the high n bits we want to set
- mod = 8-mod;
-
- // note - lookup table results in a nearly 10% performance improvement in fill* functions
- // register uint8_t mask = ~(0xFF >> (mod));
- static uint8_t premask[8] = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
- register uint8_t mask = premask[mod];
-
- // adjust the mask if we're not going to reach the end of this byte
- if( h < mod) {
- mask &= (0XFF >> (mod-h));
- }
-
- switch (color)
- {
- case WHITE: *pBuf |= mask; break;
- case BLACK: *pBuf &= ~mask; break;
- case INVERSE: *pBuf ^= mask; break;
- }
-
- // fast exit if we're done here!
- if(h= 8) {
- if (color == INVERSE) { // separate copy of the code so we don't impact performance of the black/white write version with an extra comparison per loop
- do {
- *pBuf=~(*pBuf);
-
- // adjust the buffer forward 8 rows worth of data
- pBuf += SSD1306_LCDWIDTH;
-
- // adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
- h -= 8;
- } while(h >= 8);
- }
- else {
- // store a local value to work with
- register uint8_t val = (color == WHITE) ? 255 : 0;
-
- do {
- // write our value in
- *pBuf = val;
-
- // adjust the buffer forward 8 rows worth of data
- pBuf += SSD1306_LCDWIDTH;
-
- // adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
- h -= 8;
- } while(h >= 8);
- }
- }
-
- // now do the final partial byte, if necessary
- if(h) {
- mod = h & 7;
- // this time we want to mask the low bits of the byte, vs the high bits we did above
- // register uint8_t mask = (1 << mod) - 1;
- // note - lookup table results in a nearly 10% performance improvement in fill* functions
- static uint8_t postmask[8] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
- register uint8_t mask = postmask[mod];
- switch (color)
- {
- case WHITE: *pBuf |= mask; break;
- case BLACK: *pBuf &= ~mask; break;
- case INVERSE: *pBuf ^= mask; break;
- }
- }
-}
diff --git a/lib/Adafruit_SSD1306-1.1.2/Adafruit_SSD1306.h b/lib/Adafruit_SSD1306-1.1.2/Adafruit_SSD1306.h
deleted file mode 100644
index 1d43dfddf..000000000
--- a/lib/Adafruit_SSD1306-1.1.2/Adafruit_SSD1306.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*********************************************************************
-This is a library for our Monochrome OLEDs based on SSD1306 drivers
-
- Pick one up today in the adafruit shop!
- ------> http://www.adafruit.com/category/63_98
-
-These displays use SPI to communicate, 4 or 5 pins are required to
-interface
-
-Adafruit invests time and resources providing this open source code,
-please support Adafruit and open-source hardware by purchasing
-products from Adafruit!
-
-Written by Limor Fried/Ladyada for Adafruit Industries.
-BSD license, check license.txt for more information
-All text above, and the splash screen must be included in any redistribution
-*********************************************************************/
-#ifndef _Adafruit_SSD1306_H_
-#define _Adafruit_SSD1306_H_
-
-#if ARDUINO >= 100
- #include "Arduino.h"
- #define WIRE_WRITE Wire.write
-#else
- #include "WProgram.h"
- #define WIRE_WRITE Wire.send
-#endif
-
-#if defined(__SAM3X8E__)
- typedef volatile RwReg PortReg;
- typedef uint32_t PortMask;
- #define HAVE_PORTREG
-#elif defined(ARDUINO_ARCH_SAMD)
-// not supported
-#elif defined(ESP8266) || defined(ESP32) || defined(ARDUINO_STM32_FEATHER) || defined(__arc__)
- typedef volatile uint32_t PortReg;
- typedef uint32_t PortMask;
-#elif defined(__AVR__)
- typedef volatile uint8_t PortReg;
- typedef uint8_t PortMask;
- #define HAVE_PORTREG
-#else
- // chances are its 32 bit so assume that
- typedef volatile uint32_t PortReg;
- typedef uint32_t PortMask;
-#endif
-
-#include
-#include
-
-#define BLACK 0
-#define WHITE 1
-#define INVERSE 2
-
-#define SSD1306_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D
-// Address for 128x32 is 0x3C
-// Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded)
-
-/*=========================================================================
- SSD1306 Displays
- -----------------------------------------------------------------------
- The driver is used in multiple displays (128x64, 128x32, etc.).
- Select the appropriate display below to create an appropriately
- sized framebuffer, etc.
-
- SSD1306_128_64 128x64 pixel display
-
- SSD1306_128_32 128x32 pixel display
-
- SSD1306_96_16
-
- -----------------------------------------------------------------------*/
- #define SSD1306_128_64
-// #define SSD1306_128_32
-// #define SSD1306_96_16
-/*=========================================================================*/
-
-#if defined SSD1306_128_64 && defined SSD1306_128_32
- #error "Only one SSD1306 display can be specified at once in SSD1306.h"
-#endif
-#if !defined SSD1306_128_64 && !defined SSD1306_128_32 && !defined SSD1306_96_16
- #error "At least one SSD1306 display must be specified in SSD1306.h"
-#endif
-
-#if defined SSD1306_128_64
- #define SSD1306_LCDWIDTH 128
- #define SSD1306_LCDHEIGHT 64
-#endif
-#if defined SSD1306_128_32
- #define SSD1306_LCDWIDTH 128
- #define SSD1306_LCDHEIGHT 32
-#endif
-#if defined SSD1306_96_16
- #define SSD1306_LCDWIDTH 96
- #define SSD1306_LCDHEIGHT 16
-#endif
-
-#define SSD1306_SETCONTRAST 0x81
-#define SSD1306_DISPLAYALLON_RESUME 0xA4
-#define SSD1306_DISPLAYALLON 0xA5
-#define SSD1306_NORMALDISPLAY 0xA6
-#define SSD1306_INVERTDISPLAY 0xA7
-#define SSD1306_DISPLAYOFF 0xAE
-#define SSD1306_DISPLAYON 0xAF
-
-#define SSD1306_SETDISPLAYOFFSET 0xD3
-#define SSD1306_SETCOMPINS 0xDA
-
-#define SSD1306_SETVCOMDETECT 0xDB
-
-#define SSD1306_SETDISPLAYCLOCKDIV 0xD5
-#define SSD1306_SETPRECHARGE 0xD9
-
-#define SSD1306_SETMULTIPLEX 0xA8
-
-#define SSD1306_SETLOWCOLUMN 0x00
-#define SSD1306_SETHIGHCOLUMN 0x10
-
-#define SSD1306_SETSTARTLINE 0x40
-
-#define SSD1306_MEMORYMODE 0x20
-#define SSD1306_COLUMNADDR 0x21
-#define SSD1306_PAGEADDR 0x22
-
-#define SSD1306_COMSCANINC 0xC0
-#define SSD1306_COMSCANDEC 0xC8
-
-#define SSD1306_SEGREMAP 0xA0
-
-#define SSD1306_CHARGEPUMP 0x8D
-
-#define SSD1306_EXTERNALVCC 0x1
-#define SSD1306_SWITCHCAPVCC 0x2
-
-// Scrolling #defines
-#define SSD1306_ACTIVATE_SCROLL 0x2F
-#define SSD1306_DEACTIVATE_SCROLL 0x2E
-#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3
-#define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26
-#define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27
-#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
-#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A
-
-class Adafruit_SSD1306 : public Adafruit_GFX {
- public:
- Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS);
- Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS);
- Adafruit_SSD1306(int8_t RST = -1);
-
- void begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS, bool reset=true);
- void ssd1306_command(uint8_t c);
-
- void clearDisplay(void);
- void invertDisplay(uint8_t i);
- void display();
-
- void startscrollright(uint8_t start, uint8_t stop);
- void startscrollleft(uint8_t start, uint8_t stop);
-
- void startscrolldiagright(uint8_t start, uint8_t stop);
- void startscrolldiagleft(uint8_t start, uint8_t stop);
- void stopscroll(void);
-
- void dim(boolean dim);
-
- void drawPixel(int16_t x, int16_t y, uint16_t color);
-
- virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
- virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
-
- private:
- int8_t _i2caddr, _vccstate, sid, sclk, dc, rst, cs;
- void fastSPIwrite(uint8_t c);
-
- boolean hwSPI;
-#ifdef HAVE_PORTREG
- PortReg *mosiport, *clkport, *csport, *dcport;
- PortMask mosipinmask, clkpinmask, cspinmask, dcpinmask;
-#endif
-
- inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline));
- inline void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline));
-
-};
-
-#endif /* _Adafruit_SSD1306_H_ */
diff --git a/lib/Adafruit_SSD1306-1.1.2/README.md b/lib/Adafruit_SSD1306-1.1.2/README.md
deleted file mode 100644
index d76bb285c..000000000
--- a/lib/Adafruit_SSD1306-1.1.2/README.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# Adafruit_SSD1306
-
-
-## Compatibility
-
-MCU | Tested Works | Doesn't Work | Not Tested | Notes
------------------- | :----------: | :----------: | :---------: | -----
-Atmega328 @ 16MHz | X | | |
-Atmega328 @ 12MHz | X | | |
-Atmega32u4 @ 16MHz | X | | |
-Atmega32u4 @ 8MHz | X | | |
-ESP8266 | X | | | change OLED_RESET to different pin if using default I2C pins D4/D5.
-Atmega2560 @ 16MHz | X | | |
-ATSAM3X8E | X | | |
-ATSAM21D | X | | |
-ATtiny85 @ 16MHz | | X | |
-ATtiny85 @ 8MHz | | X | |
-Intel Curie @ 32MHz | | | X |
-STM32F2 | | | X |
-
- * ATmega328 @ 16MHz : Arduino UNO, Adafruit Pro Trinket 5V, Adafruit Metro 328, Adafruit Metro Mini
- * ATmega328 @ 12MHz : Adafruit Pro Trinket 3V
- * ATmega32u4 @ 16MHz : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0
- * ATmega32u4 @ 8MHz : Adafruit Flora, Bluefruit Micro
- * ESP8266 : Adafruit Huzzah
- * ATmega2560 @ 16MHz : Arduino Mega
- * ATSAM3X8E : Arduino Due
- * ATSAM21D : Arduino Zero, M0 Pro
- * ATtiny85 @ 16MHz : Adafruit Trinket 5V
- * ATtiny85 @ 8MHz : Adafruit Gemma, Arduino Gemma, Adafruit Trinket 3V
-
-
diff --git a/lib/Adafruit_SSD1306-1.1.2/README.txt b/lib/Adafruit_SSD1306-1.1.2/README.txt
deleted file mode 100644
index 420cc153c..000000000
--- a/lib/Adafruit_SSD1306-1.1.2/README.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-This is a library for our Monochrome OLEDs based on SSD1306 drivers
-
- Pick one up today in the adafruit shop!
- ------> http://www.adafruit.com/category/63_98
-
-These displays use SPI to communicate, 4 or 5 pins are required to
-interface
-
-Adafruit invests time and resources providing this open source code,
-please support Adafruit and open-source hardware by purchasing
-products from Adafruit!
-
-Written by Limor Fried/Ladyada for Adafruit Industries.
-Scrolling code contributed by Michael Gregg
-BSD license, check license.txt for more information
-All text above must be included in any redistribution
-
-To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder Adafruit_SSD1306. Check that the Adafruit_SSD1306 folder contains Adafruit_SSD1306.cpp and Adafruit_SSD1306.h
-
-Place the Adafruit_SSD1306 library folder your /libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE.
-
-You will also have to download the Adafruit GFX Graphics core which does all the circles, text, rectangles, etc. You can get it from
-https://github.com/adafruit/Adafruit-GFX-Library
-and download/install that library as well
\ No newline at end of file
diff --git a/lib/Adafruit_SSD1306-1.1.2/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino b/lib/Adafruit_SSD1306-1.1.2/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino
deleted file mode 100644
index b3b8bfa9a..000000000
--- a/lib/Adafruit_SSD1306-1.1.2/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino
+++ /dev/null
@@ -1,375 +0,0 @@
-/*********************************************************************
-This is an example for our Monochrome OLEDs based on SSD1306 drivers
-
- Pick one up today in the adafruit shop!
- ------> http://www.adafruit.com/category/63_98
-
-This example is for a 128x32 size display using I2C to communicate
-3 pins are required to interface (2 I2C and one reset)
-
-Adafruit invests time and resources providing this open source code,
-please support Adafruit and open-source hardware by purchasing
-products from Adafruit!
-
-Written by Limor Fried/Ladyada for Adafruit Industries.
-BSD license, check license.txt for more information
-All text above, and the splash screen must be included in any redistribution
-*********************************************************************/
-
-#include
-#include
-#include
-#include
-
-#define OLED_RESET 4
-Adafruit_SSD1306 display(OLED_RESET);
-
-#define NUMFLAKES 10
-#define XPOS 0
-#define YPOS 1
-#define DELTAY 2
-
-
-#define LOGO16_GLCD_HEIGHT 16
-#define LOGO16_GLCD_WIDTH 16
-static const unsigned char PROGMEM logo16_glcd_bmp[] =
-{ B00000000, B11000000,
- B00000001, B11000000,
- B00000001, B11000000,
- B00000011, B11100000,
- B11110011, B11100000,
- B11111110, B11111000,
- B01111110, B11111111,
- B00110011, B10011111,
- B00011111, B11111100,
- B00001101, B01110000,
- B00011011, B10100000,
- B00111111, B11100000,
- B00111111, B11110000,
- B01111100, B11110000,
- B01110000, B01110000,
- B00000000, B00110000 };
-
-#if (SSD1306_LCDHEIGHT != 32)
-#error("Height incorrect, please fix Adafruit_SSD1306.h!");
-#endif
-
-void setup() {
- Serial.begin(9600);
-
- // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
- display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
- // init done
-
- // Show image buffer on the display hardware.
- // Since the buffer is intialized with an Adafruit splashscreen
- // internally, this will display the splashscreen.
- display.display();
- delay(2000);
-
- // Clear the buffer.
- display.clearDisplay();
-
- // draw a single pixel
- display.drawPixel(10, 10, WHITE);
- // Show the display buffer on the hardware.
- // NOTE: You _must_ call display after making any drawing commands
- // to make them visible on the display hardware!
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw many lines
- testdrawline();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw rectangles
- testdrawrect();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw multiple rectangles
- testfillrect();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw mulitple circles
- testdrawcircle();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw a white circle, 10 pixel radius
- display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
- display.display();
- delay(2000);
- display.clearDisplay();
-
- testdrawroundrect();
- delay(2000);
- display.clearDisplay();
-
- testfillroundrect();
- delay(2000);
- display.clearDisplay();
-
- testdrawtriangle();
- delay(2000);
- display.clearDisplay();
-
- testfilltriangle();
- delay(2000);
- display.clearDisplay();
-
- // draw the first ~12 characters in the font
- testdrawchar();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw scrolling text
- testscrolltext();
- delay(2000);
- display.clearDisplay();
-
- // text display tests
- display.setTextSize(1);
- display.setTextColor(WHITE);
- display.setCursor(0,0);
- display.println("Hello, world!");
- display.setTextColor(BLACK, WHITE); // 'inverted' text
- display.println(3.141592);
- display.setTextSize(2);
- display.setTextColor(WHITE);
- display.print("0x"); display.println(0xDEADBEEF, HEX);
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // miniature bitmap display
- display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1);
- display.display();
- delay(1);
-
- // invert the display
- display.invertDisplay(true);
- delay(1000);
- display.invertDisplay(false);
- delay(1000);
- display.clearDisplay();
-
- // draw a bitmap icon and 'animate' movement
- testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
-}
-
-
-void loop() {
-
-}
-
-
-void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
- uint8_t icons[NUMFLAKES][3];
-
- // initialize
- for (uint8_t f=0; f< NUMFLAKES; f++) {
- icons[f][XPOS] = random(display.width());
- icons[f][YPOS] = 0;
- icons[f][DELTAY] = random(5) + 1;
-
- Serial.print("x: ");
- Serial.print(icons[f][XPOS], DEC);
- Serial.print(" y: ");
- Serial.print(icons[f][YPOS], DEC);
- Serial.print(" dy: ");
- Serial.println(icons[f][DELTAY], DEC);
- }
-
- while (1) {
- // draw each icon
- for (uint8_t f=0; f< NUMFLAKES; f++) {
- display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
- }
- display.display();
- delay(200);
-
- // then erase it + move it
- for (uint8_t f=0; f< NUMFLAKES; f++) {
- display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK);
- // move it
- icons[f][YPOS] += icons[f][DELTAY];
- // if its gone, reinit
- if (icons[f][YPOS] > display.height()) {
- icons[f][XPOS] = random(display.width());
- icons[f][YPOS] = 0;
- icons[f][DELTAY] = random(5) + 1;
- }
- }
- }
-}
-
-
-void testdrawchar(void) {
- display.setTextSize(1);
- display.setTextColor(WHITE);
- display.setCursor(0,0);
-
- for (uint8_t i=0; i < 168; i++) {
- if (i == '\n') continue;
- display.write(i);
- if ((i > 0) && (i % 21 == 0))
- display.println();
- }
- display.display();
- delay(1);
-}
-
-void testdrawcircle(void) {
- for (int16_t i=0; i0; i-=5) {
- display.fillTriangle(display.width()/2, display.height()/2-i,
- display.width()/2-i, display.height()/2+i,
- display.width()/2+i, display.height()/2+i, WHITE);
- if (color == WHITE) color = BLACK;
- else color = WHITE;
- display.display();
- delay(1);
- }
-}
-
-void testdrawroundrect(void) {
- for (int16_t i=0; i=0; i-=4) {
- display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
- display.display();
- delay(1);
- }
- delay(250);
-
- display.clearDisplay();
- for (int16_t i=display.width()-1; i>=0; i-=4) {
- display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
- display.display();
- delay(1);
- }
- for (int16_t i=display.height()-1; i>=0; i-=4) {
- display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
- display.display();
- delay(1);
- }
- delay(250);
-
- display.clearDisplay();
- for (int16_t i=0; i http://www.adafruit.com/category/63_98
-
-This example is for a 128x32 size display using SPI to communicate
-4 or 5 pins are required to interface
-
-Adafruit invests time and resources providing this open source code,
-please support Adafruit and open-source hardware by purchasing
-products from Adafruit!
-
-Written by Limor Fried/Ladyada for Adafruit Industries.
-BSD license, check license.txt for more information
-All text above, and the splash screen must be included in any redistribution
-*********************************************************************/
-
-#include
-#include
-#include
-#include
-
-// If using software SPI (the default case):
-#define OLED_MOSI 9
-#define OLED_CLK 10
-#define OLED_DC 11
-#define OLED_CS 12
-#define OLED_RESET 13
-Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
-
-/* Uncomment this block to use hardware SPI
-#define OLED_DC 6
-#define OLED_CS 7
-#define OLED_RESET 8
-Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);
-*/
-
-#define NUMFLAKES 10
-#define XPOS 0
-#define YPOS 1
-#define DELTAY 2
-
-#define LOGO16_GLCD_HEIGHT 16
-#define LOGO16_GLCD_WIDTH 16
-static const unsigned char PROGMEM logo16_glcd_bmp[] =
-{ B00000000, B11000000,
- B00000001, B11000000,
- B00000001, B11000000,
- B00000011, B11100000,
- B11110011, B11100000,
- B11111110, B11111000,
- B01111110, B11111111,
- B00110011, B10011111,
- B00011111, B11111100,
- B00001101, B01110000,
- B00011011, B10100000,
- B00111111, B11100000,
- B00111111, B11110000,
- B01111100, B11110000,
- B01110000, B01110000,
- B00000000, B00110000 };
-
-#if (SSD1306_LCDHEIGHT != 32)
-#error("Height incorrect, please fix Adafruit_SSD1306.h!");
-#endif
-
-void setup() {
- Serial.begin(9600);
-
- // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
- display.begin(SSD1306_SWITCHCAPVCC);
- // init done
-
- // Show image buffer on the display hardware.
- // Since the buffer is intialized with an Adafruit splashscreen
- // internally, this will display the splashscreen.
- display.display();
- delay(2000);
-
- // Clear the buffer.
- display.clearDisplay();
-
- // draw a single pixel
- display.drawPixel(10, 10, WHITE);
- // Show the display buffer on the hardware.
- // NOTE: You _must_ call display after making any drawing commands
- // to make them visible on the display hardware!
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw many lines
- testdrawline();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw rectangles
- testdrawrect();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw multiple rectangles
- testfillrect();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw mulitple circles
- testdrawcircle();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw a white circle, 10 pixel radius
- display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
- display.display();
- delay(2000);
- display.clearDisplay();
-
- testdrawroundrect();
- delay(2000);
- display.clearDisplay();
-
- testfillroundrect();
- delay(2000);
- display.clearDisplay();
-
- testdrawtriangle();
- delay(2000);
- display.clearDisplay();
-
- testfilltriangle();
- delay(2000);
- display.clearDisplay();
-
- // draw the first ~12 characters in the font
- testdrawchar();
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // draw scrolling text
- testscrolltext();
- delay(2000);
- display.clearDisplay();
-
- // text display tests
- display.setTextSize(1);
- display.setTextColor(WHITE);
- display.setCursor(0,0);
- display.println("Hello, world!");
- display.setTextColor(BLACK, WHITE); // 'inverted' text
- display.println(3.141592);
- display.setTextSize(2);
- display.setTextColor(WHITE);
- display.print("0x"); display.println(0xDEADBEEF, HEX);
- display.display();
- delay(2000);
- display.clearDisplay();
-
- // miniature bitmap display
- display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1);
- display.display();
-
- // invert the display
- display.invertDisplay(true);
- delay(1000);
- display.invertDisplay(false);
- delay(1000);
- display.clearDisplay();
-
- // draw a bitmap icon and 'animate' movement
- testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
-}
-
-
-void loop() {
-
-}
-
-
-void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
- uint8_t icons[NUMFLAKES][3];
-
- // initialize
- for (uint8_t f=0; f< NUMFLAKES; f++) {
- icons[f][XPOS] = random(display.width());
- icons[f][YPOS] = 0;
- icons[f][DELTAY] = random(5) + 1;
-
- Serial.print("x: ");
- Serial.print(icons[f][XPOS], DEC);
- Serial.print(" y: ");
- Serial.print(icons[f][YPOS], DEC);
- Serial.print(" dy: ");
- Serial.println(icons[f][DELTAY], DEC);
- }
-
- while (1) {
- // draw each icon
- for (uint8_t f=0; f< NUMFLAKES; f++) {
- display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
- }
- display.display();
- delay(200);
-
- // then erase it + move it
- for (uint8_t f=0; f< NUMFLAKES; f++) {
- display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK);
- // move it
- icons[f][YPOS] += icons[f][DELTAY];
- // if its gone, reinit
- if (icons[f][YPOS] > display.height()) {
- icons[f][XPOS] = random(display.width());
- icons[f][YPOS] = 0;
- icons[f][DELTAY] = random(5) + 1;
- }
- }
- }
-}
-
-
-void testdrawchar(void) {
- display.setTextSize(1);
- display.setTextColor(WHITE);
- display.setCursor(0,0);
-
- for (uint8_t i=0; i < 168; i++) {
- if (i == '\n') continue;
- display.write(i);
- if ((i > 0) && (i % 21 == 0))
- display.println();
- }
- display.display();
-}
-
-void testdrawcircle(void) {
- for (int16_t i=0; i0; i-=5) {
- display.fillTriangle(display.width()/2, display.height()/2-i,
- display.width()/2-i, display.height()/2+i,
- display.width()/2+i, display.height()/2+i, WHITE);
- if (color == WHITE) color = BLACK;
- else color = WHITE;
- display.display();
- }
-}
-
-void testdrawroundrect(void) {
- for (int16_t i=0; i=0; i-=4) {
- display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
- display.display();
- }
- delay(250);
-
- display.clearDisplay();
- for (int16_t i=display.width()-1; i>=0; i-=4) {
- display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
- display.display();
- }
- for (int16_t i=display.height()-1; i>=0; i-=4) {
- display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
- display.display();
- }
- delay(250);
-
- display.clearDisplay();
- for (int16_t i=0; i
-sentence=SSD1306 oled driver library for 'monochrome' 128x64 and 128x32 OLEDs!
-paragraph=SSD1306 oled driver library for 'monochrome' 128x64 and 128x32 OLEDs!
-category=Display
-url=https://github.com/adafruit/Adafruit_SSD1306
-architectures=*
diff --git a/lib/Adafruit_SSD1306-1.1.2/.github/ISSUE_TEMPLATE.md b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md
similarity index 100%
rename from lib/Adafruit_SSD1306-1.1.2/.github/ISSUE_TEMPLATE.md
rename to lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md
diff --git a/lib/Adafruit_SSD1306-1.1.2/.github/PULL_REQUEST_TEMPLATE.md b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md
similarity index 100%
rename from lib/Adafruit_SSD1306-1.1.2/.github/PULL_REQUEST_TEMPLATE.md
rename to lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore
new file mode 100644
index 000000000..c2a26c038
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore
@@ -0,0 +1,4 @@
+# Our handy .gitignore for automation ease
+Doxyfile*
+doxygen_sqlite3.db
+html
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml
new file mode 100644
index 000000000..1d9184e52
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml
@@ -0,0 +1,29 @@
+language: c
+sudo: false
+cache:
+ directories:
+ - ~/arduino_ide
+ - ~/.arduino15/packages/
+git:
+ depth: false
+ quiet: true
+env:
+ global:
+ - ARDUINO_IDE_VERSION="1.8.5"
+ - PRETTYNAME="Adafruit SSD1306"
+# Optional, will default to "$TRAVIS_BUILD_DIR/Doxyfile"
+# - DOXYFILE: $TRAVIS_BUILD_DIR/Doxyfile
+
+before_install:
+ - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
+
+install:
+ - arduino --install-library "Adafruit GFX Library"
+
+script:
+ - build_main_platforms
+
+# Generate and deploy documentation
+after_success:
+ - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh)
+ - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp
new file mode 100644
index 000000000..9015c6e83
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp
@@ -0,0 +1,1139 @@
+/*!
+ * @file Adafruit_SSD1306.cpp
+ *
+ * @mainpage Arduino library for monochrome OLEDs based on SSD1306 drivers.
+ *
+ * @section intro_sec Introduction
+ *
+ * This is documentation for Adafruit's SSD1306 library for monochrome
+ * OLED displays: http://www.adafruit.com/category/63_98
+ *
+ * These displays use I2C or SPI to communicate. I2C requires 2 pins
+ * (SCL+SDA) and optionally a RESET pin. SPI requires 4 pins (MOSI, SCK,
+ * select, data/command) and optionally a reset pin. Hardware SPI or
+ * 'bitbang' software SPI are both supported.
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing
+ * products from Adafruit!
+ *
+ * @section dependencies Dependencies
+ *
+ * This library depends on
+ * Adafruit_GFX being present on your system. Please make sure you have
+ * installed the latest version before using this library.
+ *
+ * @section author Author
+ *
+ * Written by Limor Fried/Ladyada for Adafruit Industries, with
+ * contributions from the open source community.
+ *
+ * @section license License
+ *
+ * BSD license, all text above, and the splash screen included below,
+ * must be included in any redistribution.
+ *
+ */
+
+#ifdef __AVR__
+ #include
+#elif defined(ESP8266) || defined(ESP32)
+ #include
+#else
+ #define pgm_read_byte(addr) \
+ (*(const unsigned char *)(addr)) ///< PROGMEM workaround for non-AVR
+#endif
+
+#if !defined(__ARM_ARCH) && !defined(ENERGIA) && !defined(ESP8266) && !defined(ESP32) && !defined(__arc__)
+ #include
+#endif
+
+#include
+#include "Adafruit_SSD1306.h"
+#include "splash.h"
+
+// SOME DEFINES AND STATIC VARIABLES USED INTERNALLY -----------------------
+
+#if defined(BUFFER_LENGTH)
+ #define WIRE_MAX BUFFER_LENGTH ///< AVR or similar Wire lib
+#elif defined(SERIAL_BUFFER_SIZE)
+ #define WIRE_MAX (SERIAL_BUFFER_SIZE-1) ///< Newer Wire uses RingBuffer
+#else
+ #define WIRE_MAX 32 ///< Use common Arduino core default
+#endif
+
+#define ssd1306_swap(a, b) \
+ (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) ///< No-temp-var swap operation
+
+#if ARDUINO >= 100
+ #define WIRE_WRITE wire->write ///< Wire write function in recent Arduino lib
+#else
+ #define WIRE_WRITE wire->send ///< Wire write function in older Arduino lib
+#endif
+
+#ifdef HAVE_PORTREG
+ #define SSD1306_SELECT *csPort &= ~csPinMask; ///< Device select
+ #define SSD1306_DESELECT *csPort |= csPinMask; ///< Device deselect
+ #define SSD1306_MODE_COMMAND *dcPort &= ~dcPinMask; ///< Command mode
+ #define SSD1306_MODE_DATA *dcPort |= dcPinMask; ///< Data mode
+#else
+ #define SSD1306_SELECT digitalWrite(csPin, LOW); ///< Device select
+ #define SSD1306_DESELECT digitalWrite(csPin, HIGH); ///< Device deselect
+ #define SSD1306_MODE_COMMAND digitalWrite(dcPin, LOW); ///< Command mode
+ #define SSD1306_MODE_DATA digitalWrite(dcPin, HIGH); ///< Data mode
+#endif
+
+#if (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER)
+ #define SETWIRECLOCK wire->setClock(wireClk) ///< Set before I2C transfer
+ #define RESWIRECLOCK wire->setClock(restoreClk) ///< Restore after I2C xfer
+#else // setClock() is not present in older Arduino Wire lib (or WICED)
+ #define SETWIRECLOCK ///< Dummy stand-in define
+ #define RESWIRECLOCK ///< keeps compiler happy
+#endif
+
+#if defined(SPI_HAS_TRANSACTION)
+ #define SPI_TRANSACTION_START spi->beginTransaction(spiSettings) ///< Pre-SPI
+ #define SPI_TRANSACTION_END spi->endTransaction() ///< Post-SPI
+#else // SPI transactions likewise not present in older Arduino SPI lib
+ #define SPI_TRANSACTION_START ///< Dummy stand-in define
+ #define SPI_TRANSACTION_END ///< keeps compiler happy
+#endif
+
+// The definition of 'transaction' is broadened a bit in the context of
+// this library -- referring not just to SPI transactions (if supported
+// in the version of the SPI library being used), but also chip select
+// (if SPI is being used, whether hardware or soft), and also to the
+// beginning and end of I2C transfers (the Wire clock may be sped up before
+// issuing data to the display, then restored to the default rate afterward
+// so other I2C device types still work). All of these are encapsulated
+// in the TRANSACTION_* macros.
+
+// Check first if Wire, then hardware SPI, then soft SPI:
+#define TRANSACTION_START \
+ if(wire) { \
+ SETWIRECLOCK; \
+ } else { \
+ if(spi) { \
+ SPI_TRANSACTION_START; \
+ } \
+ SSD1306_SELECT; \
+ } ///< Wire, SPI or bitbang transfer setup
+#define TRANSACTION_END \
+ if(wire) { \
+ RESWIRECLOCK; \
+ } else { \
+ SSD1306_DESELECT; \
+ if(spi) { \
+ SPI_TRANSACTION_END; \
+ } \
+ } ///< Wire, SPI or bitbang transfer end
+
+// CONSTRUCTORS, DESTRUCTOR ------------------------------------------------
+
+/*!
+ @brief Constructor for I2C-interfaced SSD1306 displays.
+ @param w
+ Display width in pixels
+ @param h
+ Display height in pixels
+ @param twi
+ Pointer to an existing TwoWire instance (e.g. &Wire, the
+ microcontroller's primary I2C bus).
+ @param rst_pin
+ Reset pin (using Arduino pin numbering), or -1 if not used
+ (some displays might be wired to share the microcontroller's
+ reset pin).
+ @param clkDuring
+ Speed (in Hz) for Wire transmissions in SSD1306 library calls.
+ Defaults to 400000 (400 KHz), a known 'safe' value for most
+ microcontrollers, and meets the SSD1306 datasheet spec.
+ Some systems can operate I2C faster (800 KHz for ESP32, 1 MHz
+ for many other 32-bit MCUs), and some (perhaps not all)
+ SSD1306's can work with this -- so it's optionally be specified
+ here and is not a default behavior. (Ignored if using pre-1.5.7
+ Arduino software, which operates I2C at a fixed 100 KHz.)
+ @param clkAfter
+ Speed (in Hz) for Wire transmissions following SSD1306 library
+ calls. Defaults to 100000 (100 KHz), the default Arduino Wire
+ speed. This is done rather than leaving it at the 'during' speed
+ because other devices on the I2C bus might not be compatible
+ with the faster rate. (Ignored if using pre-1.5.7 Arduino
+ software, which operates I2C at a fixed 100 KHz.)
+ @return Adafruit_SSD1306 object.
+ @note Call the object's begin() function before use -- buffer
+ allocation is performed there!
+*/
+Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi,
+ int8_t rst_pin, uint32_t clkDuring, uint32_t clkAfter) :
+ Renderer(w, h), spi(NULL), wire(twi ? twi : &Wire), xbuffer(NULL),
+ mosiPin(-1), clkPin(-1), dcPin(-1), csPin(-1), rstPin(rst_pin),
+ wireClk(clkDuring), restoreClk(clkAfter) {
+}
+
+/*!
+ @brief Constructor for SPI SSD1306 displays, using software (bitbang)
+ SPI.
+ @param w
+ Display width in pixels
+ @param h
+ Display height in pixels
+ @param mosi_pin
+ MOSI (master out, slave in) pin (using Arduino pin numbering).
+ This transfers serial data from microcontroller to display.
+ @param sclk_pin
+ SCLK (serial clock) pin (using Arduino pin numbering).
+ This clocks each bit from MOSI.
+ @param dc_pin
+ Data/command pin (using Arduino pin numbering), selects whether
+ display is receiving commands (low) or data (high).
+ @param rst_pin
+ Reset pin (using Arduino pin numbering), or -1 if not used
+ (some displays might be wired to share the microcontroller's
+ reset pin).
+ @param cs_pin
+ Chip-select pin (using Arduino pin numbering) for sharing the
+ bus with other devices. Active low.
+ @return Adafruit_SSD1306 object.
+ @note Call the object's begin() function before use -- buffer
+ allocation is performed there!
+*/
+Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h,
+ int8_t mosi_pin, int8_t sclk_pin, int8_t dc_pin, int8_t rst_pin,
+ int8_t cs_pin) : Renderer(w, h), spi(NULL), wire(NULL), xbuffer(NULL),
+ mosiPin(mosi_pin), clkPin(sclk_pin), dcPin(dc_pin), csPin(cs_pin),
+ rstPin(rst_pin) {
+}
+
+/*!
+ @brief Constructor for SPI SSD1306 displays, using native hardware SPI.
+ @param w
+ Display width in pixels
+ @param h
+ Display height in pixels
+ @param spi
+ Pointer to an existing SPIClass instance (e.g. &SPI, the
+ microcontroller's primary SPI bus).
+ @param dc_pin
+ Data/command pin (using Arduino pin numbering), selects whether
+ display is receiving commands (low) or data (high).
+ @param rst_pin
+ Reset pin (using Arduino pin numbering), or -1 if not used
+ (some displays might be wired to share the microcontroller's
+ reset pin).
+ @param cs_pin
+ Chip-select pin (using Arduino pin numbering) for sharing the
+ bus with other devices. Active low.
+ @param bitrate
+ SPI clock rate for transfers to this display. Default if
+ unspecified is 8000000UL (8 MHz).
+ @return Adafruit_SSD1306 object.
+ @note Call the object's begin() function before use -- buffer
+ allocation is performed there!
+*/
+Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, SPIClass *spi,
+ int8_t dc_pin, int8_t rst_pin, int8_t cs_pin, uint32_t bitrate) :
+ Renderer(w, h), spi(spi ? spi : &SPI), wire(NULL), xbuffer(NULL),
+ mosiPin(-1), clkPin(-1), dcPin(dc_pin), csPin(cs_pin), rstPin(rst_pin) {
+#ifdef SPI_HAS_TRANSACTION
+ spiSettings = SPISettings(bitrate, MSBFIRST, SPI_MODE0);
+#endif
+}
+
+/*!
+ @brief DEPRECATED constructor for SPI SSD1306 displays, using software
+ (bitbang) SPI. Provided for older code to maintain compatibility
+ with the current library. Screen size is determined by enabling
+ one of the SSD1306_* size defines in Adafruit_SSD1306.h. New
+ code should NOT use this.
+ @param mosi_pin
+ MOSI (master out, slave in) pin (using Arduino pin numbering).
+ This transfers serial data from microcontroller to display.
+ @param sclk_pin
+ SCLK (serial clock) pin (using Arduino pin numbering).
+ This clocks each bit from MOSI.
+ @param dc_pin
+ Data/command pin (using Arduino pin numbering), selects whether
+ display is receiving commands (low) or data (high).
+ @param rst_pin
+ Reset pin (using Arduino pin numbering), or -1 if not used
+ (some displays might be wired to share the microcontroller's
+ reset pin).
+ @param cs_pin
+ Chip-select pin (using Arduino pin numbering) for sharing the
+ bus with other devices. Active low.
+ @return Adafruit_SSD1306 object.
+ @note Call the object's begin() function before use -- buffer
+ allocation is performed there!
+*/
+Adafruit_SSD1306::Adafruit_SSD1306(int8_t mosi_pin, int8_t sclk_pin,
+ int8_t dc_pin, int8_t rst_pin, int8_t cs_pin) :
+ Renderer(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT), spi(NULL), wire(NULL),
+ xbuffer(NULL), mosiPin(mosi_pin), clkPin(sclk_pin), dcPin(dc_pin),
+ csPin(cs_pin), rstPin(rst_pin) {
+}
+
+/*!
+ @brief DEPRECATED constructor for SPI SSD1306 displays, using native
+ hardware SPI. Provided for older code to maintain compatibility
+ with the current library. Screen size is determined by enabling
+ one of the SSD1306_* size defines in Adafruit_SSD1306.h. New
+ code should NOT use this. Only the primary SPI bus is supported,
+ and bitrate is fixed at 8 MHz.
+ @param dc_pin
+ Data/command pin (using Arduino pin numbering), selects whether
+ display is receiving commands (low) or data (high).
+ @param rst_pin
+ Reset pin (using Arduino pin numbering), or -1 if not used
+ (some displays might be wired to share the microcontroller's
+ reset pin).
+ @param cs_pin
+ Chip-select pin (using Arduino pin numbering) for sharing the
+ bus with other devices. Active low.
+ @return Adafruit_SSD1306 object.
+ @note Call the object's begin() function before use -- buffer
+ allocation is performed there!
+*/
+Adafruit_SSD1306::Adafruit_SSD1306(int8_t dc_pin, int8_t rst_pin,
+ int8_t cs_pin) : Renderer(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT),
+ spi(&SPI), wire(NULL), xbuffer(NULL), mosiPin(-1), clkPin(-1),
+ dcPin(dc_pin), csPin(cs_pin), rstPin(rst_pin) {
+#ifdef SPI_HAS_TRANSACTION
+ spiSettings = SPISettings(8000000, MSBFIRST, SPI_MODE0);
+#endif
+}
+
+/*!
+ @brief DEPRECATED constructor for I2C SSD1306 displays. Provided for
+ older code to maintain compatibility with the current library.
+ Screen size is determined by enabling one of the SSD1306_* size
+ defines in Adafruit_SSD1306.h. New code should NOT use this.
+ Only the primary I2C bus is supported.
+ @param rst_pin
+ Reset pin (using Arduino pin numbering), or -1 if not used
+ (some displays might be wired to share the microcontroller's
+ reset pin).
+ @return Adafruit_SSD1306 object.
+ @note Call the object's begin() function before use -- buffer
+ allocation is performed there!
+*/
+Adafruit_SSD1306::Adafruit_SSD1306(int8_t rst_pin) :
+ Renderer(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT), spi(NULL), wire(&Wire),
+ xbuffer(NULL), mosiPin(-1), clkPin(-1), dcPin(-1), csPin(-1),
+ rstPin(rst_pin) {
+}
+
+/*!
+ @brief Destructor for Adafruit_SSD1306 object.
+*/
+Adafruit_SSD1306::~Adafruit_SSD1306(void) {
+ if(buffer) {
+ free(buffer);
+ buffer = NULL;
+ }
+}
+
+// LOW-LEVEL UTILS ---------------------------------------------------------
+
+// Issue single byte out SPI, either soft or hardware as appropriate.
+// SPI transaction/selection must be performed in calling function.
+inline void Adafruit_SSD1306::SPIwrite(uint8_t d) {
+ if(spi) {
+ (void)spi->transfer(d);
+ } else {
+ for(uint8_t bit = 0x80; bit; bit >>= 1) {
+#ifdef HAVE_PORTREG
+ if(d & bit) *mosiPort |= mosiPinMask;
+ else *mosiPort &= ~mosiPinMask;
+ *clkPort |= clkPinMask; // Clock high
+ *clkPort &= ~clkPinMask; // Clock low
+#else
+ digitalWrite(mosiPin, d & bit);
+ digitalWrite(clkPin , HIGH);
+ digitalWrite(clkPin , LOW);
+#endif
+ }
+ }
+}
+
+// Issue single command to SSD1306, using I2C or hard/soft SPI as needed.
+// Because command calls are often grouped, SPI transaction and selection
+// must be started/ended in calling function for efficiency.
+// This is a private function, not exposed (see ssd1306_command() instead).
+void Adafruit_SSD1306::ssd1306_command1(uint8_t c) {
+ if(wire) { // I2C
+ wire->beginTransmission(i2caddr);
+ WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0
+ WIRE_WRITE(c);
+ wire->endTransmission();
+ } else { // SPI (hw or soft) -- transaction started in calling function
+ SSD1306_MODE_COMMAND
+ SPIwrite(c);
+ }
+}
+
+// Issue list of commands to SSD1306, same rules as above re: transactions.
+// This is a private function, not exposed.
+void Adafruit_SSD1306::ssd1306_commandList(const uint8_t *c, uint8_t n) {
+ if(wire) { // I2C
+ wire->beginTransmission(i2caddr);
+ WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0
+ uint8_t bytesOut = 1;
+ while(n--) {
+ if(bytesOut >= WIRE_MAX) {
+ wire->endTransmission();
+ wire->beginTransmission(i2caddr);
+ WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0
+ bytesOut = 1;
+ }
+ WIRE_WRITE(pgm_read_byte(c++));
+ bytesOut++;
+ }
+ wire->endTransmission();
+ } else { // SPI -- transaction started in calling function
+ SSD1306_MODE_COMMAND
+ while(n--) SPIwrite(pgm_read_byte(c++));
+ }
+}
+
+// A public version of ssd1306_command1(), for existing user code that
+// might rely on that function. This encapsulates the command transfer
+// in a transaction start/end, similar to old library's handling of it.
+/*!
+ @brief Issue a single low-level command directly to the SSD1306
+ display, bypassing the library.
+ @param c
+ Command to issue (0x00 to 0xFF, see datasheet).
+ @return None (void).
+*/
+void Adafruit_SSD1306::ssd1306_command(uint8_t c) {
+ TRANSACTION_START
+ ssd1306_command1(c);
+ TRANSACTION_END
+}
+
+// ALLOCATE & INIT DISPLAY -------------------------------------------------
+
+/*!
+ @brief Allocate RAM for image buffer, initialize peripherals and pins.
+ @param vcs
+ VCC selection. Pass SSD1306_SWITCHCAPVCC to generate the display
+ voltage (step up) from the 3.3V source, or SSD1306_EXTERNALVCC
+ otherwise. Most situations with Adafruit SSD1306 breakouts will
+ want SSD1306_SWITCHCAPVCC.
+ @param addr
+ I2C address of corresponding SSD1306 display (or pass 0 to use
+ default of 0x3C for 128x32 display, 0x3D for all others).
+ SPI displays (hardware or software) do not use addresses, but
+ this argument is still required (pass 0 or any value really,
+ it will simply be ignored). Default if unspecified is 0.
+ @param reset
+ If true, and if the reset pin passed to the constructor is
+ valid, a hard reset will be performed before initializing the
+ display. If using multiple SSD1306 displays on the same bus, and
+ if they all share the same reset pin, you should only pass true
+ on the first display being initialized, false on all others,
+ else the already-initialized displays would be reset. Default if
+ unspecified is true.
+ @param periphBegin
+ If true, and if a hardware peripheral is being used (I2C or SPI,
+ but not software SPI), call that peripheral's begin() function,
+ else (false) it has already been done in one's sketch code.
+ Cases where false might be used include multiple displays or
+ other devices sharing a common bus, or situations on some
+ platforms where a nonstandard begin() function is available
+ (e.g. a TwoWire interface on non-default pins, as can be done
+ on the ESP8266 and perhaps others).
+ @return true on successful allocation/init, false otherwise.
+ Well-behaved code should check the return value before
+ proceeding.
+ @note MUST call this function before any drawing or updates!
+*/
+boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset,
+ boolean periphBegin) {
+
+// if((!buffer) && !(buffer = (uint8_t *)malloc(WIDTH * ((HEIGHT + 7) / 8))))
+// return false;
+
+ clearDisplay();
+
+ /*
+ if(HEIGHT > 32) {
+ drawBitmap((WIDTH - splash1_width) / 2, (HEIGHT - splash1_height) / 2,
+ splash1_data, splash1_width, splash1_height, 1);
+ } else {
+ drawBitmap((WIDTH - splash2_width) / 2, (HEIGHT - splash2_height) / 2,
+ splash2_data, splash2_width, splash2_height, 1);
+ }
+*/
+ vccstate = vcs;
+
+ // Setup pin directions
+ if(wire) { // Using I2C
+ // If I2C address is unspecified, use default
+ // (0x3C for 32-pixel-tall displays, 0x3D for all others).
+ i2caddr = addr ? addr : ((HEIGHT == 32) ? 0x3C : 0x3D);
+ // TwoWire begin() function might be already performed by the calling
+ // function if it has unusual circumstances (e.g. TWI variants that
+ // can accept different SDA/SCL pins, or if two SSD1306 instances
+ // with different addresses -- only a single begin() is needed).
+ if(periphBegin) wire->begin();
+ } else { // Using one of the SPI modes, either soft or hardware
+ pinMode(dcPin, OUTPUT); // Set data/command pin as output
+ pinMode(csPin, OUTPUT); // Same for chip select
+#ifdef HAVE_PORTREG
+ dcPort = (PortReg *)portOutputRegister(digitalPinToPort(dcPin));
+ dcPinMask = digitalPinToBitMask(dcPin);
+ csPort = (PortReg *)portOutputRegister(digitalPinToPort(csPin));
+ csPinMask = digitalPinToBitMask(csPin);
+#endif
+ SSD1306_DESELECT
+ if(spi) { // Hardware SPI
+ // SPI peripheral begin same as wire check above.
+ if(periphBegin) spi->begin();
+ } else { // Soft SPI
+ pinMode(mosiPin, OUTPUT); // MOSI and SCLK outputs
+ pinMode(clkPin , OUTPUT);
+#ifdef HAVE_PORTREG
+ mosiPort = (PortReg *)portOutputRegister(digitalPinToPort(mosiPin));
+ mosiPinMask = digitalPinToBitMask(mosiPin);
+ clkPort = (PortReg *)portOutputRegister(digitalPinToPort(clkPin));
+ clkPinMask = digitalPinToBitMask(clkPin);
+ *clkPort &= ~clkPinMask; // Clock low
+#else
+ digitalWrite(clkPin, LOW); // Clock low
+#endif
+ }
+ }
+
+ // Reset SSD1306 if requested and reset pin specified in constructor
+ if(reset && (rstPin >= 0)) {
+ pinMode( rstPin, OUTPUT);
+ digitalWrite(rstPin, HIGH);
+ delay(1); // VDD goes high at start, pause for 1 ms
+ digitalWrite(rstPin, LOW); // Bring reset low
+ delay(10); // Wait 10 ms
+ digitalWrite(rstPin, HIGH); // Bring out of reset
+ }
+
+ TRANSACTION_START
+
+ // Init sequence
+ static const uint8_t PROGMEM init1[] = {
+ SSD1306_DISPLAYOFF, // 0xAE
+ SSD1306_SETDISPLAYCLOCKDIV, // 0xD5
+ 0x80, // the suggested ratio 0x80
+ SSD1306_SETMULTIPLEX }; // 0xA8
+ ssd1306_commandList(init1, sizeof(init1));
+ ssd1306_command1(HEIGHT - 1);
+
+ static const uint8_t PROGMEM init2[] = {
+ SSD1306_SETDISPLAYOFFSET, // 0xD3
+ 0x0, // no offset
+ SSD1306_SETSTARTLINE | 0x0, // line #0
+ SSD1306_CHARGEPUMP }; // 0x8D
+ ssd1306_commandList(init2, sizeof(init2));
+
+ ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0x14);
+
+ static const uint8_t PROGMEM init3[] = {
+ SSD1306_MEMORYMODE, // 0x20
+ 0x00, // 0x0 act like ks0108
+ SSD1306_SEGREMAP | 0x1,
+ SSD1306_COMSCANDEC };
+ ssd1306_commandList(init3, sizeof(init3));
+
+ if((WIDTH == 128) && (HEIGHT == 32)) {
+ static const uint8_t PROGMEM init4a[] = {
+ SSD1306_SETCOMPINS, // 0xDA
+ 0x02,
+ SSD1306_SETCONTRAST, // 0x81
+ 0x8F };
+ ssd1306_commandList(init4a, sizeof(init4a));
+ } else if((WIDTH == 128) && (HEIGHT == 64)) {
+ static const uint8_t PROGMEM init4b[] = {
+ SSD1306_SETCOMPINS, // 0xDA
+ 0x12,
+ SSD1306_SETCONTRAST }; // 0x81
+ ssd1306_commandList(init4b, sizeof(init4b));
+ ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF);
+ } else if((WIDTH == 96) && (HEIGHT == 16)) {
+ static const uint8_t PROGMEM init4c[] = {
+ SSD1306_SETCOMPINS, // 0xDA
+ 0x2, // ada x12
+ SSD1306_SETCONTRAST }; // 0x81
+ ssd1306_commandList(init4c, sizeof(init4c));
+ ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0xAF);
+ } else {
+ // Other screen varieties -- TBD
+ }
+
+ ssd1306_command1(SSD1306_SETPRECHARGE); // 0xd9
+ ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x22 : 0xF1);
+ static const uint8_t PROGMEM init5[] = {
+ SSD1306_SETVCOMDETECT, // 0xDB
+ 0x40,
+ SSD1306_DISPLAYALLON_RESUME, // 0xA4
+ SSD1306_NORMALDISPLAY, // 0xA6
+ SSD1306_DEACTIVATE_SCROLL,
+ SSD1306_DISPLAYON }; // Main screen turn on
+ ssd1306_commandList(init5, sizeof(init5));
+
+ TRANSACTION_END
+
+ return true; // Success
+}
+
+
+void Adafruit_SSD1306::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
+// ignore update mode
+ //if (p==DISPLAY_INIT_MODE) {
+ setRotation(rot);
+ invertDisplay(false);
+ setTextWrap(false); // Allow text to run off edges
+ cp437(true);
+ setTextFont(font);
+ setTextSize(size);
+ setTextColor(WHITE,BLACK);
+ setCursor(0,0);
+ fillScreen(BLACK);
+ Updateframe();
+ //}
+}
+
+#if 0
+
+// DRAWING FUNCTIONS -------------------------------------------------------
+
+/*!
+ @brief Set/clear/invert a single pixel. This is also invoked by the
+ Adafruit_GFX library in generating many higher-level graphics
+ primitives.
+ @param x
+ Column of display -- 0 at left to (screen width - 1) at right.
+ @param y
+ Row of display -- 0 at top to (screen height -1) at bottom.
+ @param color
+ Pixel color, one of: BLACK, WHITE or INVERT.
+ @return None (void).
+ @note Changes buffer contents only, no immediate effect on display.
+ Follow up with a call to display(), or with other graphics
+ commands as needed by one's own application.
+*/
+void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) {
+ if((x >= 0) && (x < width()) && (y >= 0) && (y < height())) {
+ // Pixel is in-bounds. Rotate coordinates if needed.
+ switch(getRotation()) {
+ case 1:
+ ssd1306_swap(x, y);
+ x = WIDTH - x - 1;
+ break;
+ case 2:
+ x = WIDTH - x - 1;
+ y = HEIGHT - y - 1;
+ break;
+ case 3:
+ ssd1306_swap(x, y);
+ y = HEIGHT - y - 1;
+ break;
+ }
+ switch(color) {
+ case WHITE: buffer[x + (y/8)*WIDTH] |= (1 << (y&7)); break;
+ case BLACK: buffer[x + (y/8)*WIDTH] &= ~(1 << (y&7)); break;
+ case INVERSE: buffer[x + (y/8)*WIDTH] ^= (1 << (y&7)); break;
+ }
+ }
+}
+
+/*!
+ @brief Clear contents of display buffer (set all pixels to off).
+ @return None (void).
+ @note Changes buffer contents only, no immediate effect on display.
+ Follow up with a call to display(), or with other graphics
+ commands as needed by one's own application.
+*/
+void Adafruit_SSD1306::clearDisplay(void) {
+ memset(buffer, 0, WIDTH * ((HEIGHT + 7) / 8));
+}
+
+/*!
+ @brief Draw a horizontal line. This is also invoked by the Adafruit_GFX
+ library in generating many higher-level graphics primitives.
+ @param x
+ Leftmost column -- 0 at left to (screen width - 1) at right.
+ @param y
+ Row of display -- 0 at top to (screen height -1) at bottom.
+ @param w
+ Width of line, in pixels.
+ @param color
+ Line color, one of: BLACK, WHITE or INVERT.
+ @return None (void).
+ @note Changes buffer contents only, no immediate effect on display.
+ Follow up with a call to display(), or with other graphics
+ commands as needed by one's own application.
+*/
+void Adafruit_SSD1306::drawFastHLine(
+ int16_t x, int16_t y, int16_t w, uint16_t color) {
+ boolean bSwap = false;
+ switch(rotation) {
+ case 1:
+ // 90 degree rotation, swap x & y for rotation, then invert x
+ bSwap = true;
+ ssd1306_swap(x, y);
+ x = WIDTH - x - 1;
+ break;
+ case 2:
+ // 180 degree rotation, invert x and y, then shift y around for height.
+ x = WIDTH - x - 1;
+ y = HEIGHT - y - 1;
+ x -= (w-1);
+ break;
+ case 3:
+ // 270 degree rotation, swap x & y for rotation,
+ // then invert y and adjust y for w (not to become h)
+ bSwap = true;
+ ssd1306_swap(x, y);
+ y = HEIGHT - y - 1;
+ y -= (w-1);
+ break;
+ }
+
+ if(bSwap) drawFastVLineInternal(x, y, w, color);
+ else drawFastHLineInternal(x, y, w, color);
+}
+
+
+
+/*!
+ @brief Draw a vertical line. This is also invoked by the Adafruit_GFX
+ library in generating many higher-level graphics primitives.
+ @param x
+ Column of display -- 0 at left to (screen width -1) at right.
+ @param y
+ Topmost row -- 0 at top to (screen height - 1) at bottom.
+ @param h
+ Height of line, in pixels.
+ @param color
+ Line color, one of: BLACK, WHITE or INVERT.
+ @return None (void).
+ @note Changes buffer contents only, no immediate effect on display.
+ Follow up with a call to display(), or with other graphics
+ commands as needed by one's own application.
+*/
+void Adafruit_SSD1306::drawFastVLine(
+ int16_t x, int16_t y, int16_t h, uint16_t color) {
+ boolean bSwap = false;
+ switch(rotation) {
+ case 1:
+ // 90 degree rotation, swap x & y for rotation,
+ // then invert x and adjust x for h (now to become w)
+ bSwap = true;
+ ssd1306_swap(x, y);
+ x = WIDTH - x - 1;
+ x -= (h-1);
+ break;
+ case 2:
+ // 180 degree rotation, invert x and y, then shift y around for height.
+ x = WIDTH - x - 1;
+ y = HEIGHT - y - 1;
+ y -= (h-1);
+ break;
+ case 3:
+ // 270 degree rotation, swap x & y for rotation, then invert y
+ bSwap = true;
+ ssd1306_swap(x, y);
+ y = HEIGHT - y - 1;
+ break;
+ }
+
+ if(bSwap) drawFastHLineInternal(x, y, h, color);
+ else drawFastVLineInternal(x, y, h, color);
+}
+#endif
+
+void Adafruit_SSD1306::drawFastHLineInternal(
+ int16_t x, int16_t y, int16_t w, uint16_t color) {
+
+ if((y >= 0) && (y < HEIGHT)) { // Y coord in bounds?
+ if(x < 0) { // Clip left
+ w += x;
+ x = 0;
+ }
+ if((x + w) > WIDTH) { // Clip right
+ w = (WIDTH - x);
+ }
+ if(w > 0) { // Proceed only if width is positive
+ uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x],
+ mask = 1 << (y & 7);
+ switch(color) {
+ case WHITE: while(w--) { *pBuf++ |= mask; }; break;
+ case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
+ case INVERSE: while(w--) { *pBuf++ ^= mask; }; break;
+ }
+ }
+ }
+}
+
+void Adafruit_SSD1306::drawFastVLineInternal(
+ int16_t x, int16_t __y, int16_t __h, uint16_t color) {
+
+ if((x >= 0) && (x < WIDTH)) { // X coord in bounds?
+ if(__y < 0) { // Clip top
+ __h += __y;
+ __y = 0;
+ }
+ if((__y + __h) > HEIGHT) { // Clip bottom
+ __h = (HEIGHT - __y);
+ }
+ if(__h > 0) { // Proceed only if height is now positive
+ // this display doesn't need ints for coordinates,
+ // use local byte registers for faster juggling
+ uint8_t y = __y, h = __h;
+ uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x];
+
+ // do the first partial byte, if necessary - this requires some masking
+ uint8_t mod = (y & 7);
+ if(mod) {
+ // mask off the high n bits we want to set
+ mod = 8 - mod;
+ // note - lookup table results in a nearly 10% performance
+ // improvement in fill* functions
+ // uint8_t mask = ~(0xFF >> mod);
+ static const uint8_t PROGMEM premask[8] =
+ { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
+ uint8_t mask = pgm_read_byte(&premask[mod]);
+ // adjust the mask if we're not going to reach the end of this byte
+ if(h < mod) mask &= (0XFF >> (mod - h));
+
+ switch(color) {
+ case WHITE: *pBuf |= mask; break;
+ case BLACK: *pBuf &= ~mask; break;
+ case INVERSE: *pBuf ^= mask; break;
+ }
+ pBuf += WIDTH;
+ }
+
+ if(h >= mod) { // More to go?
+ h -= mod;
+ // Write solid bytes while we can - effectively 8 rows at a time
+ if(h >= 8) {
+ if(color == INVERSE) {
+ // separate copy of the code so we don't impact performance of
+ // black/white write version with an extra comparison per loop
+ do {
+ *pBuf ^= 0xFF; // Invert byte
+ pBuf += WIDTH; // Advance pointer 8 rows
+ h -= 8; // Subtract 8 rows from height
+ } while(h >= 8);
+ } else {
+ // store a local value to work with
+ uint8_t val = (color != BLACK) ? 255 : 0;
+ do {
+ *pBuf = val; // Set byte
+ pBuf += WIDTH; // Advance pointer 8 rows
+ h -= 8; // Subtract 8 rows from height
+ } while(h >= 8);
+ }
+ }
+
+ if(h) { // Do the final partial byte, if necessary
+ mod = h & 7;
+ // this time we want to mask the low bits of the byte,
+ // vs the high bits we did above
+ // uint8_t mask = (1 << mod) - 1;
+ // note - lookup table results in a nearly 10% performance
+ // improvement in fill* functions
+ static const uint8_t PROGMEM postmask[8] =
+ { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
+ uint8_t mask = pgm_read_byte(&postmask[mod]);
+ switch(color) {
+ case WHITE: *pBuf |= mask; break;
+ case BLACK: *pBuf &= ~mask; break;
+ case INVERSE: *pBuf ^= mask; break;
+ }
+ }
+ }
+ } // endif positive height
+ } // endif x in bounds
+}
+
+/*!
+ @brief Return color of a single pixel in display buffer.
+ @param x
+ Column of display -- 0 at left to (screen width - 1) at right.
+ @param y
+ Row of display -- 0 at top to (screen height -1) at bottom.
+ @return true if pixel is set (usually WHITE, unless display invert mode
+ is enabled), false if clear (BLACK).
+ @note Reads from buffer contents; may not reflect current contents of
+ screen if display() has not been called.
+*/
+boolean Adafruit_SSD1306::getPixel(int16_t x, int16_t y) {
+ if((x >= 0) && (x < width()) && (y >= 0) && (y < height())) {
+ // Pixel is in-bounds. Rotate coordinates if needed.
+ switch(getRotation()) {
+ case 1:
+ ssd1306_swap(x, y);
+ x = WIDTH - x - 1;
+ break;
+ case 2:
+ x = WIDTH - x - 1;
+ y = HEIGHT - y - 1;
+ break;
+ case 3:
+ ssd1306_swap(x, y);
+ y = HEIGHT - y - 1;
+ break;
+ }
+ return (buffer[x + (y / 8) * WIDTH] & (1 << (y & 7)));
+ }
+ return false; // Pixel out of bounds
+}
+
+/*!
+ @brief Get base address of display buffer for direct reading or writing.
+ @return Pointer to an unsigned 8-bit array, column-major, columns padded
+ to full byte boundary if needed.
+*/
+uint8_t *Adafruit_SSD1306::getBuffer(void) {
+ return xbuffer;
+}
+
+
+// REFRESH DISPLAY ---------------------------------------------------------
+
+/*!
+ @brief Push data currently in RAM to SSD1306 display.
+ @return None (void).
+ @note Drawing operations are not visible until this function is
+ called. Call after each graphics command, or after a whole set
+ of graphics commands, as best needed by one's own application.
+*/
+void Adafruit_SSD1306::display(void) {
+ TRANSACTION_START
+ static const uint8_t PROGMEM dlist1[] = {
+ SSD1306_PAGEADDR,
+ 0, // Page start address
+ 0xFF, // Page end (not really, but works here)
+ SSD1306_COLUMNADDR,
+ 0 }; // Column start address
+ ssd1306_commandList(dlist1, sizeof(dlist1));
+ ssd1306_command1(WIDTH - 1); // Column end address
+
+#if defined(ESP8266)
+ // ESP8266 needs a periodic yield() call to avoid watchdog reset.
+ // With the limited size of SSD1306 displays, and the fast bitrate
+ // being used (1 MHz or more), I think one yield() immediately before
+ // a screen write and one immediately after should cover it. But if
+ // not, if this becomes a problem, yields() might be added in the
+ // 32-byte transfer condition below.
+ yield();
+#endif
+ uint16_t count = WIDTH * ((HEIGHT + 7) / 8);
+ uint8_t *ptr = buffer;
+ if(wire) { // I2C
+ wire->beginTransmission(i2caddr);
+ WIRE_WRITE((uint8_t)0x40);
+ uint8_t bytesOut = 1;
+ while(count--) {
+ if(bytesOut >= WIRE_MAX) {
+ wire->endTransmission();
+ wire->beginTransmission(i2caddr);
+ WIRE_WRITE((uint8_t)0x40);
+ bytesOut = 1;
+ }
+ WIRE_WRITE(*ptr++);
+ bytesOut++;
+ }
+ wire->endTransmission();
+ } else { // SPI
+ SSD1306_MODE_DATA
+ while(count--) SPIwrite(*ptr++);
+ }
+ TRANSACTION_END
+#if defined(ESP8266)
+ yield();
+#endif
+}
+
+// SCROLLING FUNCTIONS -----------------------------------------------------
+
+/*!
+ @brief Activate a right-handed scroll for all or part of the display.
+ @param start
+ First row.
+ @param stop
+ Last row.
+ @return None (void).
+*/
+// To scroll the whole display, run: display.startscrollright(0x00, 0x0F)
+void Adafruit_SSD1306::startscrollright(uint8_t start, uint8_t stop) {
+ TRANSACTION_START
+ static const uint8_t PROGMEM scrollList1a[] = {
+ SSD1306_RIGHT_HORIZONTAL_SCROLL,
+ 0X00 };
+ ssd1306_commandList(scrollList1a, sizeof(scrollList1a));
+ ssd1306_command1(start);
+ ssd1306_command1(0X00);
+ ssd1306_command1(stop);
+ static const uint8_t PROGMEM scrollList1b[] = {
+ 0X00,
+ 0XFF,
+ SSD1306_ACTIVATE_SCROLL };
+ ssd1306_commandList(scrollList1b, sizeof(scrollList1b));
+ TRANSACTION_END
+}
+
+/*!
+ @brief Activate a left-handed scroll for all or part of the display.
+ @param start
+ First row.
+ @param stop
+ Last row.
+ @return None (void).
+*/
+// To scroll the whole display, run: display.startscrollleft(0x00, 0x0F)
+void Adafruit_SSD1306::startscrollleft(uint8_t start, uint8_t stop) {
+ TRANSACTION_START
+ static const uint8_t PROGMEM scrollList2a[] = {
+ SSD1306_LEFT_HORIZONTAL_SCROLL,
+ 0X00 };
+ ssd1306_commandList(scrollList2a, sizeof(scrollList2a));
+ ssd1306_command1(start);
+ ssd1306_command1(0X00);
+ ssd1306_command1(stop);
+ static const uint8_t PROGMEM scrollList2b[] = {
+ 0X00,
+ 0XFF,
+ SSD1306_ACTIVATE_SCROLL };
+ ssd1306_commandList(scrollList2b, sizeof(scrollList2b));
+ TRANSACTION_END
+}
+
+/*!
+ @brief Activate a diagonal scroll for all or part of the display.
+ @param start
+ First row.
+ @param stop
+ Last row.
+ @return None (void).
+*/
+// display.startscrolldiagright(0x00, 0x0F)
+void Adafruit_SSD1306::startscrolldiagright(uint8_t start, uint8_t stop) {
+ TRANSACTION_START
+ static const uint8_t PROGMEM scrollList3a[] = {
+ SSD1306_SET_VERTICAL_SCROLL_AREA,
+ 0X00 };
+ ssd1306_commandList(scrollList3a, sizeof(scrollList3a));
+ ssd1306_command1(HEIGHT);
+ static const uint8_t PROGMEM scrollList3b[] = {
+ SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL,
+ 0X00 };
+ ssd1306_commandList(scrollList3b, sizeof(scrollList3b));
+ ssd1306_command1(start);
+ ssd1306_command1(0X00);
+ ssd1306_command1(stop);
+ static const uint8_t PROGMEM scrollList3c[] = {
+ 0X01,
+ SSD1306_ACTIVATE_SCROLL };
+ ssd1306_commandList(scrollList3c, sizeof(scrollList3c));
+ TRANSACTION_END
+}
+
+/*!
+ @brief Activate alternate diagonal scroll for all or part of the display.
+ @param start
+ First row.
+ @param stop
+ Last row.
+ @return None (void).
+*/
+// To scroll the whole display, run: display.startscrolldiagleft(0x00, 0x0F)
+void Adafruit_SSD1306::startscrolldiagleft(uint8_t start, uint8_t stop) {
+ TRANSACTION_START
+ static const uint8_t PROGMEM scrollList4a[] = {
+ SSD1306_SET_VERTICAL_SCROLL_AREA,
+ 0X00 };
+ ssd1306_commandList(scrollList4a, sizeof(scrollList4a));
+ ssd1306_command1(HEIGHT);
+ static const uint8_t PROGMEM scrollList4b[] = {
+ SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL,
+ 0X00 };
+ ssd1306_commandList(scrollList4b, sizeof(scrollList4b));
+ ssd1306_command1(start);
+ ssd1306_command1(0X00);
+ ssd1306_command1(stop);
+ static const uint8_t PROGMEM scrollList4c[] = {
+ 0X01,
+ SSD1306_ACTIVATE_SCROLL };
+ ssd1306_commandList(scrollList4c, sizeof(scrollList4c));
+ TRANSACTION_END
+}
+
+/*!
+ @brief Cease a previously-begun scrolling action.
+ @return None (void).
+*/
+void Adafruit_SSD1306::stopscroll(void) {
+ TRANSACTION_START
+ ssd1306_command1(SSD1306_DEACTIVATE_SCROLL);
+ TRANSACTION_END
+}
+
+// OTHER HARDWARE SETTINGS -------------------------------------------------
+
+/*!
+ @brief Enable or disable display invert mode (white-on-black vs
+ black-on-white).
+ @param i
+ If true, switch to invert mode (black-on-white), else normal
+ mode (white-on-black).
+ @return None (void).
+ @note This has an immediate effect on the display, no need to call the
+ display() function -- buffer contents are not changed, rather a
+ different pixel mode of the display hardware is used. When
+ enabled, drawing BLACK (value 0) pixels will actually draw white,
+ WHITE (value 1) will draw black.
+*/
+void Adafruit_SSD1306::invertDisplay(boolean i) {
+ TRANSACTION_START
+ ssd1306_command1(i ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY);
+ TRANSACTION_END
+}
+
+/*!
+ @brief Dim the display.
+ @param dim
+ true to enable lower brightness mode, false for full brightness.
+ @return None (void).
+ @note This has an immediate effect on the display, no need to call the
+ display() function -- buffer contents are not changed.
+*/
+void Adafruit_SSD1306::dim(boolean dim) {
+ uint8_t contrast;
+
+ if(dim) {
+ contrast = 0; // Dimmed display
+ } else {
+ contrast = (vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF;
+ }
+ // the range of contrast to too small to be really useful
+ // it is useful to dim the display
+ TRANSACTION_START
+ ssd1306_command1(SSD1306_SETCONTRAST);
+ ssd1306_command1(contrast);
+ TRANSACTION_END
+}
+
+void Adafruit_SSD1306::DisplayOnff(int8_t on) {
+ TRANSACTION_START
+ if(on) {
+ ssd1306_command1(SSD1306_DISPLAYON);
+ } else {
+ ssd1306_command1(SSD1306_DISPLAYOFF);
+ }
+ TRANSACTION_END
+}
+
+void Adafruit_SSD1306::Updateframe(void) {
+ display();
+}
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h
new file mode 100644
index 000000000..5be544199
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h
@@ -0,0 +1,189 @@
+/*!
+ * @file Adafruit_SSD1306.h
+ *
+ * This is part of for Adafruit's SSD1306 library for monochrome
+ * OLED displays: http://www.adafruit.com/category/63_98
+ *
+ * These displays use I2C or SPI to communicate. I2C requires 2 pins
+ * (SCL+SDA) and optionally a RESET pin. SPI requires 4 pins (MOSI, SCK,
+ * select, data/command) and optionally a reset pin. Hardware SPI or
+ * 'bitbang' software SPI are both supported.
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing
+ * products from Adafruit!
+ *
+ * Written by Limor Fried/Ladyada for Adafruit Industries, with
+ * contributions from the open source community.
+ *
+ * BSD license, all text above, and the splash screen header file,
+ * must be included in any redistribution.
+ *
+ */
+
+#ifndef _Adafruit_SSD1306_H_
+#define _Adafruit_SSD1306_H_
+
+#include
+
+extern uint8_t *buffer;
+
+// ONE of the following three lines must be #defined:
+//#define SSD1306_128_64 ///< DEPRECTAED: old way to specify 128x64 screen
+#define SSD1306_128_32 ///< DEPRECATED: old way to specify 128x32 screen
+//#define SSD1306_96_16 ///< DEPRECATED: old way to specify 96x16 screen
+// This establishes the screen dimensions in old Adafruit_SSD1306 sketches
+// (NEW CODE SHOULD IGNORE THIS, USE THE CONSTRUCTORS THAT ACCEPT WIDTH
+// AND HEIGHT ARGUMENTS).
+
+#if defined(ARDUINO_STM32_FEATHER)
+ typedef class HardwareSPI SPIClass;
+#endif
+
+#include
+#include
+#include
+
+#if defined(__AVR__)
+ typedef volatile uint8_t PortReg;
+ typedef uint8_t PortMask;
+ #define HAVE_PORTREG
+#elif defined(__SAM3X8E__)
+ typedef volatile RwReg PortReg;
+ typedef uint32_t PortMask;
+ #define HAVE_PORTREG
+#elif defined(__arm__) || defined(ARDUINO_FEATHER52)
+ typedef volatile uint32_t PortReg;
+ typedef uint32_t PortMask;
+ #define HAVE_PORTREG
+#endif
+
+#define BLACK 0 ///< Draw 'off' pixels
+#define WHITE 1 ///< Draw 'on' pixels
+#define INVERSE 2 ///< Invert pixels
+
+#define SSD1306_MEMORYMODE 0x20 ///< See datasheet
+#define SSD1306_COLUMNADDR 0x21 ///< See datasheet
+#define SSD1306_PAGEADDR 0x22 ///< See datasheet
+#define SSD1306_SETCONTRAST 0x81 ///< See datasheet
+#define SSD1306_CHARGEPUMP 0x8D ///< See datasheet
+#define SSD1306_SEGREMAP 0xA0 ///< See datasheet
+#define SSD1306_DISPLAYALLON_RESUME 0xA4 ///< See datasheet
+#define SSD1306_DISPLAYALLON 0xA5 ///< Not currently used
+#define SSD1306_NORMALDISPLAY 0xA6 ///< See datasheet
+#define SSD1306_INVERTDISPLAY 0xA7 ///< See datasheet
+#define SSD1306_SETMULTIPLEX 0xA8 ///< See datasheet
+#define SSD1306_DISPLAYOFF 0xAE ///< See datasheet
+#define SSD1306_DISPLAYON 0xAF ///< See datasheet
+#define SSD1306_COMSCANINC 0xC0 ///< Not currently used
+#define SSD1306_COMSCANDEC 0xC8 ///< See datasheet
+#define SSD1306_SETDISPLAYOFFSET 0xD3 ///< See datasheet
+#define SSD1306_SETDISPLAYCLOCKDIV 0xD5 ///< See datasheet
+#define SSD1306_SETPRECHARGE 0xD9 ///< See datasheet
+#define SSD1306_SETCOMPINS 0xDA ///< See datasheet
+#define SSD1306_SETVCOMDETECT 0xDB ///< See datasheet
+
+#define SSD1306_SETLOWCOLUMN 0x00 ///< Not currently used
+#define SSD1306_SETHIGHCOLUMN 0x10 ///< Not currently used
+#define SSD1306_SETSTARTLINE 0x40 ///< See datasheet
+
+#define SSD1306_EXTERNALVCC 0x01 ///< External display voltage source
+#define SSD1306_SWITCHCAPVCC 0x02 ///< Gen. display voltage from 3.3V
+
+#define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26 ///< Init rt scroll
+#define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27 ///< Init left scroll
+#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29 ///< Init diag scroll
+#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A ///< Init diag scroll
+#define SSD1306_DEACTIVATE_SCROLL 0x2E ///< Stop scroll
+#define SSD1306_ACTIVATE_SCROLL 0x2F ///< Start scroll
+#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3 ///< Set scroll range
+
+// Deprecated size stuff for backwards compatibility with old sketches
+#if defined SSD1306_128_64
+ #define SSD1306_LCDWIDTH 128 ///< DEPRECATED: width w/SSD1306_128_64 defined
+ #define SSD1306_LCDHEIGHT 64 ///< DEPRECATED: height w/SSD1306_128_64 defined
+#endif
+#if defined SSD1306_128_32
+ #define SSD1306_LCDWIDTH 128 ///< DEPRECATED: width w/SSD1306_128_32 defined
+ #define SSD1306_LCDHEIGHT 32 ///< DEPRECATED: height w/SSD1306_128_32 defined
+#endif
+#if defined SSD1306_96_16
+ #define SSD1306_LCDWIDTH 96 ///< DEPRECATED: width w/SSD1306_96_16 defined
+ #define SSD1306_LCDHEIGHT 16 ///< DEPRECATED: height w/SSD1306_96_16 defined
+#endif
+
+/*!
+ @brief Class that stores state and functions for interacting with
+ SSD1306 OLED displays.
+*/
+class Adafruit_SSD1306 : public Renderer {
+public:
+ // NEW CONSTRUCTORS -- recommended for new projects
+ Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi=&Wire, int8_t rst_pin=-1,
+ uint32_t clkDuring=400000UL, uint32_t clkAfter=100000UL);
+ Adafruit_SSD1306(uint8_t w, uint8_t h, int8_t mosi_pin, int8_t sclk_pin,
+ int8_t dc_pin, int8_t rst_pin, int8_t cs_pin);
+ Adafruit_SSD1306(uint8_t w, uint8_t h, SPIClass *spi,
+ int8_t dc_pin, int8_t rst_pin, int8_t cs_pin, uint32_t bitrate=8000000UL);
+
+ // DEPRECATED CONSTRUCTORS - for back compatibility, avoid in new projects
+ Adafruit_SSD1306(int8_t mosi_pin, int8_t sclk_pin, int8_t dc_pin,
+ int8_t rst_pin, int8_t cs_pin);
+ Adafruit_SSD1306(int8_t dc_pin, int8_t rst_pin, int8_t cs_pin);
+ Adafruit_SSD1306(int8_t rst_pin = -1);
+
+ ~Adafruit_SSD1306(void);
+
+ boolean begin(uint8_t switchvcc=SSD1306_SWITCHCAPVCC,
+ uint8_t i2caddr=0, boolean reset=true,
+ boolean periphBegin=true);
+ void display(void);
+ void invertDisplay(boolean i);
+ void dim(boolean dim);
+ void DisplayOnff(int8_t on);
+ void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
+
+ #if 0
+ void clearDisplay(void);
+ void drawPixel(int16_t x, int16_t y, uint16_t color);
+ virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
+ virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
+ #endif
+ void startscrollright(uint8_t start, uint8_t stop);
+ void startscrollleft(uint8_t start, uint8_t stop);
+ void startscrolldiagright(uint8_t start, uint8_t stop);
+ void startscrolldiagleft(uint8_t start, uint8_t stop);
+ void stopscroll(void);
+ void ssd1306_command(uint8_t c);
+ boolean getPixel(int16_t x, int16_t y);
+ uint8_t *getBuffer(void);
+ void Updateframe(void);
+
+ private:
+ inline void SPIwrite(uint8_t d) __attribute__((always_inline));
+ void drawFastHLineInternal(int16_t x, int16_t y, int16_t w,
+ uint16_t color);
+ void drawFastVLineInternal(int16_t x, int16_t y, int16_t h,
+ uint16_t color);
+ void ssd1306_command1(uint8_t c);
+ void ssd1306_commandList(const uint8_t *c, uint8_t n);
+
+ SPIClass *spi;
+ TwoWire *wire;
+ uint8_t *xbuffer;
+ int8_t i2caddr, vccstate, page_end;
+ int8_t mosiPin , clkPin , dcPin , csPin, rstPin;
+#ifdef HAVE_PORTREG
+ PortReg *mosiPort , *clkPort , *dcPort , *csPort;
+ PortMask mosiPinMask, clkPinMask, dcPinMask, csPinMask;
+#endif
+#if defined(SPI_HAS_TRANSACTION)
+ SPISettings spiSettings;
+#endif
+#if ARDUINO >= 157
+ uint32_t wireClk; // Wire speed for SSD1306 transfers
+ uint32_t restoreClk; // Wire speed following SSD1306 transfers
+#endif
+};
+
+#endif // _Adafruit_SSD1306_H_
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md
new file mode 100644
index 000000000..f2e01ad4b
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md
@@ -0,0 +1,54 @@
+# Adafruit_SSD1306 [](https://travis-ci.org/adafruit/Adafruit_SSD1306)
+
+This is a library for our Monochrome OLEDs based on SSD1306 drivers
+
+ Pick one up today in the adafruit shop!
+ ------> http://www.adafruit.com/category/63_98
+
+These displays use I2C or SPI to communicate, 2 to 5 pins are required to interface.
+
+Adafruit invests time and resources providing this open source code,
+please support Adafruit and open-source hardware by purchasing
+products from Adafruit!
+
+Written by Limor Fried/Ladyada for Adafruit Industries, with contributions from the open source community. Scrolling code contributed by Michael Gregg. Dynamic buffer allocation based on work by Andrew Canaday.
+BSD license, check license.txt for more information. All text above must be included in any redistribution
+
+Preferred installation method is to use the Arduino IDE Library Manager. To download the source from Github instead, click "Clone or download" above, then "Download ZIP." After uncompressing, rename the resulting folder Adafruit_SSD1306. Check that the Adafruit_SSD1306 folder contains Adafruit_SSD1306.cpp and Adafruit_SSD1306.h.
+
+You will also have to install the **Adafruit GFX library** which provides graphics primitves such as lines, circles, text, etc. This also can be found in the Arduino Library Manager, or you can get the source from https://github.com/adafruit/Adafruit-GFX-Library
+
+## Changes
+
+Version 1.2 (November 2018) introduces some significant changes:
+
+ * Display dimensions are now specified in the constructor...you no longer need to edit the .h file for different screens (though old sketches can continue to work that way).
+ * SPI transactions are used and SPI bitrate can be specified (both require Arduino 1.6 or later).
+ * SPI and Wire (I2C) interfaces other than the defaults are supported.
+
+
+
+## Compatibility
+
+MCU |Tested Works|Doesn't Work|Not Tested|Notes
+------------|:----------:|:----------:|:--------:|-----
+Atmega328 | X | | |
+Atmega32u4 | X | | |
+Atmega2560 | X | | |
+ESP8266 | X | | | Change OLED_RESET to different pin if using default I2C pins D4/D5.
+ESP32 | X | | |
+ATSAM3X8E | X | | |
+ATSAM21D | X | | |
+Intel Curie | X | | |
+WICED | X | | | No hardware SPI - bitbang only
+ATtiny85 | | X | |
+
+ * ATmega328 : Arduino UNO, Adafruit Pro Trinket, Adafruit Metro 328, Adafruit Metro Mini
+ * ATmega32u4 : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0, Adafruit Flora, Bluefruit Micro
+ * ATmega2560 : Arduino Mega
+ * ESP8266 : Adafruit Huzzah
+ * ATSAM3X8E : Arduino Due
+ * ATSAM21D : Arduino Zero, M0 Pro, Adafruit Metro Express, Feather M0
+ * ATtiny85 : Adafruit Gemma, Arduino Gemma, Adafruit Trinket
+
+
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino
new file mode 100644
index 000000000..2d0d24646
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino
@@ -0,0 +1,79 @@
+#include
+#include
+#include
+#include
+
+Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);
+
+// OLED FeatherWing buttons map to different pins depending on board:
+#if defined(ESP8266)
+ #define BUTTON_A 0
+ #define BUTTON_B 16
+ #define BUTTON_C 2
+#elif defined(ESP32)
+ #define BUTTON_A 15
+ #define BUTTON_B 32
+ #define BUTTON_C 14
+#elif defined(ARDUINO_STM32_FEATHER)
+ #define BUTTON_A PA15
+ #define BUTTON_B PC7
+ #define BUTTON_C PC5
+#elif defined(TEENSYDUINO)
+ #define BUTTON_A 4
+ #define BUTTON_B 3
+ #define BUTTON_C 8
+#elif defined(ARDUINO_FEATHER52832)
+ #define BUTTON_A 31
+ #define BUTTON_B 30
+ #define BUTTON_C 27
+#else // 32u4, M0, M4, nrf52840 and 328p
+ #define BUTTON_A 9
+ #define BUTTON_B 6
+ #define BUTTON_C 5
+#endif
+
+void setup() {
+ Serial.begin(9600);
+
+ Serial.println("OLED FeatherWing test");
+ // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
+ display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x32
+
+ Serial.println("OLED begun");
+
+ // Show image buffer on the display hardware.
+ // Since the buffer is intialized with an Adafruit splashscreen
+ // internally, this will display the splashscreen.
+ display.display();
+ delay(1000);
+
+ // Clear the buffer.
+ display.clearDisplay();
+ display.display();
+
+ Serial.println("IO test");
+
+ pinMode(BUTTON_A, INPUT_PULLUP);
+ pinMode(BUTTON_B, INPUT_PULLUP);
+ pinMode(BUTTON_C, INPUT_PULLUP);
+
+ // text display tests
+ display.setTextSize(1);
+ display.setTextColor(WHITE);
+ display.setCursor(0,0);
+ display.print("Connecting to SSID\n'adafruit':");
+ display.print("connected!");
+ display.println("IP: 10.0.1.23");
+ display.println("Sending val #0");
+ display.setCursor(0,0);
+ display.display(); // actually display all of the above
+}
+
+void loop() {
+ if(!digitalRead(BUTTON_A)) display.print("A");
+ if(!digitalRead(BUTTON_B)) display.print("B");
+ if(!digitalRead(BUTTON_C)) display.print("C");
+ delay(10);
+ yield();
+ display.display();
+}
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino
new file mode 100644
index 000000000..68bfee354
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino
@@ -0,0 +1,410 @@
+/**************************************************************************
+ This is an example for our Monochrome OLEDs based on SSD1306 drivers
+
+ Pick one up today in the adafruit shop!
+ ------> http://www.adafruit.com/category/63_98
+
+ This example is for a 128x32 pixel display using I2C to communicate
+ 3 pins are required to interface (two I2C and one reset).
+
+ Adafruit invests time and resources providing this open
+ source code, please support Adafruit and open-source
+ hardware by purchasing products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries,
+ with contributions from the open source community.
+ BSD license, check license.txt for more information
+ All text above, and the splash screen below must be
+ included in any redistribution.
+ **************************************************************************/
+
+#include
+#include
+#include
+#include
+
+#define SCREEN_WIDTH 128 // OLED display width, in pixels
+#define SCREEN_HEIGHT 32 // OLED display height, in pixels
+
+// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
+#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
+
+#define NUMFLAKES 10 // Number of snowflakes in the animation example
+
+#define LOGO_HEIGHT 16
+#define LOGO_WIDTH 16
+static const unsigned char PROGMEM logo_bmp[] =
+{ B00000000, B11000000,
+ B00000001, B11000000,
+ B00000001, B11000000,
+ B00000011, B11100000,
+ B11110011, B11100000,
+ B11111110, B11111000,
+ B01111110, B11111111,
+ B00110011, B10011111,
+ B00011111, B11111100,
+ B00001101, B01110000,
+ B00011011, B10100000,
+ B00111111, B11100000,
+ B00111111, B11110000,
+ B01111100, B11110000,
+ B01110000, B01110000,
+ B00000000, B00110000 };
+
+void setup() {
+ Serial.begin(9600);
+
+ // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
+ if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
+ Serial.println(F("SSD1306 allocation failed"));
+ for(;;); // Don't proceed, loop forever
+ }
+
+ // Show initial display buffer contents on the screen --
+ // the library initializes this with an Adafruit splash screen.
+ display.display();
+ delay(2000); // Pause for 2 seconds
+
+ // Clear the buffer
+ display.clearDisplay();
+
+ // Draw a single pixel in white
+ display.drawPixel(10, 10, WHITE);
+
+ // Show the display buffer on the screen. You MUST call display() after
+ // drawing commands to make them visible on screen!
+ display.display();
+ delay(2000);
+ // display.display() is NOT necessary after every single drawing command,
+ // unless that's what you want...rather, you can batch up a bunch of
+ // drawing operations and then update the screen all at once by calling
+ // display.display(). These examples demonstrate both approaches...
+
+ testdrawline(); // Draw many lines
+
+ testdrawrect(); // Draw rectangles (outlines)
+
+ testfillrect(); // Draw rectangles (filled)
+
+ testdrawcircle(); // Draw circles (outlines)
+
+ testfillcircle(); // Draw circles (filled)
+
+ testdrawroundrect(); // Draw rounded rectangles (outlines)
+
+ testfillroundrect(); // Draw rounded rectangles (filled)
+
+ testdrawtriangle(); // Draw triangles (outlines)
+
+ testfilltriangle(); // Draw triangles (filled)
+
+ testdrawchar(); // Draw characters of the default font
+
+ testdrawstyles(); // Draw 'stylized' characters
+
+ testscrolltext(); // Draw scrolling text
+
+ testdrawbitmap(); // Draw a small bitmap image
+
+ // Invert and restore display, pausing in-between
+ display.invertDisplay(true);
+ delay(1000);
+ display.invertDisplay(false);
+ delay(1000);
+
+ testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
+}
+
+void loop() {
+}
+
+void testdrawline() {
+ int16_t i;
+
+ display.clearDisplay(); // Clear display buffer
+
+ for(i=0; i=0; i-=4) {
+ display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
+ display.display();
+ delay(1);
+ }
+ delay(250);
+
+ display.clearDisplay();
+
+ for(i=display.width()-1; i>=0; i-=4) {
+ display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
+ display.display();
+ delay(1);
+ }
+ for(i=display.height()-1; i>=0; i-=4) {
+ display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
+ display.display();
+ delay(1);
+ }
+ delay(250);
+
+ display.clearDisplay();
+
+ for(i=0; i0; i-=3) {
+ // The INVERSE color is used so circles alternate white/black
+ display.fillCircle(display.width() / 2, display.height() / 2, i, INVERSE);
+ display.display(); // Update screen with each newly-drawn circle
+ delay(1);
+ }
+
+ delay(2000);
+}
+
+void testdrawroundrect(void) {
+ display.clearDisplay();
+
+ for(int16_t i=0; i0; i-=5) {
+ // The INVERSE color is used so triangles alternate white/black
+ display.fillTriangle(
+ display.width()/2 , display.height()/2-i,
+ display.width()/2-i, display.height()/2+i,
+ display.width()/2+i, display.height()/2+i, INVERSE);
+ display.display();
+ delay(1);
+ }
+
+ delay(2000);
+}
+
+void testdrawchar(void) {
+ display.clearDisplay();
+
+ display.setTextSize(1); // Normal 1:1 pixel scale
+ display.setTextColor(WHITE); // Draw white text
+ display.setCursor(0, 0); // Start at top-left corner
+ display.cp437(true); // Use full 256 char 'Code Page 437' font
+
+ // Not all the characters will fit on the display. This is normal.
+ // Library will draw what it can and the rest will be clipped.
+ for(int16_t i=0; i<256; i++) {
+ if(i == '\n') display.write(' ');
+ else display.write(i);
+ }
+
+ display.display();
+ delay(2000);
+}
+
+void testdrawstyles(void) {
+ display.clearDisplay();
+
+ display.setTextSize(1); // Normal 1:1 pixel scale
+ display.setTextColor(WHITE); // Draw white text
+ display.setCursor(0,0); // Start at top-left corner
+ display.println(F("Hello, world!"));
+
+ display.setTextColor(BLACK, WHITE); // Draw 'inverse' text
+ display.println(3.141592);
+
+ display.setTextSize(2); // Draw 2X-scale text
+ display.setTextColor(WHITE);
+ display.print(F("0x")); display.println(0xDEADBEEF, HEX);
+
+ display.display();
+ delay(2000);
+}
+
+void testscrolltext(void) {
+ display.clearDisplay();
+
+ display.setTextSize(2); // Draw 2X-scale text
+ display.setTextColor(WHITE);
+ display.setCursor(10, 0);
+ display.println(F("scroll"));
+ display.display(); // Show initial text
+ delay(100);
+
+ // Scroll in various directions, pausing in-between:
+ display.startscrollright(0x00, 0x0F);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+ display.startscrollleft(0x00, 0x0F);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+ display.startscrolldiagright(0x00, 0x07);
+ delay(2000);
+ display.startscrolldiagleft(0x00, 0x07);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+}
+
+void testdrawbitmap(void) {
+ display.clearDisplay();
+
+ display.drawBitmap(
+ (display.width() - LOGO_WIDTH ) / 2,
+ (display.height() - LOGO_HEIGHT) / 2,
+ logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
+ display.display();
+ delay(1000);
+}
+
+#define XPOS 0 // Indexes into the 'icons' array in function below
+#define YPOS 1
+#define DELTAY 2
+
+void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
+ int8_t f, icons[NUMFLAKES][3];
+
+ // Initialize 'snowflake' positions
+ for(f=0; f< NUMFLAKES; f++) {
+ icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+ icons[f][YPOS] = -LOGO_HEIGHT;
+ icons[f][DELTAY] = random(1, 6);
+ Serial.print(F("x: "));
+ Serial.print(icons[f][XPOS], DEC);
+ Serial.print(F(" y: "));
+ Serial.print(icons[f][YPOS], DEC);
+ Serial.print(F(" dy: "));
+ Serial.println(icons[f][DELTAY], DEC);
+ }
+
+ for(;;) { // Loop forever...
+ display.clearDisplay(); // Clear the display buffer
+
+ // Draw each snowflake:
+ for(f=0; f< NUMFLAKES; f++) {
+ display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
+ }
+
+ display.display(); // Show the display buffer on the screen
+ delay(200); // Pause for 1/10 second
+
+ // Then update coordinates of each flake...
+ for(f=0; f< NUMFLAKES; f++) {
+ icons[f][YPOS] += icons[f][DELTAY];
+ // If snowflake is off the bottom of the screen...
+ if (icons[f][YPOS] >= display.height()) {
+ // Reinitialize to a random position, just off the top
+ icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+ icons[f][YPOS] = -LOGO_HEIGHT;
+ icons[f][DELTAY] = random(1, 6);
+ }
+ }
+ }
+}
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino
new file mode 100644
index 000000000..b254785f3
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino
@@ -0,0 +1,423 @@
+/**************************************************************************
+ This is an example for our Monochrome OLEDs based on SSD1306 drivers
+
+ Pick one up today in the adafruit shop!
+ ------> http://www.adafruit.com/category/63_98
+
+ This example is for a 128x32 pixel display using SPI to communicate
+ 4 or 5 pins are required to interface.
+
+ Adafruit invests time and resources providing this open
+ source code, please support Adafruit and open-source
+ hardware by purchasing products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries,
+ with contributions from the open source community.
+ BSD license, check license.txt for more information
+ All text above, and the splash screen below must be
+ included in any redistribution.
+ **************************************************************************/
+
+#include
+#include
+#include
+#include
+
+#define SCREEN_WIDTH 128 // OLED display width, in pixels
+#define SCREEN_HEIGHT 32 // OLED display height, in pixels
+
+// Declaration for SSD1306 display connected using software SPI (default case):
+#define OLED_MOSI 9
+#define OLED_CLK 10
+#define OLED_DC 11
+#define OLED_CS 12
+#define OLED_RESET 13
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
+ OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
+
+/* Comment out above, uncomment this block to use hardware SPI
+#define OLED_DC 6
+#define OLED_CS 7
+#define OLED_RESET 8
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
+ &SPI, OLED_DC, OLED_RESET, OLED_CS);
+*/
+
+#define NUMFLAKES 10 // Number of snowflakes in the animation example
+
+#define LOGO_HEIGHT 16
+#define LOGO_WIDTH 16
+static const unsigned char PROGMEM logo_bmp[] =
+{ B00000000, B11000000,
+ B00000001, B11000000,
+ B00000001, B11000000,
+ B00000011, B11100000,
+ B11110011, B11100000,
+ B11111110, B11111000,
+ B01111110, B11111111,
+ B00110011, B10011111,
+ B00011111, B11111100,
+ B00001101, B01110000,
+ B00011011, B10100000,
+ B00111111, B11100000,
+ B00111111, B11110000,
+ B01111100, B11110000,
+ B01110000, B01110000,
+ B00000000, B00110000 };
+
+void setup() {
+ Serial.begin(9600);
+
+ // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
+ if(!display.begin(SSD1306_SWITCHCAPVCC)) {
+ Serial.println(F("SSD1306 allocation failed"));
+ for(;;); // Don't proceed, loop forever
+ }
+
+ // Show initial display buffer contents on the screen --
+ // the library initializes this with an Adafruit splash screen.
+ display.display();
+ delay(2000); // Pause for 2 seconds
+
+ // Clear the buffer
+ display.clearDisplay();
+
+ // Draw a single pixel in white
+ display.drawPixel(10, 10, WHITE);
+
+ // Show the display buffer on the screen. You MUST call display() after
+ // drawing commands to make them visible on screen!
+ display.display();
+ delay(2000);
+ // display.display() is NOT necessary after every single drawing command,
+ // unless that's what you want...rather, you can batch up a bunch of
+ // drawing operations and then update the screen all at once by calling
+ // display.display(). These examples demonstrate both approaches...
+
+ testdrawline(); // Draw many lines
+
+ testdrawrect(); // Draw rectangles (outlines)
+
+ testfillrect(); // Draw rectangles (filled)
+
+ testdrawcircle(); // Draw circles (outlines)
+
+ testfillcircle(); // Draw circles (filled)
+
+ testdrawroundrect(); // Draw rounded rectangles (outlines)
+
+ testfillroundrect(); // Draw rounded rectangles (filled)
+
+ testdrawtriangle(); // Draw triangles (outlines)
+
+ testfilltriangle(); // Draw triangles (filled)
+
+ testdrawchar(); // Draw characters of the default font
+
+ testdrawstyles(); // Draw 'stylized' characters
+
+ testscrolltext(); // Draw scrolling text
+
+ testdrawbitmap(); // Draw a small bitmap image
+
+ // Invert and restore display, pausing in-between
+ display.invertDisplay(true);
+ delay(1000);
+ display.invertDisplay(false);
+ delay(1000);
+
+ testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
+}
+
+void loop() {
+}
+
+void testdrawline() {
+ int16_t i;
+
+ display.clearDisplay(); // Clear display buffer
+
+ for(i=0; i=0; i-=4) {
+ display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
+ display.display();
+ delay(1);
+ }
+ delay(250);
+
+ display.clearDisplay();
+
+ for(i=display.width()-1; i>=0; i-=4) {
+ display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
+ display.display();
+ delay(1);
+ }
+ for(i=display.height()-1; i>=0; i-=4) {
+ display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
+ display.display();
+ delay(1);
+ }
+ delay(250);
+
+ display.clearDisplay();
+
+ for(i=0; i0; i-=3) {
+ // The INVERSE color is used so circles alternate white/black
+ display.fillCircle(display.width() / 2, display.height() / 2, i, INVERSE);
+ display.display(); // Update screen with each newly-drawn circle
+ delay(1);
+ }
+
+ delay(2000);
+}
+
+void testdrawroundrect(void) {
+ display.clearDisplay();
+
+ for(int16_t i=0; i0; i-=5) {
+ // The INVERSE color is used so triangles alternate white/black
+ display.fillTriangle(
+ display.width()/2 , display.height()/2-i,
+ display.width()/2-i, display.height()/2+i,
+ display.width()/2+i, display.height()/2+i, INVERSE);
+ display.display();
+ delay(1);
+ }
+
+ delay(2000);
+}
+
+void testdrawchar(void) {
+ display.clearDisplay();
+
+ display.setTextSize(1); // Normal 1:1 pixel scale
+ display.setTextColor(WHITE); // Draw white text
+ display.setCursor(0, 0); // Start at top-left corner
+ display.cp437(true); // Use full 256 char 'Code Page 437' font
+
+ // Not all the characters will fit on the display. This is normal.
+ // Library will draw what it can and the rest will be clipped.
+ for(int16_t i=0; i<256; i++) {
+ if(i == '\n') display.write(' ');
+ else display.write(i);
+ }
+
+ display.display();
+ delay(2000);
+}
+
+void testdrawstyles(void) {
+ display.clearDisplay();
+
+ display.setTextSize(1); // Normal 1:1 pixel scale
+ display.setTextColor(WHITE); // Draw white text
+ display.setCursor(0,0); // Start at top-left corner
+ display.println(F("Hello, world!"));
+
+ display.setTextColor(BLACK, WHITE); // Draw 'inverse' text
+ display.println(3.141592);
+
+ display.setTextSize(2); // Draw 2X-scale text
+ display.setTextColor(WHITE);
+ display.print(F("0x")); display.println(0xDEADBEEF, HEX);
+
+ display.display();
+ delay(2000);
+}
+
+void testscrolltext(void) {
+ display.clearDisplay();
+
+ display.setTextSize(2); // Draw 2X-scale text
+ display.setTextColor(WHITE);
+ display.setCursor(10, 0);
+ display.println(F("scroll"));
+ display.display(); // Show initial text
+ delay(100);
+
+ // Scroll in various directions, pausing in-between:
+ display.startscrollright(0x00, 0x0F);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+ display.startscrollleft(0x00, 0x0F);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+ display.startscrolldiagright(0x00, 0x07);
+ delay(2000);
+ display.startscrolldiagleft(0x00, 0x07);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+}
+
+void testdrawbitmap(void) {
+ display.clearDisplay();
+
+ display.drawBitmap(
+ (display.width() - LOGO_WIDTH ) / 2,
+ (display.height() - LOGO_HEIGHT) / 2,
+ logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
+ display.display();
+ delay(1000);
+}
+
+#define XPOS 0 // Indexes into the 'icons' array in function below
+#define YPOS 1
+#define DELTAY 2
+
+void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
+ int8_t f, icons[NUMFLAKES][3];
+
+ // Initialize 'snowflake' positions
+ for(f=0; f< NUMFLAKES; f++) {
+ icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+ icons[f][YPOS] = -LOGO_HEIGHT;
+ icons[f][DELTAY] = random(1, 6);
+ Serial.print(F("x: "));
+ Serial.print(icons[f][XPOS], DEC);
+ Serial.print(F(" y: "));
+ Serial.print(icons[f][YPOS], DEC);
+ Serial.print(F(" dy: "));
+ Serial.println(icons[f][DELTAY], DEC);
+ }
+
+ for(;;) { // Loop forever...
+ display.clearDisplay(); // Clear the display buffer
+
+ // Draw each snowflake:
+ for(f=0; f< NUMFLAKES; f++) {
+ display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
+ }
+
+ display.display(); // Show the display buffer on the screen
+ delay(200); // Pause for 1/10 second
+
+ // Then update coordinates of each flake...
+ for(f=0; f< NUMFLAKES; f++) {
+ icons[f][YPOS] += icons[f][DELTAY];
+ // If snowflake is off the bottom of the screen...
+ if (icons[f][YPOS] >= display.height()) {
+ // Reinitialize to a random position, just off the top
+ icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+ icons[f][YPOS] = -LOGO_HEIGHT;
+ icons[f][DELTAY] = random(1, 6);
+ }
+ }
+ }
+}
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino
new file mode 100644
index 000000000..6d7d5ddd0
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino
@@ -0,0 +1,410 @@
+/**************************************************************************
+ This is an example for our Monochrome OLEDs based on SSD1306 drivers
+
+ Pick one up today in the adafruit shop!
+ ------> http://www.adafruit.com/category/63_98
+
+ This example is for a 128x32 pixel display using I2C to communicate
+ 3 pins are required to interface (two I2C and one reset).
+
+ Adafruit invests time and resources providing this open
+ source code, please support Adafruit and open-source
+ hardware by purchasing products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries,
+ with contributions from the open source community.
+ BSD license, check license.txt for more information
+ All text above, and the splash screen below must be
+ included in any redistribution.
+ **************************************************************************/
+
+#include
+#include
+#include
+#include
+
+#define SCREEN_WIDTH 128 // OLED display width, in pixels
+#define SCREEN_HEIGHT 64 // OLED display height, in pixels
+
+// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
+#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
+
+#define NUMFLAKES 10 // Number of snowflakes in the animation example
+
+#define LOGO_HEIGHT 16
+#define LOGO_WIDTH 16
+static const unsigned char PROGMEM logo_bmp[] =
+{ B00000000, B11000000,
+ B00000001, B11000000,
+ B00000001, B11000000,
+ B00000011, B11100000,
+ B11110011, B11100000,
+ B11111110, B11111000,
+ B01111110, B11111111,
+ B00110011, B10011111,
+ B00011111, B11111100,
+ B00001101, B01110000,
+ B00011011, B10100000,
+ B00111111, B11100000,
+ B00111111, B11110000,
+ B01111100, B11110000,
+ B01110000, B01110000,
+ B00000000, B00110000 };
+
+void setup() {
+ Serial.begin(9600);
+
+ // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
+ if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
+ Serial.println(F("SSD1306 allocation failed"));
+ for(;;); // Don't proceed, loop forever
+ }
+
+ // Show initial display buffer contents on the screen --
+ // the library initializes this with an Adafruit splash screen.
+ display.display();
+ delay(2000); // Pause for 2 seconds
+
+ // Clear the buffer
+ display.clearDisplay();
+
+ // Draw a single pixel in white
+ display.drawPixel(10, 10, WHITE);
+
+ // Show the display buffer on the screen. You MUST call display() after
+ // drawing commands to make them visible on screen!
+ display.display();
+ delay(2000);
+ // display.display() is NOT necessary after every single drawing command,
+ // unless that's what you want...rather, you can batch up a bunch of
+ // drawing operations and then update the screen all at once by calling
+ // display.display(). These examples demonstrate both approaches...
+
+ testdrawline(); // Draw many lines
+
+ testdrawrect(); // Draw rectangles (outlines)
+
+ testfillrect(); // Draw rectangles (filled)
+
+ testdrawcircle(); // Draw circles (outlines)
+
+ testfillcircle(); // Draw circles (filled)
+
+ testdrawroundrect(); // Draw rounded rectangles (outlines)
+
+ testfillroundrect(); // Draw rounded rectangles (filled)
+
+ testdrawtriangle(); // Draw triangles (outlines)
+
+ testfilltriangle(); // Draw triangles (filled)
+
+ testdrawchar(); // Draw characters of the default font
+
+ testdrawstyles(); // Draw 'stylized' characters
+
+ testscrolltext(); // Draw scrolling text
+
+ testdrawbitmap(); // Draw a small bitmap image
+
+ // Invert and restore display, pausing in-between
+ display.invertDisplay(true);
+ delay(1000);
+ display.invertDisplay(false);
+ delay(1000);
+
+ testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
+}
+
+void loop() {
+}
+
+void testdrawline() {
+ int16_t i;
+
+ display.clearDisplay(); // Clear display buffer
+
+ for(i=0; i=0; i-=4) {
+ display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
+ display.display();
+ delay(1);
+ }
+ delay(250);
+
+ display.clearDisplay();
+
+ for(i=display.width()-1; i>=0; i-=4) {
+ display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
+ display.display();
+ delay(1);
+ }
+ for(i=display.height()-1; i>=0; i-=4) {
+ display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
+ display.display();
+ delay(1);
+ }
+ delay(250);
+
+ display.clearDisplay();
+
+ for(i=0; i0; i-=3) {
+ // The INVERSE color is used so circles alternate white/black
+ display.fillCircle(display.width() / 2, display.height() / 2, i, INVERSE);
+ display.display(); // Update screen with each newly-drawn circle
+ delay(1);
+ }
+
+ delay(2000);
+}
+
+void testdrawroundrect(void) {
+ display.clearDisplay();
+
+ for(int16_t i=0; i0; i-=5) {
+ // The INVERSE color is used so triangles alternate white/black
+ display.fillTriangle(
+ display.width()/2 , display.height()/2-i,
+ display.width()/2-i, display.height()/2+i,
+ display.width()/2+i, display.height()/2+i, INVERSE);
+ display.display();
+ delay(1);
+ }
+
+ delay(2000);
+}
+
+void testdrawchar(void) {
+ display.clearDisplay();
+
+ display.setTextSize(1); // Normal 1:1 pixel scale
+ display.setTextColor(WHITE); // Draw white text
+ display.setCursor(0, 0); // Start at top-left corner
+ display.cp437(true); // Use full 256 char 'Code Page 437' font
+
+ // Not all the characters will fit on the display. This is normal.
+ // Library will draw what it can and the rest will be clipped.
+ for(int16_t i=0; i<256; i++) {
+ if(i == '\n') display.write(' ');
+ else display.write(i);
+ }
+
+ display.display();
+ delay(2000);
+}
+
+void testdrawstyles(void) {
+ display.clearDisplay();
+
+ display.setTextSize(1); // Normal 1:1 pixel scale
+ display.setTextColor(WHITE); // Draw white text
+ display.setCursor(0,0); // Start at top-left corner
+ display.println(F("Hello, world!"));
+
+ display.setTextColor(BLACK, WHITE); // Draw 'inverse' text
+ display.println(3.141592);
+
+ display.setTextSize(2); // Draw 2X-scale text
+ display.setTextColor(WHITE);
+ display.print(F("0x")); display.println(0xDEADBEEF, HEX);
+
+ display.display();
+ delay(2000);
+}
+
+void testscrolltext(void) {
+ display.clearDisplay();
+
+ display.setTextSize(2); // Draw 2X-scale text
+ display.setTextColor(WHITE);
+ display.setCursor(10, 0);
+ display.println(F("scroll"));
+ display.display(); // Show initial text
+ delay(100);
+
+ // Scroll in various directions, pausing in-between:
+ display.startscrollright(0x00, 0x0F);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+ display.startscrollleft(0x00, 0x0F);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+ display.startscrolldiagright(0x00, 0x07);
+ delay(2000);
+ display.startscrolldiagleft(0x00, 0x07);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+}
+
+void testdrawbitmap(void) {
+ display.clearDisplay();
+
+ display.drawBitmap(
+ (display.width() - LOGO_WIDTH ) / 2,
+ (display.height() - LOGO_HEIGHT) / 2,
+ logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
+ display.display();
+ delay(1000);
+}
+
+#define XPOS 0 // Indexes into the 'icons' array in function below
+#define YPOS 1
+#define DELTAY 2
+
+void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
+ int8_t f, icons[NUMFLAKES][3];
+
+ // Initialize 'snowflake' positions
+ for(f=0; f< NUMFLAKES; f++) {
+ icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+ icons[f][YPOS] = -LOGO_HEIGHT;
+ icons[f][DELTAY] = random(1, 6);
+ Serial.print(F("x: "));
+ Serial.print(icons[f][XPOS], DEC);
+ Serial.print(F(" y: "));
+ Serial.print(icons[f][YPOS], DEC);
+ Serial.print(F(" dy: "));
+ Serial.println(icons[f][DELTAY], DEC);
+ }
+
+ for(;;) { // Loop forever...
+ display.clearDisplay(); // Clear the display buffer
+
+ // Draw each snowflake:
+ for(f=0; f< NUMFLAKES; f++) {
+ display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
+ }
+
+ display.display(); // Show the display buffer on the screen
+ delay(200); // Pause for 1/10 second
+
+ // Then update coordinates of each flake...
+ for(f=0; f< NUMFLAKES; f++) {
+ icons[f][YPOS] += icons[f][DELTAY];
+ // If snowflake is off the bottom of the screen...
+ if (icons[f][YPOS] >= display.height()) {
+ // Reinitialize to a random position, just off the top
+ icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+ icons[f][YPOS] = -LOGO_HEIGHT;
+ icons[f][DELTAY] = random(1, 6);
+ }
+ }
+ }
+}
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino
new file mode 100644
index 000000000..dbe300d43
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino
@@ -0,0 +1,424 @@
+/**************************************************************************
+ This is an example for our Monochrome OLEDs based on SSD1306 drivers
+
+ Pick one up today in the adafruit shop!
+ ------> http://www.adafruit.com/category/63_98
+
+ This example is for a 128x64 pixel display using SPI to communicate
+ 4 or 5 pins are required to interface.
+
+ Adafruit invests time and resources providing this open
+ source code, please support Adafruit and open-source
+ hardware by purchasing products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries,
+ with contributions from the open source community.
+ BSD license, check license.txt for more information
+ All text above, and the splash screen below must be
+ included in any redistribution.
+ **************************************************************************/
+
+#include
+#include
+#include
+#include
+
+#define SCREEN_WIDTH 128 // OLED display width, in pixels
+#define SCREEN_HEIGHT 64 // OLED display height, in pixels
+
+// Declaration for SSD1306 display connected using software SPI (default case):
+#define OLED_MOSI 9
+#define OLED_CLK 10
+#define OLED_DC 11
+#define OLED_CS 12
+#define OLED_RESET 13
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
+ OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
+
+/* Comment out above, uncomment this block to use hardware SPI
+#define OLED_DC 6
+#define OLED_CS 7
+#define OLED_RESET 8
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
+ &SPI, OLED_DC, OLED_RESET, OLED_CS);
+*/
+
+#define NUMFLAKES 10 // Number of snowflakes in the animation example
+
+#define LOGO_HEIGHT 16
+#define LOGO_WIDTH 16
+static const unsigned char PROGMEM logo_bmp[] =
+{ B00000000, B11000000,
+ B00000001, B11000000,
+ B00000001, B11000000,
+ B00000011, B11100000,
+ B11110011, B11100000,
+ B11111110, B11111000,
+ B01111110, B11111111,
+ B00110011, B10011111,
+ B00011111, B11111100,
+ B00001101, B01110000,
+ B00011011, B10100000,
+ B00111111, B11100000,
+ B00111111, B11110000,
+ B01111100, B11110000,
+ B01110000, B01110000,
+ B00000000, B00110000 };
+
+void setup() {
+ Serial.begin(9600);
+
+ // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
+ if(!display.begin(SSD1306_SWITCHCAPVCC)) {
+ Serial.println(F("SSD1306 allocation failed"));
+ for(;;); // Don't proceed, loop forever
+ }
+
+
+ // Show initial display buffer contents on the screen --
+ // the library initializes this with an Adafruit splash screen.
+ display.display();
+ delay(2000); // Pause for 2 seconds
+
+ // Clear the buffer
+ display.clearDisplay();
+
+ // Draw a single pixel in white
+ display.drawPixel(10, 10, WHITE);
+
+ // Show the display buffer on the screen. You MUST call display() after
+ // drawing commands to make them visible on screen!
+ display.display();
+ delay(2000);
+ // display.display() is NOT necessary after every single drawing command,
+ // unless that's what you want...rather, you can batch up a bunch of
+ // drawing operations and then update the screen all at once by calling
+ // display.display(). These examples demonstrate both approaches...
+
+ testdrawline(); // Draw many lines
+
+ testdrawrect(); // Draw rectangles (outlines)
+
+ testfillrect(); // Draw rectangles (filled)
+
+ testdrawcircle(); // Draw circles (outlines)
+
+ testfillcircle(); // Draw circles (filled)
+
+ testdrawroundrect(); // Draw rounded rectangles (outlines)
+
+ testfillroundrect(); // Draw rounded rectangles (filled)
+
+ testdrawtriangle(); // Draw triangles (outlines)
+
+ testfilltriangle(); // Draw triangles (filled)
+
+ testdrawchar(); // Draw characters of the default font
+
+ testdrawstyles(); // Draw 'stylized' characters
+
+ testscrolltext(); // Draw scrolling text
+
+ testdrawbitmap(); // Draw a small bitmap image
+
+ // Invert and restore display, pausing in-between
+ display.invertDisplay(true);
+ delay(1000);
+ display.invertDisplay(false);
+ delay(1000);
+
+ testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
+}
+
+void loop() {
+}
+
+void testdrawline() {
+ int16_t i;
+
+ display.clearDisplay(); // Clear display buffer
+
+ for(i=0; i=0; i-=4) {
+ display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
+ display.display();
+ delay(1);
+ }
+ delay(250);
+
+ display.clearDisplay();
+
+ for(i=display.width()-1; i>=0; i-=4) {
+ display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
+ display.display();
+ delay(1);
+ }
+ for(i=display.height()-1; i>=0; i-=4) {
+ display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
+ display.display();
+ delay(1);
+ }
+ delay(250);
+
+ display.clearDisplay();
+
+ for(i=0; i0; i-=3) {
+ // The INVERSE color is used so circles alternate white/black
+ display.fillCircle(display.width() / 2, display.height() / 2, i, INVERSE);
+ display.display(); // Update screen with each newly-drawn circle
+ delay(1);
+ }
+
+ delay(2000);
+}
+
+void testdrawroundrect(void) {
+ display.clearDisplay();
+
+ for(int16_t i=0; i0; i-=5) {
+ // The INVERSE color is used so triangles alternate white/black
+ display.fillTriangle(
+ display.width()/2 , display.height()/2-i,
+ display.width()/2-i, display.height()/2+i,
+ display.width()/2+i, display.height()/2+i, INVERSE);
+ display.display();
+ delay(1);
+ }
+
+ delay(2000);
+}
+
+void testdrawchar(void) {
+ display.clearDisplay();
+
+ display.setTextSize(1); // Normal 1:1 pixel scale
+ display.setTextColor(WHITE); // Draw white text
+ display.setCursor(0, 0); // Start at top-left corner
+ display.cp437(true); // Use full 256 char 'Code Page 437' font
+
+ // Not all the characters will fit on the display. This is normal.
+ // Library will draw what it can and the rest will be clipped.
+ for(int16_t i=0; i<256; i++) {
+ if(i == '\n') display.write(' ');
+ else display.write(i);
+ }
+
+ display.display();
+ delay(2000);
+}
+
+void testdrawstyles(void) {
+ display.clearDisplay();
+
+ display.setTextSize(1); // Normal 1:1 pixel scale
+ display.setTextColor(WHITE); // Draw white text
+ display.setCursor(0,0); // Start at top-left corner
+ display.println(F("Hello, world!"));
+
+ display.setTextColor(BLACK, WHITE); // Draw 'inverse' text
+ display.println(3.141592);
+
+ display.setTextSize(2); // Draw 2X-scale text
+ display.setTextColor(WHITE);
+ display.print(F("0x")); display.println(0xDEADBEEF, HEX);
+
+ display.display();
+ delay(2000);
+}
+
+void testscrolltext(void) {
+ display.clearDisplay();
+
+ display.setTextSize(2); // Draw 2X-scale text
+ display.setTextColor(WHITE);
+ display.setCursor(10, 0);
+ display.println(F("scroll"));
+ display.display(); // Show initial text
+ delay(100);
+
+ // Scroll in various directions, pausing in-between:
+ display.startscrollright(0x00, 0x0F);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+ display.startscrollleft(0x00, 0x0F);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+ display.startscrolldiagright(0x00, 0x07);
+ delay(2000);
+ display.startscrolldiagleft(0x00, 0x07);
+ delay(2000);
+ display.stopscroll();
+ delay(1000);
+}
+
+void testdrawbitmap(void) {
+ display.clearDisplay();
+
+ display.drawBitmap(
+ (display.width() - LOGO_WIDTH ) / 2,
+ (display.height() - LOGO_HEIGHT) / 2,
+ logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
+ display.display();
+ delay(1000);
+}
+
+#define XPOS 0 // Indexes into the 'icons' array in function below
+#define YPOS 1
+#define DELTAY 2
+
+void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
+ int8_t f, icons[NUMFLAKES][3];
+
+ // Initialize 'snowflake' positions
+ for(f=0; f< NUMFLAKES; f++) {
+ icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+ icons[f][YPOS] = -LOGO_HEIGHT;
+ icons[f][DELTAY] = random(1, 6);
+ Serial.print(F("x: "));
+ Serial.print(icons[f][XPOS], DEC);
+ Serial.print(F(" y: "));
+ Serial.print(icons[f][YPOS], DEC);
+ Serial.print(F(" dy: "));
+ Serial.println(icons[f][DELTAY], DEC);
+ }
+
+ for(;;) { // Loop forever...
+ display.clearDisplay(); // Clear the display buffer
+
+ // Draw each snowflake:
+ for(f=0; f< NUMFLAKES; f++) {
+ display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
+ }
+
+ display.display(); // Show the display buffer on the screen
+ delay(200); // Pause for 1/10 second
+
+ // Then update coordinates of each flake...
+ for(f=0; f< NUMFLAKES; f++) {
+ icons[f][YPOS] += icons[f][DELTAY];
+ // If snowflake is off the bottom of the screen...
+ if (icons[f][YPOS] >= display.height()) {
+ // Reinitialize to a random position, just off the top
+ icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+ icons[f][YPOS] = -LOGO_HEIGHT;
+ icons[f][DELTAY] = random(1, 6);
+ }
+ }
+ }
+}
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties
new file mode 100644
index 000000000..61b8efa07
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties
@@ -0,0 +1,9 @@
+name=Adafruit SSD1306
+version=1.3.0
+author=Adafruit
+maintainer=Adafruit
+sentence=SSD1306 oled driver library for monochrome 128x64 and 128x32 displays
+paragraph=SSD1306 oled driver library for monochrome 128x64 and 128x32 displays
+category=Display
+url=https://github.com/adafruit/Adafruit_SSD1306
+architectures=*
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt
new file mode 100644
index 000000000..f6a0f22b8
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt
@@ -0,0 +1,26 @@
+Software License Agreement (BSD License)
+
+Copyright (c) 2012, Adafruit Industries
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+3. Neither the name of the copyright holders nor the
+names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h
new file mode 100644
index 000000000..487daecb4
--- /dev/null
+++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h
@@ -0,0 +1,108 @@
+#define splash1_width 82
+#define splash1_height 64
+
+const uint8_t PROGMEM splash1_data[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F,
+ 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x7F, 0xF0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFE, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1F, 0xFF, 0xFB, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0F, 0xFF, 0xF9, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0F, 0xFF, 0xF9, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0xFF, 0xF1, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC,
+ 0x73, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x3F,
+ 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x1E, 0x0F,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x1F, 0xFC,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF8, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xDF, 0xFF, 0xE0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x19, 0xFF, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3C, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7E, 0x7C, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0xFE, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xEF,
+ 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xCF, 0xFE,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x07, 0xFE, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x07, 0xFE, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF0, 0x03, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x80, 0x00, 0xFC, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x07, 0x80,
+ 0x01, 0xFC, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x07, 0x80, 0x01,
+ 0xFC, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x07, 0x80, 0x01, 0xE0,
+ 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x07, 0x80, 0x01, 0xE0, 0x00,
+ 0x00, 0x00, 0x1E, 0x00, 0x7F, 0xE3, 0xF7, 0x9F, 0xF9, 0xFD, 0xE7, 0x78,
+ 0x7B, 0xDF, 0xC0, 0xFF, 0xF7, 0xFF, 0xBF, 0xFD, 0xFD, 0xFF, 0x78, 0x7B,
+ 0xDF, 0xC0, 0xFF, 0xF7, 0xFF, 0xBF, 0xFD, 0xFD, 0xFF, 0x78, 0x7B, 0xDF,
+ 0xC0, 0xF0, 0xF7, 0x87, 0xBC, 0x3D, 0xE1, 0xFF, 0x78, 0x7B, 0xDE, 0x00,
+ 0xF0, 0xF7, 0x87, 0xBC, 0x3D, 0xE1, 0xF0, 0x78, 0x7B, 0xDE, 0x00, 0x00,
+ 0xF7, 0x87, 0x80, 0x3D, 0xE1, 0xE0, 0x78, 0x7B, 0xDE, 0x00, 0x7F, 0xF7,
+ 0x87, 0x9F, 0xFD, 0xE1, 0xE0, 0x78, 0x7B, 0xDE, 0x00, 0xFF, 0xF7, 0x87,
+ 0xBF, 0xFD, 0xE1, 0xE0, 0x78, 0x7B, 0xDE, 0x00, 0xF0, 0xF7, 0x87, 0xBC,
+ 0x3D, 0xE1, 0xE0, 0x78, 0x7B, 0xDE, 0x00, 0xF0, 0xF7, 0x87, 0xBC, 0x3D,
+ 0xE1, 0xE0, 0x78, 0x7B, 0xDE, 0x00, 0xF0, 0xF7, 0x87, 0xBC, 0x3D, 0xE1,
+ 0xE0, 0x78, 0x7B, 0xDE, 0x00, 0xFF, 0xF7, 0xFF, 0xBF, 0xFD, 0xE1, 0xE0,
+ 0x7F, 0xFB, 0xDF, 0xC0, 0xFF, 0xF7, 0xFF, 0xBF, 0xFD, 0xE1, 0xE0, 0x7F,
+ 0xFB, 0xDF, 0xC0, 0x7C, 0xF3, 0xF3, 0x9F, 0x3D, 0xE1, 0xE0, 0x3E, 0x7B,
+ 0xCF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x68, 0xDB, 0x11, 0x1A, 0x31, 0xC0, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFD, 0x2B, 0x5A, 0xFB, 0x6A, 0xEF, 0xC0, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFD, 0x4B, 0x5B, 0x3B, 0x1A, 0x33, 0xC0, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFD, 0x6B, 0x5B, 0xDB, 0x6A, 0xFD, 0xC0 };
+
+#define splash2_width 115
+#define splash2_height 32
+
+const uint8_t PROGMEM splash2_data[] = {
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8,
+ 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x7E, 0x00, 0x00, 0x01, 0xE0, 0x00,
+ 0x7F, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0xFE, 0x00, 0x00,
+ 0x01, 0xE0, 0x00, 0xFF, 0xEF, 0xF8, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00,
+ 0xFE, 0x00, 0x00, 0x01, 0xE0, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00,
+ 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x7F, 0xFE, 0x7F,
+ 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0x00,
+ 0x3F, 0xFE, 0x7F, 0xF8, 0x3F, 0xF1, 0xFB, 0xCF, 0xFC, 0xFE, 0xF3, 0xBC,
+ 0x3D, 0xEF, 0xE0, 0x1F, 0xFE, 0x7F, 0xFF, 0x7F, 0xFB, 0xFF, 0xDF, 0xFE,
+ 0xFE, 0xFF, 0xBC, 0x3D, 0xEF, 0xE0, 0x1F, 0xC6, 0xFF, 0xFF, 0x7F, 0xFB,
+ 0xFF, 0xDF, 0xFE, 0xFE, 0xFF, 0xBC, 0x3D, 0xEF, 0xE0, 0x0F, 0xE3, 0xC7,
+ 0xFE, 0x78, 0x7B, 0xC3, 0xDE, 0x1E, 0xF0, 0xFF, 0xBC, 0x3D, 0xEF, 0x00,
+ 0x07, 0xFF, 0x87, 0xFC, 0x78, 0x7B, 0xC3, 0xDE, 0x1E, 0xF0, 0xF8, 0x3C,
+ 0x3D, 0xEF, 0x00, 0x01, 0xFF, 0xFF, 0xF0, 0x00, 0x7B, 0xC3, 0xC0, 0x1E,
+ 0xF0, 0xF0, 0x3C, 0x3D, 0xEF, 0x00, 0x01, 0xF3, 0x7F, 0xE0, 0x3F, 0xFB,
+ 0xC3, 0xCF, 0xFE, 0xF0, 0xF0, 0x3C, 0x3D, 0xEF, 0x00, 0x03, 0xE3, 0x3F,
+ 0x80, 0x7F, 0xFB, 0xC3, 0xDF, 0xFE, 0xF0, 0xF0, 0x3C, 0x3D, 0xEF, 0x00,
+ 0x07, 0xE7, 0x3C, 0x00, 0x78, 0x7B, 0xC3, 0xDE, 0x1E, 0xF0, 0xF0, 0x3C,
+ 0x3D, 0xEF, 0x00, 0x07, 0xFF, 0xBE, 0x00, 0x78, 0x7B, 0xC3, 0xDE, 0x1E,
+ 0xF0, 0xF0, 0x3C, 0x3D, 0xEF, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x78, 0x7B,
+ 0xC3, 0xDE, 0x1E, 0xF0, 0xF0, 0x3C, 0x3D, 0xEF, 0x00, 0x0F, 0xFF, 0xFE,
+ 0x00, 0x7F, 0xFB, 0xFF, 0xDF, 0xFE, 0xF0, 0xF0, 0x3F, 0xFD, 0xEF, 0xE0,
+ 0x0F, 0xFF, 0xFF, 0x00, 0x7F, 0xFB, 0xFF, 0xDF, 0xFE, 0xF0, 0xF0, 0x3F,
+ 0xFD, 0xEF, 0xE0, 0x0F, 0xF9, 0xFF, 0x00, 0x3E, 0x79, 0xF9, 0xCF, 0x9E,
+ 0xF0, 0xF0, 0x1F, 0x3D, 0xE7, 0xE0, 0x1F, 0xF1, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x80, 0xFF,
+ 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
+ 0x1C, 0x00, 0x7F, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xB4, 0x6D, 0x88,
+ 0x8D, 0x18, 0xE0, 0x00, 0x00, 0x1F, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE,
+ 0x95, 0xAD, 0x7D, 0xB5, 0x77, 0xE0, 0x00, 0x00, 0x0F, 0x00, 0x7F, 0xFF,
+ 0xFF, 0xFF, 0xFE, 0xA5, 0xAD, 0x9D, 0x8D, 0x19, 0xE0, 0x00, 0x00, 0x06,
+ 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xB5, 0xAD, 0xED, 0xB5, 0x7E, 0xE0 };
diff --git a/lib/Adafruit_SSD1351-gemu-1.0/README.md b/lib/Adafruit_SSD1351-gemu-1.0/README.md
new file mode 100644
index 000000000..6414419d0
--- /dev/null
+++ b/lib/Adafruit_SSD1351-gemu-1.0/README.md
@@ -0,0 +1,2 @@
+### SSD3115 Arduino Library
+This library is for support for the 128x128 oled controller over 3 wire SPI. It is based heavily on the [Adafruit_SSD1351](https://github.com/adafruit/Adafruit-SSD1351-library) library and is designed to work with the [Adafruit_GFX library](https://github.com/adafruit/Adafruit-GFX-Library).
diff --git a/lib/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp b/lib/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp
new file mode 100644
index 000000000..3e1ccb2c7
--- /dev/null
+++ b/lib/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp
@@ -0,0 +1,520 @@
+/***************************************************
+ This is our library for the Adafruit SSD1351 Breakout and Shield
+
+ Check out the links above for our tutorials and wiring diagrams
+ These displays use SPI to communicate, 4 or 5 pins are required to
+ interface (RST is optional)
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries.
+ MIT license, all text above must be included in any redistribution
+ ****************************************************/
+#include
+#include "SSD1351.h"
+#include
+#include
+
+
+const uint16_t ssd1351_colors[]={SSD1351_BLACK,SSD1351_WHITE,SSD1351_RED,SSD1351_GREEN,SSD1351_BLUE,SSD1351_CYAN,SSD1351_MAGENTA,\
+ SSD1351_YELLOW,SSD1351_NAVY,SSD1351_DARKGREEN,SSD1351_DARKCYAN,SSD1351_MAROON,SSD1351_PURPLE,SSD1351_OLIVE,\
+SSD1351_LIGHTGREY,SSD1351_DARKGREY,SSD1351_ORANGE,SSD1351_GREENYELLOW,SSD1351_PINK};
+
+// Constructor when using software SPI. All output pins are configurable.
+SSD1351::SSD1351(int8_t cs,int8_t mosi,int8_t sclk) : Renderer(SSD1351_WIDTH, SSD1351_HEIGHT) {
+ _cs = cs;
+ _mosi = mosi;
+ _sclk = sclk;
+ _hwspi = 0;
+}
+
+#include "spi_register.h"
+
+/* CPU Clock = 80 Mhz
+max clock of display is 4.545 Mhz (220ns sclk cycle)
+so cpu/18 => 4.44 Mhz should be ok
+HSPI CLK 5 GPIO14
+HSPI /CS 8 GPIO15
+HSPI MOSI 7 GPIO13
+*/
+
+uint8_t ssd131_start;
+
+uint32_t ssd1351_clock;
+uint32_t ssd1351_usr;
+uint32_t ssd1351_usr1;
+uint32_t ssd1351_usr2;
+uint32_t ssd1351_spi1c;
+uint32_t ssd1351_spi1p;
+//uint32_t ssd1351_gpmux;
+uint32_t ssd1351_mtdo;
+
+
+uint32_t ssd1351_clock_prev;
+uint32_t ssd1351_usr_prev;
+uint32_t ssd1351_usr1_prev;
+uint32_t ssd1351_usr2_prev;
+uint32_t ssd1351_spi1c_prev;
+uint32_t ssd1351_spi1p_prev;
+//uint32_t ssd1351_gpmux_prev;
+uint32_t ssd1351_mtdo_prev;
+
+// code from espressif SDK
+/******************************************************************************
+ * FunctionName : spi_lcd_mode_init
+ * Description : SPI master initial function for driving LCD 3 wire spi
+*******************************************************************************/
+void SSD1351::spi_lcd_mode_init(void) {
+ uint32 regvalue;
+
+ ssd1351_clock_prev=SPI1CLK;
+ ssd1351_usr_prev=SPI1U;
+ ssd1351_usr1_prev=SPI1U1;
+ ssd1351_usr2_prev=SPI1U2;
+ ssd1351_spi1c_prev=SPI1C;
+ ssd1351_spi1p_prev=SPI1P;
+ //ssd1351_gpmux_prev=GPMUX;
+ ssd1351_mtdo_prev=READ_PERI_REG(PERIPHS_IO_MUX_MTDO_U);
+
+ SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE;
+ SPI1U1=0;
+ SPI1C = 0;
+
+ //bit9 of PERIPHS_IO_MUX should be cleared when HSPI clock doesn't equal CPU clock
+ //bit8 of PERIPHS_IO_MUX should be cleared when SPI clock doesn't equal CPU clock
+
+ WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9
+ //PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure miso to spi mode
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure mosi to spi mode
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure sclk to spi mode
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure cs to spi mode
+
+// the current implementation leaves about 1 us between transfers ????
+// due to lack of documentation i could not find the reason
+// skipping this would double the speed !!!
+
+ //SET_PERI_REG_MASK(SPI_USER(1), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND);
+
+ SET_PERI_REG_MASK(SPI_USER(1), SPI_USR_COMMAND);
+
+ CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_FLASH_MODE);
+ // SPI clock=CPU clock/8 => 10 Mhz
+ /*
+ WRITE_PERI_REG(SPI_CLOCK(1),
+ ((1&SPI_CLKDIV_PRE)<>1)&0x7f;
+
+ start();
+
+//#define SPI_USR_COMMAND_BITLEN 0x0000000F
+//#define SPI_USR_COMMAND_BITLEN_S 28
+
+ regvalue= ((8&SPI_USR_COMMAND_BITLEN)<>1)|0x80;
+
+ start();
+
+ regvalue= ((8&SPI_USR_COMMAND_BITLEN)<=sizeof(ssd1351_colors)/2) index=0;
+ return ssd1351_colors[index];
+}
+
+void SSD1351::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
+ setRotation(rot);
+ invertDisplay(false);
+ setTextWrap(false); // Allow text to run off edges
+ cp437(true);
+ setTextFont(font&3);
+ setTextSize(size&7);
+ setTextColor(SSD1351_WHITE,SSD1351_BLACK);
+ setCursor(0,0);
+ fillScreen(SSD1351_BLACK);
+ stop();
+}
+
+void SSD1351::DisplayOnff(int8_t on) {
+ if (on) {
+ writecommand(SSD1351_CMD_DISPLAYON); //Display on
+ } else {
+ writecommand(SSD1351_CMD_DISPLAYOFF);
+ }
+ stop();
+}
+
+// dimmer 0-100
+void SSD1351::dim(uint8_t contrast) {
+ writecommand(SSD1351_CMD_CONTRASTMASTER);
+ if (contrast>15) contrast=15;
+ writedata(contrast);
+ stop();
+}
+
+/*
+if (SSD_COMSPLIT == 1){
+ _remapReg |= ((1 << 5));
+ } else {
+ _remapReg |= ((0 << 5));
+ }
+ setRegister_cont(CMD_CMDLOCK,SSD_COMMANDLOCK1);
+ setRegister_cont(CMD_CMDLOCK,SSD_COMMANDLOCK2);
+ writecommand_cont(CMD_DISPLAYOFF);
+ setRegister_cont(CMD_CLOCKDIV,SSD_CLOCKDIV);
+ setRegister_cont(CMD_MUXRATIO,SSD_MUXRATIO);
+ setRegister_cont(CMD_STARTLINE,SSD_STARTLINE); >>>
+ setRegister_cont(CMD_DISPLAYOFFSET,SSD_DISPLAYOFFSET);
+ setRegister_cont(CMD_SETGPIO,SSD_SETGPIO);
+ setRegister_cont(CMD_FUNCTIONSELECT,SSD_FUNCTIONSELECT);
+ writecommand_cont(CMD_SETVSL);
+ writedata8_cont(SSD_SETVSL_A);writedata8_cont(SSD_SETVSL_B);writedata8_cont(SSD_SETVSL_C);
+ writecommand_cont(CMD_CONTRASTABC);
+ writedata8_cont(SSD_CONTRAST_A);writedata8_cont(SSD_CONTRAST_B);writedata8_cont(SSD_CONTRAST_C);
+ setRegister_cont(CMD_MASTERCURRENT,SSD_MASTERCURRENT); >>>
+ writecommand_cont(CMD_DISPLAYENHANCE); >>
+ if (SSD_ENHANCE){
+ writedata8_cont(0xA4);
+ } else {
+ writedata8_cont(0x00);
+ }
+ writedata8_cont(0x00);
+ writedata8_cont(0x00);
+ #if defined(SSD_GAMMASET)
+ //writecommand_cont(CMD_GRAYSCALE); for (uint8_t i =0;i<32;i++){writedata8_cont(SSD_GRAYTABLE[i]);}
+ #else
+ writecommand_cont(CMD_USELUT);
+ #endif
+ // phase here
+ setRegister_cont(CMD_PRECHARGE,SSD_PRECHARGE); >>
+ setRegister_cont(CMD_PRECHARGE2,SSD_PRECHARGE2);
+ setRegister_cont(CMD_VCOMH,SSD_VCOMH);
+ #endif
+ //setAddrWindow_cont(0,0,SSD_WIDTH-1,SSD_HEIGHT-1,false);// ???
+ //_pushColors_cont(_defaultBgColor, SSD_CGRAM);//???
+ //Normal Display and turn ON
+ writecommand_cont(CMD_NORMALDISPLAY);
+*/
+static const uint8_t PROGMEM initList[] = {
+ SSD1351_CMD_COMMANDLOCK, 1, // Set command lock, 1 arg
+ 0x12,
+ SSD1351_CMD_COMMANDLOCK, 1, // Set command lock, 1 arg
+ 0xB1,
+ SSD1351_CMD_DISPLAYOFF, 0, // Display off, no args
+ SSD1351_CMD_CLOCKDIV, 1,
+ 0xF1, // 7:4 = Oscillator Freq, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
+ SSD1351_CMD_MUXRATIO, 1,
+ 127,
+ SSD1351_CMD_DISPLAYOFFSET, 1,
+ 0x0,
+ SSD1351_CMD_SETGPIO, 1,
+ 0x00,
+ SSD1351_CMD_FUNCTIONSELECT, 1,
+ 0x01, // internal (diode drop)
+ SSD1351_CMD_PRECHARGE, 1,
+ 0x32,
+ SSD1351_CMD_VCOMH, 1,
+ 0x05,
+ SSD1351_CMD_STARTLINE, 1,
+ 0x00,
+ SSD1351_CMD_NORMALDISPLAY, 0,
+ SSD1351_CMD_CONTRASTABC, 3,
+ 0xC8, 0x80, 0xC8,
+ SSD1351_CMD_CONTRASTMASTER, 1,
+ 0x0F,
+ SSD1351_CMD_SETVSL, 3,
+ 0xA0, 0xB5, 0x55,
+ SSD1351_CMD_PRECHARGE2, 1,
+ 0x01,
+ SSD1351_CMD_HORIZSCROLL, 1,
+ 0x00,
+ SSD1351_CMD_STOPSCROLL, 0,
+ SSD1351_CMD_DISPLAYON, 0, // Main screen turn on
+ 0 }; // END OF COMMAND LIST
+
+
+ void SSD1351::sendcommand(uint8_t commandByte, const uint8_t *dataBytes, uint8_t numDataBytes) {
+ writecommand(commandByte);
+ for (int i=0; i 0) { // '0' command ends list
+ x = pgm_read_byte(addr++);
+ numArgs = x & 0x7F;
+ if (cmd != 0xFF) { // '255' is ignored
+ sendcommand(cmd, addr, numArgs);
+ }
+ addr += numArgs;
+ }
+ delay(100);
+ setRotation(0);
+ stop();
+}
+
+
+#define ssd1351_swap(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) ///< No-temp-var swap operation
+
+
+
+void SSD1351::setAddrWindow_i(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h) {
+ uint16_t x2 = x1 + w - 1,
+ y2 = y1 + h - 1;
+ if (rotation&1) { // Vertical address increment mode
+ ssd1351_swap(x1,y1);
+ ssd1351_swap(x2,y2);
+ }
+ writecommand(SSD1351_CMD_SETCOLUMN); // X range
+ writedata(x1);
+ writedata(x2);
+ writecommand(SSD1351_CMD_SETROW); // Y range
+ writedata(y1);
+ writedata(y2);
+ writecommand(SSD1351_CMD_WRITERAM); // Begin write
+}
+
+void SSD1351::write16BitColor(uint16_t color){
+ writedata(color>>8);
+ writedata(color&0xff);
+}
+
+#define MADCTL_MY 0x80
+#define MADCTL_MX 0x40
+#define MADCTL_MV 0x20
+#define MADCTL_ML 0x10
+#define MADCTL_RGB 0x00
+#define MADCTL_BGR 0x08
+#define MADCTL_MH 0x04
+
+void SSD1351::setRotation(uint8_t r) {
+ // madctl bits:
+ // 6,7 Color depth (01 = 64K)
+ // 5 Odd/even split COM (0: disable, 1: enable)
+ // 4 Scan direction (0: top-down, 1: bottom-up)
+ // 3 Reserved
+ // 2 Color remap (0: A->B->C, 1: C->B->A)
+ // 1 Column remap (0: 0-127, 1: 127-0)
+ // 0 Address increment (0: horizontal, 1: vertical)
+ uint8_t madctl = 0b01100100; // 64K, enable split, CBA
+
+ rotation = r & 3; // Clip input to valid range
+
+ switch(rotation) {
+ case 0:
+ madctl |= 0b00010000; // Scan bottom-up
+ _width = SSD1351_WIDTH;
+ _height = SSD1351_HEIGHT;
+ break;
+ case 1:
+ madctl |= 0b00010011; // Scan bottom-up, column remap 127-0, vertical
+ _width = SSD1351_HEIGHT;
+ _height = SSD1351_WIDTH;
+ break;
+ case 2:
+ madctl |= 0b00000010; // Column remap 127-0
+ _width = SSD1351_WIDTH;
+ _height = SSD1351_HEIGHT;
+ break;
+ case 3:
+ madctl |= 0b00000001; // Vertical
+ _width = SSD1351_HEIGHT;
+ _height = SSD1351_WIDTH;
+ break;
+ }
+
+ sendcommand(SSD1351_CMD_SETREMAP, &madctl, 1);
+ uint8_t startline = (rotation < 2) ? SSD1351_HEIGHT : 0;
+ sendcommand(SSD1351_CMD_STARTLINE, &startline, 1);
+ stop();
+}
+
+void SSD1351::invertDisplay(boolean i) {
+ writecommand(i ? SSD1351_CMD_INVERTDISPLAY : SSD1351_CMD_NORMALDISPLAY);
+ stop();
+}
+
+void SSD1351::drawPixel(int16_t x, int16_t y, uint16_t color) {
+ if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
+ setAddrWindow_i(x,y,1,1);
+ write16BitColor(color);
+ stop();
+}
+
+void SSD1351::setAddrWindow(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
+ // uint16_t x2 = x1 + w - 1,
+ // y2 = y1 + h - 1;
+ uint8_t flag=0;
+
+ if (!x1 && !y1 && !x2 && !y2) {
+ x1=0;
+ y1=0;
+ x2=_width;
+ y2=_height;
+ flag=1;
+ }
+
+ if (x2>_width) x2=_width;
+ if (y2>_height) y2=_height;
+
+ x2--;
+ y2--;
+ if (rotation&1) { // Vertical address increment mode
+ ssd1351_swap(x1,y1);
+ ssd1351_swap(x2,y2);
+ }
+ //Serial.printf("x1:%d x2:%d y1:%d y2:%d\n",x1,x2,y1,y2);
+ writecommand(SSD1351_CMD_SETCOLUMN); // X range
+ writedata(x1);
+ writedata(x2);
+ writecommand(SSD1351_CMD_SETROW); // Y range
+ writedata(y1);
+ writedata(y2);
+ writecommand(SSD1351_CMD_WRITERAM); // Begin write
+ if (flag) stop();
+}
+
+void SSD1351::pushColors(uint16_t *data, uint8_t len, boolean first) {
+ for (uint16_t b=0; b= _width) || (y >= _height)) return;
+ if ((y+h-1) >= _height) h = _height-y;
+
+ setAddrWindow_i(x,y,1,h);
+ while (h--) {
+ write16BitColor(color);
+ }
+ stop();
+}
+
+void SSD1351::drawFastHLine(int16_t x,int16_t y,int16_t w,uint16_t color) {
+ // Rudimentary clipping
+ if ((x >= _width) || (y >= _height)) return;
+ if ((x+w-1) >= _width) w = _width-x;
+
+ setAddrWindow_i(x,y,w,1);
+ while (w--) {
+ write16BitColor(color);
+ }
+ stop();
+}
+
+void ICACHE_RAM_ATTR SSD1351::fastSPIwrite(uint8_t d,uint8_t dc) {
+
+ WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_cs);
+ WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk);
+ if(dc) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi);
+ else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi);
+ WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk);
+
+ for(uint8_t bit = 0x80; bit; bit >>= 1) {
+ WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk);
+ if(d&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi);
+ else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi);
+ WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk);
+ }
+ WRITE_PERI_REG( PIN_OUT_SET, 1<<_cs);
+}
diff --git a/lib/Adafruit_SSD1351-gemu-1.0/SSD1351.h b/lib/Adafruit_SSD1351-gemu-1.0/SSD1351.h
new file mode 100644
index 000000000..ecfac6b17
--- /dev/null
+++ b/lib/Adafruit_SSD1351-gemu-1.0/SSD1351.h
@@ -0,0 +1,129 @@
+/***************************************************
+ This is our library for the Adafruit SSD1351 Breakout and Shield
+ ----> http://www.adafruit.com/products/1651
+
+ Check out the links above for our tutorials and wiring diagrams
+ These displays use SPI to communicate, 3 pins are required to
+ interface
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries.
+ MIT license, all text above must be included in any redistribution
+ ****************************************************/
+
+#ifndef _SSD1351_
+#define _SSD1351_
+
+#if ARDUINO >= 100
+ #include "Arduino.h"
+ #include "Print.h"
+#else
+ #include "WProgram.h"
+#endif
+
+#include
+#include
+
+
+
+#define SSD1351_WIDTH 128
+#define SSD1351_HEIGHT 128
+
+
+// Color definitions
+#define SSD1351_BLACK 0x0000 /* 0, 0, 0 */
+#define SSD1351_NAVY 0x000F /* 0, 0, 128 */
+#define SSD1351_DARKGREEN 0x03E0 /* 0, 128, 0 */
+#define SSD1351_DARKCYAN 0x03EF /* 0, 128, 128 */
+#define SSD1351_MAROON 0x7800 /* 128, 0, 0 */
+#define SSD1351_PURPLE 0x780F /* 128, 0, 128 */
+#define SSD1351_OLIVE 0x7BE0 /* 128, 128, 0 */
+#define SSD1351_LIGHTGREY 0xC618 /* 192, 192, 192 */
+#define SSD1351_DARKGREY 0x7BEF /* 128, 128, 128 */
+#define SSD1351_BLUE 0x001F /* 0, 0, 255 */
+#define SSD1351_GREEN 0x07E0 /* 0, 255, 0 */
+#define SSD1351_CYAN 0x07FF /* 0, 255, 255 */
+#define SSD1351_RED 0xF800 /* 255, 0, 0 */
+#define SSD1351_MAGENTA 0xF81F /* 255, 0, 255 */
+#define SSD1351_YELLOW 0xFFE0 /* 255, 255, 0 */
+#define SSD1351_WHITE 0xFFFF /* 255, 255, 255 */
+#define SSD1351_ORANGE 0xFD20 /* 255, 165, 0 */
+#define SSD1351_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
+#define SSD1351_PINK 0xF81F
+
+#define SSD1351_CMD_SETCOLUMN 0x15
+#define SSD1351_CMD_SETROW 0x75
+#define SSD1351_CMD_WRITERAM 0x5C
+#define SSD1351_CMD_READRAM 0x5D
+#define SSD1351_CMD_SETREMAP 0xA0
+#define SSD1351_CMD_STARTLINE 0xA1
+#define SSD1351_CMD_DISPLAYOFFSET 0xA2
+#define SSD1351_CMD_DISPLAYALLOFF 0xA4
+#define SSD1351_CMD_DISPLAYALLON 0xA5
+#define SSD1351_CMD_NORMALDISPLAY 0xA6
+#define SSD1351_CMD_INVERTDISPLAY 0xA7
+#define SSD1351_CMD_FUNCTIONSELECT 0xAB
+#define SSD1351_CMD_DISPLAYOFF 0xAE
+#define SSD1351_CMD_DISPLAYON 0xAF
+#define SSD1351_CMD_PRECHARGE 0xB1
+#define SSD1351_CMD_DISPLAYENHANCE 0xB2
+#define SSD1351_CMD_CLOCKDIV 0xB3
+#define SSD1351_CMD_SETVSL 0xB4
+#define SSD1351_CMD_SETGPIO 0xB5
+#define SSD1351_CMD_PRECHARGE2 0xB6
+#define SSD1351_CMD_SETGRAY 0xB8
+#define SSD1351_CMD_USELUT 0xB9
+#define SSD1351_CMD_PRECHARGELEVEL 0xBB
+#define SSD1351_CMD_VCOMH 0xBE
+#define SSD1351_CMD_CONTRASTABC 0xC1
+#define SSD1351_CMD_CONTRASTMASTER 0xC7
+#define SSD1351_CMD_MUXRATIO 0xCA
+#define SSD1351_CMD_COMMANDLOCK 0xFD
+#define SSD1351_CMD_HORIZSCROLL 0x96
+#define SSD1351_CMD_STOPSCROLL 0x9E
+#define SSD1351_CMD_STARTSCROLL 0x9F
+
+
+#define PIN_OUT_SET 0x60000304
+#define PIN_OUT_CLEAR 0x60000308
+
+class SSD1351 : public Renderer {
+
+ public:
+
+ SSD1351(int8_t cs,int8_t mosi,int8_t sclk);
+
+ void begin(void);
+ void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
+ void setAddrWindow_i(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
+ void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
+ void pushColors(uint16_t *data, uint8_t len, boolean first);
+ void drawPixel(int16_t x, int16_t y, uint16_t color);
+ void write16BitColor(uint16_t color);
+ void setRotation(uint8_t r);
+ void invertDisplay(boolean i);
+ uint16_t GetColorFromIndex(uint8_t index);
+ void DisplayOnff(int8_t on);
+ void writecommand(uint8_t c);
+ void writedata(uint8_t d);
+ void commandList(uint8_t *addr);
+ void hw_spi_init();
+ void sendcommand(uint8_t commandByte, const uint8_t *dataBytes, uint8_t numDataBytes);
+ void sendcommand(uint8_t commandByte,uint8_t *dataBytes, uint8_t numDataBytes);
+ void drawFastVLine(int16_t x,int16_t y,int16_t h,uint16_t color);
+ void drawFastHLine(int16_t x,int16_t y,int16_t w,uint16_t color);
+ void spi_lcd_mode_init(void);
+ void dim(uint8_t contrast);
+
+ private:
+ uint8_t tabcolor;
+ void fastSPIwrite(uint8_t d,uint8_t dc);
+ void start(void);
+ void stop(void);
+ int8_t _cs, _mosi, _sclk, _hwspi;
+
+};
+
+#endif
diff --git a/lib/Adafruit_SSD1351-gemu-1.0/Tiger.c b/lib/Adafruit_SSD1351-gemu-1.0/Tiger.c
new file mode 100644
index 000000000..83e0ba9bf
--- /dev/null
+++ b/lib/Adafruit_SSD1351-gemu-1.0/Tiger.c
@@ -0,0 +1,42 @@
+#include
+// picture with 51 x 34 pixels
+// table size 3468 bytes
+#if 0
+const uint16_t picture[] = {
+0x0000,0x0841,0x0841,0x0840,0x0841,0x0841,0x1041,0x1041,0x1041,0x1041,0x1041,0x1880,0x1041,0x1041,0x1040,0x1041,0x1881,0x1880,0x1880,0x1880,0x2081,0x2081,0x2080,0x20c1,0x3942,0x3942,0x3101,0x2080,0x2881,0x2880,0x2881,0x2881,0x2881,0x2880,0x2881,0x30c1,0x30c1,0x1840,0x2881,0x30c1,0x3901,0x3941,0x3901,0x3101,0x3101,0x3101,0x3101,0x3101,0x4182,0x4182,0x0000,
+0x0000,0x0841,0x0841,0x0841,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x2081,0x28c1,0x2081,0x2080,0x2081,0x2081,0x28c1,0x28c1,0x2901,0x3101,0x3101,0x3101,0x3101,0x3942,0x5a04,0x6244,0x6244,0x51c2,0x4101,0x4101,0x4101,0x4101,0x3901,0x4101,0x4101,0x5181,0x4941,0x59c2,0x4141,0x30c1,0x4941,0x4982,0x38c1,0x5182,0x4141,0x4101,0x4941,0x5182,0x5182,0x6a43,0x0000,
+0x0000,0x1041,0x0841,0x1041,0x1881,0x20c1,0x2081,0x20c1,0x2081,0x28c1,0x20c1,0x2901,0x2081,0x2081,0x20c1,0x28c1,0x28c1,0x3101,0x3101,0x3101,0x3101,0x3941,0x3942,0x4183,0x5a45,0x6244,0x6a85,0x6a84,0x5a03,0x4141,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101,0x4941,0x4141,0x59c2,0x2880,0x38c1,0x4941,0x4941,0x4141,0x4941,0x5181,0x5182,0x6203,0x6203,0x0000,
+0x0000,0x20c1,0x1041,0x1881,0x2901,0x3142,0x20c1,0x28c1,0x2901,0x2901,0x2901,0x2901,0x2901,0x2901,0x3101,0x3101,0x3141,0x3942,0x4182,0x4182,0x49c3,0x49c3,0x5204,0x5a45,0x5a45,0x5a45,0x6245,0x6245,0x5a45,0x5a04,0x51c2,0x4141,0x4101,0x4101,0x4101,0x6244,0x8388,0x5a04,0x4101,0x4101,0x4901,0x5182,0x30c1,0x4982,0x4982,0x5182,0x4941,0x4941,0x5181,0x4141,0x0000,
+0x0000,0x1881,0x1041,0x1881,0x2101,0x2902,0x28c1,0x2901,0x2901,0x2901,0x2901,0x28c1,0x20c1,0x20c1,0x28c1,0x28c1,0x28c1,0x3942,0x4182,0x4141,0x4182,0x4982,0x4982,0x51c3,0x51c3,0x51c3,0x51c3,0x51c3,0x51c3,0x51c3,0x5a04,0x51c3,0x4982,0x4141,0x9c09,0xd612,0xbd50,0xa48c,0x4100,0x4101,0x4101,0x4101,0x59c2,0x4981,0x3901,0x3901,0x3901,0x4941,0x4101,0x5182,0x0000,
+0x0000,0x1881,0x1041,0x1881,0x2902,0x2902,0x2902,0x3142,0x3102,0x3102,0x2901,0x28c1,0x28c1,0x28c1,0x28c1,0x28c1,0x3942,0x51c3,0x6a84,0x3941,0x4182,0x4982,0x4982,0x5a03,0x5a03,0x6244,0x5a04,0x51c3,0x51c3,0x5a03,0x5a44,0x5204,0x3942,0x9bc8,0xcd8f,0xc590,0xc5d1,0xcdd2,0x4100,0x4101,0x4101,0x4101,0x4941,0x4941,0x5182,0x3101,0x4941,0x4941,0x4941,0x4941,0x0000,
+0x0000,0x1881,0x1041,0x1881,0x3142,0x3142,0x3102,0x3142,0x3142,0x3102,0x3101,0x28c1,0x28c1,0x28c1,0x28c1,0x5204,0x8bc9,0xbd4f,0xcdd1,0xcdd0,0x6244,0x4982,0x51c2,0x5a45,0xac4a,0x9387,0x4982,0x8b87,0x9387,0x8346,0x6a86,0x5204,0xac89,0xaccc,0xc54f,0xb4ce,0x9c4b,0xc5d1,0x4100,0x4901,0x4101,0x4941,0x4941,0x4101,0x4142,0x6203,0x4941,0x2081,0x38c1,0x5182,0x0000,
+0x0000,0x1881,0x1041,0x2081,0x3143,0x3142,0x3142,0x3983,0x3943,0x3102,0x3101,0x28c1,0x28c1,0x28c1,0x2901,0x8b89,0x9c0b,0x9c0a,0xd612,0xac8c,0xd5d1,0x9bc8,0xbc8a,0x9bc7,0xa3c7,0x9bc7,0x9b86,0x9bc7,0x8347,0x93c8,0xac8b,0xc50c,0xcd4b,0xb48a,0xde12,0xde94,0xaccd,0x6ac6,0x4101,0x4101,0x4941,0x4901,0x4101,0x4941,0x4101,0x38c1,0x3901,0x4141,0x2081,0x3901,0x0000,
+0x0000,0x1881,0x1041,0x20c1,0x3984,0x3143,0x3943,0x41c4,0x3983,0x3142,0x3101,0x3101,0x3101,0x3101,0x3101,0x9c0a,0x7ac5,0x6203,0xa48c,0xc54f,0xa44b,0xbd0c,0xac08,0x8306,0xc54c,0x72c5,0x7b06,0x6a85,0xddcd,0xcd4c,0x93c7,0xcd0b,0x9386,0xdd8c,0xe60f,0xac8b,0x8389,0x6244,0x6203,0x5181,0x4101,0x4101,0x4901,0x4901,0x4101,0x3901,0x3081,0x38c1,0x59c2,0x4141,0x0000,
+0x0000,0x2081,0x1841,0x28c1,0x41c4,0x3142,0x3983,0x49c5,0x4184,0x3102,0x3101,0x3101,0x3101,0x3101,0x3101,0x8348,0xa44b,0x6203,0x6204,0xb50e,0xbd0d,0xe60f,0xe650,0xee90,0x8346,0xb48b,0xb48b,0x7b07,0x72c6,0xd54c,0xbd0b,0xf758,0xffd9,0xb489,0xac07,0xe60e,0xee92,0x5204,0x51c3,0x5181,0x4941,0x4941,0x4101,0x4101,0x4941,0x4101,0x4101,0x3081,0x30c1,0x6a43,0x0000,
+0x0000,0x1881,0x1841,0x28c1,0x41c4,0x3983,0x3983,0x41c4,0x3983,0x3102,0x3101,0x3101,0x3101,0x3101,0x3101,0x3941,0x6245,0x7285,0x9c4b,0xa44b,0xee90,0xdd8c,0x8b05,0xde10,0x940b,0xd58e,0xddcd,0xcd0b,0xdd8c,0x8b47,0x9b87,0xbd90,0xd654,0xffda,0xb48b,0xa3c7,0x9c08,0x6285,0x49c3,0x4983,0x4942,0x4941,0x5181,0x4101,0x4101,0x4941,0x4101,0x38c1,0x30c1,0x4141,0x0000,
+0x0000,0x1881,0x1881,0x28c1,0x41c4,0x3983,0x41c4,0x4183,0x3942,0x3101,0x3101,0x3101,0x3101,0x3901,0x3901,0x3901,0x4142,0x8bc9,0x6286,0x8b87,0xbc89,0x9345,0xc50b,0xffd9,0xce13,0xe716,0xcd4b,0x7ac5,0xc4ca,0x7284,0x9bc8,0xcdd0,0xde53,0xbd91,0xce13,0xbd0d,0xe60f,0xb4cc,0x6ac6,0x51c4,0x49c3,0x4982,0x5182,0x5181,0x4941,0x4101,0x4101,0x4101,0x4101,0x4101,0x0000,
+0x0000,0x1881,0x1881,0x2901,0x41c4,0x3983,0x41c4,0x4183,0x3942,0x3101,0x3101,0x3901,0x3901,0x3101,0x3101,0x6244,0x8b05,0xa409,0xd58d,0xb448,0x82c4,0xbcca,0xee93,0xf757,0xb50f,0xbd4f,0x9c4b,0xb489,0x8b46,0xcd0a,0x7ac4,0x9bc8,0xff98,0xb50f,0xacce,0x940a,0xb4cc,0xac8b,0xeed4,0x51c4,0x49c3,0x49c3,0x4983,0x51c3,0x4941,0x4101,0x4101,0x3901,0x4101,0x38c1,0x0000,
+0x0000,0x2081,0x2081,0x2901,0x4184,0x3983,0x4183,0x3942,0x3142,0x3101,0x3101,0x3101,0x3941,0x3101,0x7ac5,0x7ac5,0x6a43,0x6a43,0x6a43,0xbcca,0xe5cd,0x4182,0x9c4b,0x4183,0x8bca,0xa44c,0xb4cd,0xb447,0xb448,0xccc9,0xccca,0xc4c9,0xee94,0x6245,0x838a,0x8b46,0xd5cf,0xde52,0xef15,0x51c3,0x49c3,0x49c3,0x49c3,0x5a45,0x4982,0x4941,0x5141,0x4941,0x3901,0x4101,0x0000,
+0x0000,0x2081,0x2080,0x3102,0x3983,0x4184,0x3942,0x3142,0x3942,0x3942,0x3901,0x3941,0x3942,0x7ac5,0x7ac4,0x82c4,0x59c2,0xa3c8,0x5a45,0xd5cd,0xe60f,0xbccb,0x9c09,0xc54e,0x8389,0x93c8,0x9b87,0x69c2,0x8ac4,0xbc89,0xcd0a,0xbc88,0x8bca,0x8b86,0xbd92,0x8305,0xddcf,0xb50e,0xacce,0x5a45,0x51c3,0x49c3,0x49c3,0x5a46,0x4982,0x4982,0x4941,0x4101,0x30c1,0x30c1,0x0000,
+0x0000,0x2081,0x2081,0x3142,0x49c4,0x4a05,0x4184,0x4183,0x4183,0x49c3,0x4183,0x7ac6,0x9bc8,0x9b86,0xa386,0x6a44,0x3901,0xb48b,0x4182,0xd54c,0x3101,0xc4ca,0x6244,0x8348,0x61c2,0x6202,0x5a04,0x7a84,0x69c2,0xac07,0xcd0a,0xb448,0x7307,0xf79a,0x7284,0xbc89,0xaccd,0x940b,0x6245,0x51c3,0x51c3,0x49c3,0x49c3,0x6246,0x4982,0x4982,0x4982,0x4141,0x3081,0x2881,0x0000,
+0x0000,0x28c1,0x28c1,0x4184,0x5206,0x4a05,0x49c4,0x49c4,0x49c4,0x5205,0x9b87,0x7b06,0x9386,0xa3c6,0x51c2,0x61c2,0x5981,0xe652,0x5204,0xa449,0x3901,0xa3c7,0xac07,0x9305,0x8348,0xb4ce,0x28c1,0x61c2,0x7243,0x9b45,0xcd0a,0xbc89,0x8b05,0xcd8e,0xcd4b,0x8347,0xffd9,0xd654,0x6a87,0x6286,0x6286,0x5a46,0x5a46,0x6287,0x5a45,0x5204,0x5204,0x5204,0x4182,0x2081,0x0000,
+0x0000,0x28c1,0x28c1,0x3983,0x41c4,0x41c4,0x4184,0x4184,0x7285,0x82c5,0xa387,0x49c3,0xa3c7,0x9b86,0x4182,0x6a02,0x61c2,0x8b88,0x4142,0x72c5,0x6a84,0xa3c7,0x4982,0x3101,0xa3c6,0xbc8a,0x51c3,0x4941,0x7202,0xac07,0xbc89,0xcd0a,0xccca,0x9b87,0xcd0b,0x8b89,0x7b8a,0xa48e,0x5204,0x5204,0x49c4,0x49c3,0x49c3,0x49c4,0x49c3,0x4983,0x4183,0x4182,0x4182,0x3982,0x0000,
+0x0000,0x2081,0x28c1,0x3983,0x41c4,0x4184,0x4184,0x5a03,0x9b86,0x9b86,0x7ac5,0x6244,0x9346,0x9b46,0x4141,0x6a02,0x69c2,0x8305,0x7285,0x3941,0xa449,0xac08,0xcd0c,0x9b86,0x7ac5,0xac08,0x9388,0x6202,0x7a83,0xac09,0xa408,0xcd0b,0xc50b,0xa3c6,0xbcca,0xff99,0x940c,0xaccf,0x49c3,0x49c3,0x49c3,0x4183,0x4183,0x4183,0x4183,0x4182,0x3942,0x3942,0x3942,0x4183,0x0000,
+0x0000,0x2081,0x28c1,0x3943,0x41c4,0x4184,0x4183,0x9386,0x9b87,0xa408,0x9346,0x6a44,0x8b05,0x8284,0x5982,0x7a43,0x5181,0x7a43,0x9c09,0x72c6,0xbd0c,0x5a03,0x93c8,0x6a45,0x8b05,0x9b86,0x7a84,0x7243,0x7243,0x9b86,0xb489,0xbccb,0xbccb,0xb447,0xbc8a,0x6ac7,0xce13,0xc5d2,0x49c3,0x49c3,0x4983,0x4183,0x4183,0x4182,0x4182,0x4182,0x3942,0x3942,0x3942,0x4183,0x0000,
+0x0000,0x2080,0x28c1,0x3942,0x3984,0x7b06,0x7285,0x7ac5,0x9b87,0x9b86,0x9345,0x6203,0x8284,0x7a83,0x5982,0x7202,0x7203,0x7243,0x9387,0x7b07,0x8b88,0x8347,0x2080,0xb4cb,0xbccc,0x5a03,0x6a03,0x8b04,0x61c2,0x8b05,0xb48b,0xbccb,0xcd4c,0xac09,0xcd0b,0xc590,0x9c8d,0x7b89,0x4983,0x4983,0x4983,0x4183,0x4182,0x4182,0x4182,0x4182,0x3942,0x3942,0x3941,0x4183,0x0000,
+0x0000,0x2081,0x28c1,0x3942,0x8b46,0x8b05,0x8b05,0x3101,0x9b86,0x9345,0x8ac4,0x82c4,0x7a43,0x7a83,0x6a02,0x8283,0x8283,0x61c2,0x9b86,0x8b88,0x5204,0xb48b,0x51c3,0xac8a,0x3942,0x6a03,0x7243,0x9345,0x7284,0x8305,0xbccc,0xc54d,0xcd8d,0xc58e,0xcd4c,0xac8c,0xcdd2,0x7307,0x4183,0x4983,0x4982,0x4182,0x4182,0x4182,0x4182,0x3982,0x3942,0x3942,0x3101,0x4183,0x0000,
+0x0000,0x2081,0x5a03,0x59c2,0x4141,0x8283,0x82c4,0x4982,0x8b05,0x8b05,0x8284,0x82c4,0x8283,0x8283,0x7a43,0x8283,0x7a02,0x8ac3,0x9346,0x7285,0x93c9,0x5a44,0xa44a,0xb4cb,0x9388,0x7284,0x7a84,0x7243,0x4182,0x7ac5,0xa44a,0x9c4b,0xcd4e,0xbd0e,0xb4cb,0xde53,0xa4ce,0x7308,0x8bca,0x49c3,0x4182,0x4182,0x4182,0x4182,0x4142,0x3942,0x3942,0x3942,0x3101,0x4183,0x0000,
+0x0000,0x7243,0x7a43,0x8283,0x3101,0x59c2,0x7a83,0x7a83,0x4141,0x9345,0x8b05,0x7202,0x7203,0x7a43,0x7a43,0x69c2,0x61c2,0x7a02,0x82c4,0x9387,0xa44b,0x3101,0x4182,0x6a86,0x8b88,0xbd4e,0x6244,0x4981,0xac8b,0x4142,0x6203,0xb3c8,0x8307,0xffd9,0xac8b,0x8389,0xa48d,0xa4cd,0x8bca,0x7b49,0x49c3,0x4182,0x4182,0x3982,0x4182,0x3942,0x3942,0x3141,0x3101,0x4183,0x0000,
+0x0000,0x6a02,0x7a43,0x7a83,0x8283,0x3901,0x7243,0x7a43,0x7a43,0x4982,0x8283,0x7a43,0x7243,0x5981,0x7202,0x7202,0x69c2,0x5981,0x7a42,0x9bc7,0x51c3,0x93c8,0xa449,0x93c9,0x7b48,0x8347,0x4142,0x6a84,0x8346,0xbccc,0x8b88,0x5182,0xde53,0xcdd1,0xd613,0x8bca,0xb50f,0x8bca,0x8bca,0x8389,0x6286,0x5204,0x4a04,0x49c3,0x4183,0x4183,0x4183,0x4182,0x3982,0x4a04,0x0000,
+0x0000,0x8283,0x61c2,0x59c2,0x7202,0x8283,0x4941,0x7a83,0x7243,0x7243,0x7a83,0x7a43,0x7a43,0x7242,0x6182,0x6181,0x7202,0x61c2,0x5981,0x7a43,0x6a43,0x8347,0x8346,0xb48b,0xb4cb,0x9c09,0x5a04,0x7b07,0x93c9,0x9c0a,0x9c0a,0x5a44,0xb4cd,0xa44d,0x8389,0xb50e,0xa44c,0x8b89,0x8b89,0x93ca,0x8388,0x8348,0x8348,0x7b48,0x7b07,0x7307,0x7307,0x72c7,0x6ac7,0x7307,0x0000,
+0x0000,0x8ac4,0x8283,0x7a83,0x61c2,0x7a43,0x7a43,0x4942,0x8ac4,0x6a02,0x4982,0x7a83,0x7202,0x7243,0x7a43,0x6a02,0x5941,0x69c2,0x5981,0x5981,0x9386,0x8b46,0x7284,0x5a03,0x51c3,0x8b88,0x6244,0x4183,0x4142,0x7b07,0x3941,0x5a44,0x3982,0x7b07,0x9c0b,0x8348,0x8bc9,0x8b89,0x8388,0x8388,0x8348,0x8348,0x8348,0x8348,0x7b47,0x7b07,0x7b07,0x7307,0x72c6,0x72c7,0x0000,
+0x0000,0x8ac4,0x8b04,0x82c3,0x82c4,0x82c4,0x8283,0x82c4,0x4982,0x8ac4,0x6a02,0x5182,0x7243,0x7202,0x7202,0x7202,0x6182,0x5141,0x6182,0x69c2,0x4941,0x7284,0x8b46,0x9bc8,0x8b46,0x93c8,0x49c3,0x3101,0x5a03,0x8306,0x72c7,0xb50e,0xacce,0xb50e,0x8348,0x8348,0x8b89,0x8348,0x8348,0x8348,0x8348,0x8348,0x8347,0x7b07,0x7b07,0x7b07,0x7307,0x72c7,0x72c6,0x72c6,0x0000,
+0x0000,0x8b04,0x8ac4,0x9305,0x8ac4,0x8ac4,0x9304,0x8ac4,0x8b04,0x59c2,0x6a03,0x7a43,0x6a03,0x6a02,0x7203,0x69c2,0x69c2,0x6182,0x5141,0x5941,0x69c2,0x5141,0x6203,0x7243,0x7ac5,0x7ac5,0x8346,0xa44a,0xb50d,0xbd0e,0xcd8f,0xd613,0xbd50,0x8bca,0x72c7,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x7307,0x7b07,0x7b07,0x7b07,0x7b07,0x7307,0x72c6,0x72c6,0x72c6,0x72c6,0x0000,
+0x0000,0x9345,0x9304,0x9345,0x9345,0x9345,0x9305,0x9345,0x9305,0x8ac4,0x7283,0x5182,0x6202,0x7243,0x6a02,0x69c2,0x61c2,0x5981,0x5982,0x5141,0x4101,0x5101,0x5982,0x5141,0x5141,0x61c2,0x8284,0x9386,0xa44a,0xde53,0xad0f,0xef16,0xe6d6,0x6245,0x4982,0x4982,0x4982,0x4982,0x49c2,0x49c2,0x49c3,0x49c3,0x51c3,0x51c3,0x51c3,0x5203,0x5203,0x5203,0x5203,0x5203,0x0000,
+0x0000,0x7a84,0x51c2,0x9b86,0x9b85,0x9304,0x8b04,0x8b04,0x8b04,0x9345,0x7a83,0x7a83,0x7a84,0x30c0,0x7243,0x61c2,0x6182,0x5981,0x5981,0x5141,0x5141,0x38c1,0x2881,0x38c1,0x5181,0x6a02,0x8b04,0xa407,0xcd4c,0xde52,0xef16,0xef57,0xd695,0x6285,0x5a04,0x51c3,0x49c3,0x4982,0x4182,0x3942,0x3941,0x3101,0x3101,0x28c1,0x28c1,0x20c1,0x2081,0x2081,0x2081,0x2081,0x0000,
+0x0000,0xa407,0x9b86,0x3901,0x9b86,0xa386,0x9345,0x82c4,0x8b04,0x82c4,0x9304,0x7243,0x59c2,0x7243,0x28c1,0x69c2,0x5981,0x5981,0x4941,0x4901,0x4901,0x5141,0x5141,0x5141,0x4101,0x4941,0x5182,0x5182,0x4182,0xcd8f,0xef16,0xef57,0xa4cf,0x7b07,0x7b07,0x7b07,0x7ac6,0x72c6,0x72c6,0x6a85,0x6a85,0x6245,0x6244,0x5a04,0x5203,0x49c3,0x4182,0x3942,0x3941,0x3101,0x0000,
+0x0000,0xac48,0xa407,0xac08,0x30c1,0x8b45,0xa3c7,0x9345,0x8b04,0x8ac4,0x82c4,0x82c4,0x7a83,0x6202,0x6a02,0x30c1,0x59c2,0x61c2,0x5141,0x4901,0x4101,0x4101,0x4101,0x4901,0x5141,0x6182,0x7202,0x8ac4,0xa407,0xac8a,0xa48d,0xef57,0xb550,0x7b06,0x7306,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x6ac6,0x6ac6,0x6a85,0x6a85,0x6a85,0x0000,
+0x0000,0x0000,0x1081,0x1081,0x1081,0x0000,0x1041,0x1041,0x0841,0x0840,0x0841,0x0840,0x0841,0x0000,0x0840,0x0840,0x0000,0x0800,0x0840,0x0800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0800,0x0840,0x0840,0x1041,0x1082,0x1082,0x18c3,0x1081,0x0841,0x0841,0x0841,0x0841,0x0841,0x0840,0x0840,0x0841,0x0841,0x0840,0x0841,0x0840,0x0841,0x0840,0x0840,0x0840,0x0840,0x0000,
+0x0000
+};
+#endif
diff --git a/lib/Adafruit_SSD1351-gemu-1.0/Tiger.rgb b/lib/Adafruit_SSD1351-gemu-1.0/Tiger.rgb
new file mode 100644
index 000000000..e3c49ce82
Binary files /dev/null and b/lib/Adafruit_SSD1351-gemu-1.0/Tiger.rgb differ
diff --git a/lib/Adafruit_SSD1351-gemu-1.0/keywords.txt b/lib/Adafruit_SSD1351-gemu-1.0/keywords.txt
new file mode 100644
index 000000000..cfc1e2023
--- /dev/null
+++ b/lib/Adafruit_SSD1351-gemu-1.0/keywords.txt
@@ -0,0 +1,30 @@
+#######################################
+# Syntax Coloring Map
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+SSD3115 KEYWORD1
+
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+setRotation KEYWORD2
+setAddrWindow KEYWORD2
+pushColor KEYWORD2
+drawPixel KEYWORD2
+drawFastVLine KEYWORD2
+drawFastHLine KEYWORD2
+fillRect KEYWORD2
+setRotation KEYWORD2
+setRotation KEYWORD2
+height KEYWORD2
+width KEYWORD2
+invertDisplay KEYWORD2
+drawImage KEYWORD2
+setScrollArea KEYWORD2
+scroll KEYWORD2
diff --git a/lib/Adafruit_SSD1351-gemu-1.0/library.properties b/lib/Adafruit_SSD1351-gemu-1.0/library.properties
new file mode 100644
index 000000000..e405f69b6
--- /dev/null
+++ b/lib/Adafruit_SSD1351-gemu-1.0/library.properties
@@ -0,0 +1,9 @@
+name=SSD3115
+version=1.0
+author=Limor Fried/Ladyada
+maintainer=Limor Fried/Ladyada
+sentence=Library for SSD3115 displays
+paragraph=Library for SSD3115 displays
+category=Display
+url=https://github.com/adafruit/Adafruit-SSD1351-library
+architectures=*
diff --git a/lib/Adafruit_SSD1351-gemu-1.0/spi_register.h b/lib/Adafruit_SSD1351-gemu-1.0/spi_register.h
new file mode 100644
index 000000000..340559ae1
--- /dev/null
+++ b/lib/Adafruit_SSD1351-gemu-1.0/spi_register.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2010 - 2011 Espressif System
+ *
+ */
+
+#ifndef SPI_REGISTER_H_INCLUDED
+#define SPI_REGISTER_H_INCLUDED
+
+#define REG_SPI_BASE(i) (0x60000200-i*0x100)
+#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
+#define SPI_USR (BIT(18))
+
+#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
+
+#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
+#define SPI_WR_BIT_ORDER (BIT(26))
+#define SPI_RD_BIT_ORDER (BIT(25))
+#define SPI_QIO_MODE (BIT(24))
+#define SPI_DIO_MODE (BIT(23))
+#define SPI_QOUT_MODE (BIT(20))
+#define SPI_DOUT_MODE (BIT(14))
+#define SPI_FASTRD_MODE (BIT(13))
+
+
+
+#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
+
+#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
+
+#define SPI_CS_DELAY_NUM 0x0000000F
+#define SPI_CS_DELAY_NUM_S 28
+#define SPI_CS_DELAY_MODE 0x00000003
+#define SPI_CS_DELAY_MODE_S 26
+#define SPI_MOSI_DELAY_NUM 0x00000007
+#define SPI_MOSI_DELAY_NUM_S 23
+#define SPI_MOSI_DELAY_MODE 0x00000003
+#define SPI_MOSI_DELAY_MODE_S 21
+#define SPI_MISO_DELAY_NUM 0x00000007
+#define SPI_MISO_DELAY_NUM_S 18
+#define SPI_MISO_DELAY_MODE 0x00000003
+#define SPI_MISO_DELAY_MODE_S 16
+#define SPI_CK_OUT_HIGH_MODE 0x0000000F
+#define SPI_CK_OUT_HIGH_MODE_S 12
+#define SPI_CK_OUT_LOW_MODE 0x0000000F
+#define SPI_CK_OUT_LOW_MODE_S 8
+
+#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
+#define SPI_CLK_EQU_SYSCLK (BIT(31))
+#define SPI_CLKDIV_PRE 0x00001FFF
+#define SPI_CLKDIV_PRE_S 18
+#define SPI_CLKCNT_N 0x0000003F
+#define SPI_CLKCNT_N_S 12
+#define SPI_CLKCNT_H 0x0000003F
+#define SPI_CLKCNT_H_S 6
+#define SPI_CLKCNT_L 0x0000003F
+#define SPI_CLKCNT_L_S 0
+
+#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
+#define SPI_USR_COMMAND (BIT(31))
+#define SPI_USR_ADDR (BIT(30))
+#define SPI_USR_DUMMY (BIT(29))
+#define SPI_USR_MISO (BIT(28))
+#define SPI_USR_MOSI (BIT(27))
+
+#define SPI_USR_MOSI_HIGHPART (BIT(25))
+#define SPI_USR_MISO_HIGHPART (BIT(24))
+
+
+#define SPI_SIO (BIT(16))
+#define SPI_FWRITE_QIO (BIT(15))
+#define SPI_FWRITE_DIO (BIT(14))
+#define SPI_FWRITE_QUAD (BIT(13))
+#define SPI_FWRITE_DUAL (BIT(12))
+#define SPI_WR_BYTE_ORDER (BIT(11))
+#define SPI_RD_BYTE_ORDER (BIT(10))
+#define SPI_CK_OUT_EDGE (BIT(7))
+#define SPI_CK_I_EDGE (BIT(6))
+#define SPI_CS_SETUP (BIT(5))
+#define SPI_CS_HOLD (BIT(4))
+#define SPI_FLASH_MODE (BIT(2))
+#define SPI_DOUTDIN (BIT(0))
+
+#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
+#define SPI_USR_ADDR_BITLEN 0x0000003F
+#define SPI_USR_ADDR_BITLEN_S 26
+#define SPI_USR_MOSI_BITLEN 0x000001FF
+#define SPI_USR_MOSI_BITLEN_S 17
+#define SPI_USR_MISO_BITLEN 0x000001FF
+#define SPI_USR_MISO_BITLEN_S 8
+
+#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
+#define SPI_USR_DUMMY_CYCLELEN_S 0
+
+#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
+#define SPI_USR_COMMAND_BITLEN 0x0000000F
+#define SPI_USR_COMMAND_BITLEN_S 28
+#define SPI_USR_COMMAND_VALUE 0x0000FFFF
+#define SPI_USR_COMMAND_VALUE_S 0
+
+#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
+#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
+#define SPI_CS2_DIS (BIT(2))
+#define SPI_CS1_DIS (BIT(1))
+#define SPI_CS0_DIS (BIT(0))
+#define SPI_IDLE_EDGE (BIT(29))
+
+#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
+#define SPI_SYNC_RESET (BIT(31))
+#define SPI_SLAVE_MODE (BIT(30))
+#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
+#define SPI_SLV_WR_RD_STA_EN (BIT(28))
+#define SPI_SLV_CMD_DEFINE (BIT(27))
+#define SPI_TRANS_CNT 0x0000000F
+#define SPI_TRANS_CNT_S 23
+#define SPI_TRANS_DONE_EN (BIT(9))
+#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
+#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
+#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
+#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
+
+
+
+#define SLV_SPI_INT_EN 0x0000001f
+#define SLV_SPI_INT_EN_S 5
+
+#define SPI_TRANS_DONE (BIT(4))
+#define SPI_SLV_WR_STA_DONE (BIT(3))
+#define SPI_SLV_RD_STA_DONE (BIT(2))
+#define SPI_SLV_WR_BUF_DONE (BIT(1))
+#define SPI_SLV_RD_BUF_DONE (BIT(0))
+
+#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
+#define SPI_SLV_STATUS_BITLEN 0x0000001F
+#define SPI_SLV_STATUS_BITLEN_S 27
+#define SPI_SLV_BUF_BITLEN 0x000001FF
+#define SPI_SLV_BUF_BITLEN_S 16
+#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
+#define SPI_SLV_RD_ADDR_BITLEN_S 10
+#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
+#define SPI_SLV_WR_ADDR_BITLEN_S 4
+
+#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
+#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
+#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
+#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
+
+
+
+#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
+#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF
+#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
+#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF
+#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
+#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF
+#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8
+#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
+#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
+
+#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
+#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
+#define SPI_SLV_WRSTA_CMD_VALUE_S 24
+#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
+#define SPI_SLV_RDSTA_CMD_VALUE_S 16
+#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
+#define SPI_SLV_WRBUF_CMD_VALUE_S 8
+#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
+#define SPI_SLV_RDBUF_CMD_VALUE_S 0
+
+#define SPI_W0(i) (REG_SPI_BASE(i) +0x40)
+#define SPI_W1(i) (REG_SPI_BASE(i) +0x44)
+#define SPI_W2(i) (REG_SPI_BASE(i) +0x48)
+#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C)
+#define SPI_W4(i) (REG_SPI_BASE(i) +0x50)
+#define SPI_W5(i) (REG_SPI_BASE(i) +0x54)
+#define SPI_W6(i) (REG_SPI_BASE(i) +0x58)
+#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C)
+#define SPI_W8(i) (REG_SPI_BASE(i) +0x60)
+#define SPI_W9(i) (REG_SPI_BASE(i) +0x64)
+#define SPI_W10(i) (REG_SPI_BASE(i) +0x68)
+#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C)
+#define SPI_W12(i) (REG_SPI_BASE(i) +0x70)
+#define SPI_W13(i) (REG_SPI_BASE(i) +0x74)
+#define SPI_W14(i) (REG_SPI_BASE(i) +0x78)
+#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C)
+
+#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
+#define SPI_INT_HOLD_ENA 0x00000003
+#define SPI_INT_HOLD_ENA_S 0
+#endif // SPI_REGISTER_H_INCLUDED
diff --git a/lib/ArduinoHexParse/README.md b/lib/ArduinoHexParse/README.md
new file mode 100644
index 000000000..c5c6a6751
--- /dev/null
+++ b/lib/ArduinoHexParse/README.md
@@ -0,0 +1,3 @@
+# ArduinoHexParse
+
+Parse hex files created by Arduino for Uno/Mini/Nano
diff --git a/lib/ArduinoHexParse/keywords.txt b/lib/ArduinoHexParse/keywords.txt
new file mode 100644
index 000000000..c60688578
--- /dev/null
+++ b/lib/ArduinoHexParse/keywords.txt
@@ -0,0 +1,25 @@
+#######################################
+# Syntax Coloring Map for ArduinoHexParse
+# (esp8266)
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+ArduinoHexParse KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+ArduinoHexParse KEYWORD2
+ParseLine KEYWORD2
+GetFlashPage KEYWORD2
+GetLoadAddress KEYWORD2
+IsFlashPageReady KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
diff --git a/lib/ArduinoHexParse/library.json b/lib/ArduinoHexParse/library.json
new file mode 100644
index 000000000..896b53f6d
--- /dev/null
+++ b/lib/ArduinoHexParse/library.json
@@ -0,0 +1,12 @@
+{
+ "name": "ArduinoHexParse",
+ "version": "0.0.1",
+ "description": "Parse hex files created by Arduino for Uno/Mini/Nano",
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/arendst/Sonoff-Tasmota/lib/ArduinoHexParse"
+ },
+ "frameworks": "arduino",
+ "platforms": "espressif8266"
+}
diff --git a/lib/ArduinoHexParse/library.properties b/lib/ArduinoHexParse/library.properties
new file mode 100644
index 000000000..034c22e64
--- /dev/null
+++ b/lib/ArduinoHexParse/library.properties
@@ -0,0 +1,9 @@
+name=ArduinoHexParse
+version=0.0.1
+author=Andre Thomas
+maintainer=Andre Thomas
+sentence=Parse hex files created by Arduino for Uno/Mini/Nano
+paragraph=
+category=Signal Input/Output
+url=
+architectures=esp8266
diff --git a/lib/ArduinoHexParse/src/ArduinoHexParse.cpp b/lib/ArduinoHexParse/src/ArduinoHexParse.cpp
new file mode 100644
index 000000000..d4125f2f5
--- /dev/null
+++ b/lib/ArduinoHexParse/src/ArduinoHexParse.cpp
@@ -0,0 +1,134 @@
+/*
+ Copyright (C) 2019 Andre Thomas and Theo Arends
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include "ArduinoHexParse.h"
+
+ArduinoHexParse::ArduinoHexParse(void)
+{
+ loadAddress[0] = 0;
+ loadAddress[1] = 0;
+}
+
+void ArduinoHexParse::ParseLine(byte* hexline)
+{
+ recordType = GetRecordType(hexline);
+ if (0 == recordType) {
+ address = GetAddress(hexline);
+ len = GetLength(hexline);
+ GetData(hexline, len);
+ if (128 == PageMemIdx) {
+ if (!firstRun) {
+ loadAddress[1] += 0x40;
+ if (0 == loadAddress[1]) {
+ loadAddress[0] += 1;
+ }
+ }
+ firstRun = false;
+ FlashPageReady = true;
+ PageMemIdx = 0;
+ }
+ nextAddress = address + len;
+ }
+ if (1 == recordType) {
+ EndOfFile();
+ FlashPageReady = true;
+ }
+}
+
+bool ArduinoHexParse::IsFlashPageReady(void)
+{
+ return FlashPageReady;
+}
+
+byte* ArduinoHexParse::GetFlashPage(void)
+{
+ FlashPageReady = false;
+ return FlashPage;
+}
+
+byte* ArduinoHexParse::GetLoadAddress(void)
+{
+ return loadAddress;
+}
+
+void ArduinoHexParse::GetLoadAddress(byte* hexline)
+{
+ char buff[3];
+ buff[2] = '\0';
+ buff[0] = hexline[3];
+ buff[1] = hexline[4];
+ loadAddress[0] = strtol(buff, 0, 16);
+ buff[0] = hexline[5];
+ buff[1] = hexline[6];
+ loadAddress[1] = strtol(buff, 0, 16);
+}
+
+byte* ArduinoHexParse::GetData(byte* hexline, uint32_t len)
+{
+ uint32_t start = 9;
+ uint32_t end = (len * 2) + start;
+ char buff[3];
+ buff[2] = '\0';
+ for (uint32_t x = start; x < end; x = x+2) {
+ buff[0] = hexline[x];
+ buff[1] = hexline[x+1];
+ FlashPage[PageMemIdx] = strtol(buff, 0, 16);
+ PageMemIdx++;
+ }
+}
+
+void ArduinoHexParse::EndOfFile(void)
+{
+ loadAddress[1] += 0x40;
+ if (0 == loadAddress[1]) {
+ loadAddress[0] += 1;
+ }
+ while (128 > PageMemIdx) { // Fill the remaing space in the memory page with 0xFF
+ FlashPage[PageMemIdx] = 0xFF;
+ PageMemIdx++;
+ }
+}
+
+uint32_t ArduinoHexParse::GetAddress(byte* hexline)
+{
+ char buff[5];
+ buff[0] = hexline[3];
+ buff[1] = hexline[4];
+ buff[2] = hexline[5];
+ buff[3] = hexline[6];
+ buff[4] = '\0';
+ return strtol(buff, 0, 16);
+}
+
+uint16_t ArduinoHexParse::GetLength(byte* hexline)
+{
+ char buff[3];
+ buff[0] = hexline[1];
+ buff[1] = hexline[2];
+ buff[2] = '\0';
+ return strtol(buff, 0, 16);
+}
+
+uint16_t ArduinoHexParse::GetRecordType(byte* hexline)
+{
+ char buff[3];
+ buff[0] = hexline[7];
+ buff[1] = hexline[8];
+ buff[2] = '\0';
+ return strtol(buff, 0, 16);
+}
diff --git a/lib/ArduinoHexParse/src/ArduinoHexParse.h b/lib/ArduinoHexParse/src/ArduinoHexParse.h
new file mode 100644
index 000000000..7b941eea1
--- /dev/null
+++ b/lib/ArduinoHexParse/src/ArduinoHexParse.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2019 Andre Thomas and Theo Arends
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef __ARDUINOHEXPARSE_H__
+
+#include
+
+class ArduinoHexParse {
+ public:
+ ArduinoHexParse(void);
+ void ParseLine(byte* data);
+ byte* GetFlashPage(void);
+ byte* GetLoadAddress(void);
+ bool IsFlashPageReady(void);
+ private:
+ uint32_t address = 0;
+ uint32_t len = 0;
+ uint32_t nextAddress = 0;
+ uint32_t PageMemIdx = 0;
+ uint32_t recordType = 0;
+ byte FlashPage[128];
+ byte loadAddress[2];
+ bool FlashPageReady = false;
+ bool firstRun = true;
+ uint32_t GetAddress(byte* hexline);
+ uint16_t GetLength(byte* hexline);
+ uint16_t GetRecordType(byte* hexline);
+ byte* GetData(byte* hexline, uint32_t len);
+ void GetLoadAddress(byte* hexline);
+ void EndOfFile(void);
+};
+
+#endif // __ARDUINOHEXPARSE_H__
\ No newline at end of file
diff --git a/lib/FT6236-gemu-1.0/FT6236.cpp b/lib/FT6236-gemu-1.0/FT6236.cpp
new file mode 100644
index 000000000..6397190fb
--- /dev/null
+++ b/lib/FT6236-gemu-1.0/FT6236.cpp
@@ -0,0 +1,159 @@
+#include
+#include
+
+/*
+ * This is a static library so we need to make sure we process stuff as quick as possible
+ * as we do not want it to interfere with the RTOS by delaying routines unnecessarily.
+ * So, no delay()'s etc and opto the code as much as possible.
+ * ^^^ Need to be on TODO list to go through and make sure everything is as opto as
+ * possible
+ */
+
+uint8_t FT6236buf[FT6236_BUFFER_SIZE];
+uint8_t FT6236_i2c_addr = 0x38;
+uint8_t lenLibVersion = 0;
+uint8_t firmwareId = 0;
+
+struct tbuttonregister {
+ uint16_t BUTTONID;
+ uint16_t xmin;
+ uint16_t xmax;
+ uint16_t ymin;
+ uint16_t ymax;
+} buttonregister[FT6236_MAX_BUTTONS]; // we're limiting to 16 buttons for now - can reduce or increase later as needed.
+
+uint8_t buttoncount = 0;
+
+void FT6236flushbuttonregister(void) {
+ uint16_t bid;
+ for (bid=0;bid 0) {
+ uint16_t x = tl[0].x;
+ uint16_t y = tl[0].y;
+ for (bid=0;bid= buttonregister[bid].xmin) {
+ if (x <= buttonregister[bid].xmax) {
+ if (y >= buttonregister[bid].ymin) {
+ if (y <= buttonregister[bid].ymax) {
+ return buttonregister[bid].BUTTONID;
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void FT6236begin(uint8_t i2c_addr) {
+ FT6236_i2c_addr=i2c_addr;
+ Wire.begin();
+ FT6236writeTouchRegister(0,FT6236_MODE_NORMAL);
+ lenLibVersion = FT6236readTouchAddr(0x0a1, FT6236buf, 2 );
+ firmwareId = FT6236readTouchRegister( 0xa6 );
+}
+
+void FT6236writeTouchRegister(uint8_t reg, uint8_t val)
+{
+ Wire.beginTransmission(FT6236_i2c_addr);
+ Wire.write(reg); // register 0
+ Wire.write(val); // value
+ Wire.endTransmission();
+}
+
+uint8_t FT6236readTouchRegister(uint8_t reg)
+{
+ Wire.beginTransmission(FT6236_i2c_addr);
+ Wire.write(reg); // register 0
+ uint8_t retVal = Wire.endTransmission();
+ uint8_t returned = Wire.requestFrom(FT6236_i2c_addr,uint8_t(1)); // request 6 uint8_ts from slave device #2
+ if (Wire.available())
+ {
+ retVal = Wire.read();
+ }
+ return retVal;
+}
+
+uint8_t FT6236readTouchAddr( uint8_t regAddr, uint8_t * pBuf, uint8_t len )
+{
+ Wire.beginTransmission(FT6236_i2c_addr);
+ Wire.write( regAddr ); // register 0
+ uint8_t retVal = Wire.endTransmission();
+ uint8_t returned = Wire.requestFrom(FT6236_i2c_addr, len); // request 1 bytes from slave device #2
+ uint8_t i;
+ for (i = 0; (i < len) && Wire.available(); i++) {
+ pBuf[i] = Wire.read();
+ }
+ return i;
+}
+
+uint8_t FT6236readTouchLocation( TouchLocation * pLoc, uint8_t num )
+{
+ uint8_t retVal = 0;
+ uint8_t i;
+ uint8_t k;
+ do
+ {
+ if (!pLoc) break; // must have a buffer
+ if (!num) break; // must be able to take at least one
+ uint8_t status = FT6236readTouchRegister(2);
+ static uint8_t tbuf[40];
+ if ((status & 0x0f) == 0) break; // no points detected
+ uint8_t hitPoints = status & 0x0f;
+ FT6236readTouchAddr( 0x03, tbuf, hitPoints*6);
+ for (k=0,i = 0; (i < hitPoints*6)&&(k < num); k++, i += 6) {
+ pLoc[k].x = (tbuf[i+0] & 0x0f) << 8 | tbuf[i+1];
+ pLoc[k].y = (tbuf[i+2] & 0x0f) << 8 | tbuf[i+3];
+ }
+ retVal = k;
+ } while (0);
+ return retVal;
+}
+
+uint32_t FT6236dist(const TouchLocation & loc)
+{
+ uint32_t retVal = 0;
+ uint32_t x = loc.x;
+ uint32_t y = loc.y;
+ retVal = x*x + y*y;
+ return retVal;
+}
+
+
+/*
+uint32_t FT6236dist(const TouchLocation & loc1, const TouchLocation & loc2)
+{
+ uint32_t retVal = 0;
+ uint32_t x = loc1.x - loc2.x;
+ uint32_t y = loc1.y - loc2.y;
+ retVal = sqrt(x*x + y*y);
+ return retVal;
+}
+*/
+
+bool FT6236sameLoc( const TouchLocation & loc, const TouchLocation & loc2 )
+{
+ return FT6236dist(loc,loc2) < 50;
+}
diff --git a/lib/FT6236-gemu-1.0/FT6236.h b/lib/FT6236-gemu-1.0/FT6236.h
new file mode 100644
index 000000000..601d9c67e
--- /dev/null
+++ b/lib/FT6236-gemu-1.0/FT6236.h
@@ -0,0 +1,28 @@
+#ifndef FT6236
+#define FT6236
+
+#define FT6236_MODE_NORMAL 0x00
+#define FT6236_MODE_TEST 0x04
+#define FT6236_MODE_SYSTEM 0x01
+
+#define FT6236_BUFFER_SIZE 0x1E // 30 bytes buffer
+#define FT6236_MAX_BUTTONS 1 // 50 buttons should be enough for just about any page
+
+struct TouchLocation {
+ uint16_t y; // we swop x and y in position because we're using the screen in portrait mode
+ uint16_t x;
+};
+
+void FT6236flushbuttonregister(void);
+void FT6236registerbutton(uint16_t buttonid,uint16_t xmin,uint16_t ymin,uint16_t xmax, uint16_t ymax);
+uint16_t FT6236GetButtonMask(void);
+void FT6236begin(uint8_t i2c_addr);
+uint8_t FT6236readTouchRegister( uint8_t reg );
+uint8_t FT6236readTouchLocation( TouchLocation * pLoc, uint8_t num );
+uint8_t FT6236readTouchAddr( uint8_t regAddr, uint8_t * pBuf, uint8_t len );
+void FT6236writeTouchRegister( uint8_t reg, uint8_t val);
+uint32_t FT6236dist(const TouchLocation & loc);
+uint32_t FT6236dist(const TouchLocation & loc1, const TouchLocation & loc2);
+bool FT6236sameLoc( const TouchLocation & loc, const TouchLocation & loc2 );
+
+#endif
diff --git a/lib/IRremoteESP8266-2.6.0/.travis.yml b/lib/IRremoteESP8266-2.6.0/.travis.yml
deleted file mode 100644
index ae2d9fe3c..000000000
--- a/lib/IRremoteESP8266-2.6.0/.travis.yml
+++ /dev/null
@@ -1,66 +0,0 @@
-language: c
-env:
- - BD=esp8266:esp8266:nodemcuv2:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled
- - BD=esp8266:esp8266:d1_mini:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled
-before_install:
- - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
- - sleep 3
- - export DISPLAY=:1.0
- - wget http://downloads.arduino.cc/arduino-1.8.8-linux64.tar.xz
- - tar xf arduino-1.8.8-linux64.tar.xz
- - sudo mv arduino-1.8.8 /usr/local/share/arduino
- - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
- - wget https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py
-install:
- - ln -s $PWD /usr/local/share/arduino/libraries/
- - git clone https://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WiFiManager
- - git clone https://github.com/knolleary/pubsubclient.git /usr/local/share/arduino/libraries/PubSubClient
- - git clone https://github.com/bblanchon/ArduinoJson.git --branch 5.x /usr/local/share/arduino/libraries/ArduinoJson
- - arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs
- - arduino --install-boards esp8266:esp8266
- - arduino --board $BD --save-prefs
- - arduino --pref "compiler.warning_level=all" --save-prefs
- - sudo apt-get install jq
- - sudo pip install pylint
-script:
- # Check that everything compiles.
- - arduino --verify --board $BD $PWD/examples/IRrecvDemo/IRrecvDemo.ino
- - arduino --verify --board $BD $PWD/examples/IRGCSendDemo/IRGCSendDemo.ino
- - arduino --verify --board $BD $PWD/examples/IRGCTCPServer/IRGCTCPServer.ino
- - arduino --verify --board $BD $PWD/examples/IRServer/IRServer.ino
- - arduino --verify --board $BD $PWD/examples/IRrecvDumpV2/IRrecvDumpV2.ino
- - arduino --verify --board $BD $PWD/examples/IRsendDemo/IRsendDemo.ino
- - arduino --verify --board $BD $PWD/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino
- - arduino --verify --board $BD $PWD/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino
- - arduino --verify --board $BD $PWD/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino
- - arduino --verify --board $BD $PWD/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino
- - arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino
- - arduino --verify --board $BD $PWD/examples/IRsendProntoDemo/IRsendProntoDemo.ino
- - arduino --verify --board $BD $PWD/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino
- - arduino --verify --board $BD $PWD/examples/LGACSend/LGACSend.ino
- - arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.ino
- - arduino --verify --board $BD $PWD/examples/IRMQTTServer/IRMQTTServer.ino
- - arduino --verify --board $BD $PWD/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino
- - arduino --verify --board $BD $PWD/examples/ControlSamsungAC/ControlSamsungAC.ino
- - arduino --verify --board $BD $PWD/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino
- - arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino
-
- # Also check the tools programs compile.
- - (cd tools; make all)
- # Check for lint issues.
- - shopt -s nullglob
- - python cpplint.py --extensions=c,cc,cpp,ino --headers=h,hpp {src,test,tools}/*.{h,c,cc,cpp,hpp,ino} examples/*/*.{h,c,cc,cpp,hpp,ino}
- - pylint {src,test,tools}/*.py
- - shopt -u nullglob
- # Build and run the unit tests.
- - (cd test; make run)
- - (cd tools; make run_tests)
- # Check the version numbers match.
- - LIB_VERSION=$(egrep "^#define\s+_IRREMOTEESP8266_VERSION_\s+" src/IRremoteESP8266.h | cut -d\" -f2)
- - test ${LIB_VERSION} == "$(jq -r .version library.json)"
- - grep -q "^version=${LIB_VERSION}$" library.properties
-
-notifications:
- email:
- on_success: change
- on_failure: change
diff --git a/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/platformio.ini
deleted file mode 100644
index 243b36a99..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/platformio.ini
+++ /dev/null
@@ -1,42 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags = -DMQTT_MAX_PACKET_SIZE=768
-lib_ldf_mode = chain+
-lib_deps_builtin =
-lib_deps_external =
- PubSubClient
- WifiManager@0.14
- ArduinoJson
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
-
-[env:d1_mini]
-platform=espressif8266
-framework=arduino
-board=d1_mini
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
-
-[env:d1_mini_no_mqtt]
-platform=espressif8266
-framework=arduino
-board=d1_mini
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags} -DMQTT_ENABLE=false
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRServer/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/IRServer/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/LGACSend/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/LGACSend/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/LGACSend/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/platformio.ini
deleted file mode 100644
index ec84f22f3..000000000
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/platformio.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[platformio]
-lib_extra_dirs = ../../
-src_dir=.
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/platformio.ini b/lib/IRremoteESP8266-2.6.0/platformio.ini
deleted file mode 100644
index b6020c165..000000000
--- a/lib/IRremoteESP8266-2.6.0/platformio.ini
+++ /dev/null
@@ -1,29 +0,0 @@
-[platformio]
-lib_extra_dirs = .
-src_dir = examples/IRrecvDumpV2
-
-[common]
-build_flags =
-lib_deps_builtin =
-lib_deps_external =
-lib_ldf_mode = chain+
-
-[env:nodemcuv2]
-platform = espressif8266
-framework = arduino
-board = nodemcuv2
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
-
-[env:d1_mini]
-platform = espressif8266
-framework = arduino
-board = d1_mini
-lib_ldf_mode = ${common.lib_ldf_mode}
-build_flags = ${common.build_flags}
-lib_deps =
- ${common.lib_deps_builtin}
- ${common.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRac.cpp b/lib/IRremoteESP8266-2.6.0/src/IRac.cpp
deleted file mode 100644
index 782c147c2..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/IRac.cpp
+++ /dev/null
@@ -1,1125 +0,0 @@
-// Copyright 2019 David Conran
-
-// Provide a universal/standard interface for sending A/C nessages.
-// It does not provide complete and maximum granular control but tries
-// to off most common functionallity across all supported devices.
-
-#include "IRac.h"
-#ifndef UNIT_TEST
-#include
-#endif
-
-#include
-#ifndef ARDUINO
-#include
-#endif
-#include "IRsend.h"
-#include "IRremoteESP8266.h"
-#include "ir_Argo.h"
-#include "ir_Coolix.h"
-#include "ir_Daikin.h"
-#include "ir_Fujitsu.h"
-#include "ir_Haier.h"
-#include "ir_Hitachi.h"
-#include "ir_Kelvinator.h"
-#include "ir_Midea.h"
-#include "ir_Mitsubishi.h"
-#include "ir_MitsubishiHeavy.h"
-#include "ir_Panasonic.h"
-#include "ir_Samsung.h"
-#include "ir_Tcl.h"
-#include "ir_Teco.h"
-#include "ir_Toshiba.h"
-#include "ir_Trotec.h"
-#include "ir_Vestel.h"
-#include "ir_Whirlpool.h"
-
-IRac::IRac(uint8_t pin) { _pin = pin; }
-
-// Is the given protocol supported by the IRac class?
-bool IRac::isProtocolSupported(const decode_type_t protocol) {
- switch (protocol) {
-#if SEND_ARGO
- case decode_type_t::ARGO:
-#endif
-#if SEND_COOLIX
- case decode_type_t::COOLIX:
-#endif
-#if SEND_DAIKIN
- case decode_type_t::DAIKIN:
-#endif
-#if SEND_DAIKIN2
- case decode_type_t::DAIKIN2:
-#endif
-#if SEND_DAIKIN216
- case decode_type_t::DAIKIN216:
-#endif
-#if SEND_FUJITSU_AC
- case decode_type_t::FUJITSU_AC:
-#endif
-#if SEND_GREE
- case decode_type_t::GREE:
-#endif
-#if SEND_HAIER_AC
- case decode_type_t::HAIER_AC:
-#endif
-#if SEND_HAIER_AC_YRW02
- case decode_type_t::HAIER_AC_YRW02:
-#endif
-#if SEND_HITACHI_AC
- case decode_type_t::HITACHI_AC:
-#endif
-#if SEND_KELVINATOR
- case decode_type_t::KELVINATOR:
-#endif
-#if SEND_MIDEA
- case decode_type_t::MIDEA:
-#endif
-#if SEND_MITSUBISHI_AC
- case decode_type_t::MITSUBISHI_AC:
-#endif
-#if SEND_MITSUBISHIHEAVY
- case decode_type_t::MITSUBISHI_HEAVY_88:
- case decode_type_t::MITSUBISHI_HEAVY_152:
-#endif
-#if SEND_PANASONIC_AC
- case decode_type_t::PANASONIC_AC:
-#endif
-#if SEND_SAMSUNG_AC
- case decode_type_t::SAMSUNG_AC:
-#endif
-#if SEND_TCL112AC
- case decode_type_t::TCL112AC:
-#endif
-#if SEND_TECO
- case decode_type_t::TECO:
-#endif
-#if SEND_TOSHIBA_AC
- case decode_type_t::TOSHIBA_AC:
-#endif
-#if SEND_TROTEC
- case decode_type_t::TROTEC:
-#endif
-#if SEND_VESTEL_AC
- case decode_type_t::VESTEL_AC:
-#endif
-#if SEND_WHIRLPOOL_AC
- case decode_type_t::WHIRLPOOL_AC:
-#endif
- return true;
- default:
- return false;
- }
-}
-
-#if SEND_ARGO
-void IRac::argo(IRArgoAC *ac,
- const bool on, const stdAc::opmode_t mode, const float degrees,
- const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
- const bool turbo, const int16_t sleep) {
- ac->setPower(on);
- switch (mode) {
- case stdAc::opmode_t::kCool:
- ac->setCoolMode(kArgoCoolOn);
- break;
- case stdAc::opmode_t::kHeat:
- ac->setHeatMode(kArgoHeatOn);
- break;
- case stdAc::opmode_t::kDry:
- ac->setCoolMode(kArgoCoolHum);
- break;
- default: // No idea how to set Fan mode.
- ac->setCoolMode(kArgoCoolAuto);
- }
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setFlap(ac->convertSwingV(swingv));
- // No Quiet setting available.
- // No Light setting available.
- // No Filter setting available.
- ac->setMax(turbo);
- // No Economy setting available.
- // No Clean setting available.
- // No Beep setting available.
- ac->setNight(sleep >= 0); // Convert to a boolean.
- ac->send();
-}
-#endif // SEND_ARGO
-
-#if SEND_COOLIX
-void IRac::coolix(IRCoolixAC *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool turbo, const bool light, const bool clean,
- const int16_t sleep) {
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- // No Filter setting available.
- // No Beep setting available.
- // No Clock setting available.
- // No Econo setting available.
- // No Quiet setting available.
- if (swingv != stdAc::swingv_t::kOff || swingh != stdAc::swingh_t::kOff) {
- // Swing has a special command that needs to be sent independently.
- ac->setSwing();
- ac->send();
- }
- if (turbo) {
- // Turbo has a special command that needs to be sent independently.
- ac->setTurbo();
- ac->send();
- }
- if (sleep > 0) {
- // Sleep has a special command that needs to be sent independently.
- ac->setSleep();
- ac->send();
- }
- if (light) {
- // Light has a special command that needs to be sent independently.
- ac->setLed();
- ac->send();
- }
- if (clean) {
- // Clean has a special command that needs to be sent independently.
- ac->setClean();
- ac->send();
- }
- // Power gets done last, as off has a special command.
- ac->setPower(on);
- ac->send();
-}
-#endif // SEND_COOLIX
-
-#if SEND_DAIKIN
-void IRac::daikin(IRDaikinESP *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool quiet, const bool turbo, const bool econo,
- const bool clean) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwingVertical((int8_t)swingv >= 0);
- ac->setSwingHorizontal((int8_t)swingh >= 0);
- ac->setQuiet(quiet);
- // No Light setting available.
- // No Filter setting available.
- ac->setPowerful(turbo);
- ac->setEcono(econo);
- ac->setMold(clean);
- // No Beep setting available.
- // No Sleep setting available.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_DAIKIN
-
-#if SEND_DAIKIN2
-void IRac::daikin2(IRDaikin2 *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool quiet, const bool turbo, const bool light,
- const bool econo, const bool filter, const bool clean,
- const bool beep, const int16_t sleep, const int16_t clock) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwingVertical(ac->convertSwingV(swingv));
- ac->setSwingHorizontal((int8_t)swingh >= 0);
- ac->setQuiet(quiet);
- ac->setLight(light);
- ac->setPowerful(turbo);
- ac->setEcono(econo);
- ac->setPurify(filter);
- ac->setMold(clean);
- ac->setBeep(beep);
- if (sleep > 0) ac->enableSleepTimer(sleep);
- if (clock >= 0) ac->setCurrentTime(clock);
- ac->send();
-}
-#endif // SEND_DAIKIN2
-
-#if SEND_DAIKIN216
-void IRac::daikin216(IRDaikin216 *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool quiet) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwingVertical((int8_t)swingv >= 0);
- ac->setSwingHorizontal((int8_t)swingh >= 0);
- ac->setQuiet(quiet);
- ac->send();
-}
-#endif // SEND_DAIKIN216
-
-#if SEND_FUJITSU_AC
-void IRac::fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool quiet) {
- ac->setModel(model);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFanSpeed(ac->convertFan(fan));
- uint8_t swing = kFujitsuAcSwingOff;
- if (swingv > stdAc::swingv_t::kOff) swing |= kFujitsuAcSwingVert;
- if (swingh > stdAc::swingh_t::kOff) swing |= kFujitsuAcSwingHoriz;
- ac->setSwing(swing);
- if (quiet) ac->setFanSpeed(kFujitsuAcFanQuiet);
- // No Turbo setting available.
- // No Light setting available.
- // No Econo setting available.
- // No Filter setting available.
- // No Clean setting available.
- // No Beep setting available.
- // No Sleep setting available.
- // No Clock setting available.
- if (!on) ac->off();
- ac->send();
-}
-#endif // SEND_FUJITSU_AC
-
-#if SEND_GREE
-void IRac::gree(IRGreeAC *ac,
- const bool on, const stdAc::opmode_t mode, const float degrees,
- const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
- const bool turbo, const bool light, const bool clean,
- const int16_t sleep) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwingVertical(swingv == stdAc::swingv_t::kAuto, // Set auto flag.
- ac->convertSwingV(swingv));
- ac->setLight(light);
- ac->setTurbo(turbo);
- ac->setXFan(clean);
- ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
- // No Horizontal Swing setting available.
- // No Filter setting available.
- // No Beep setting available.
- // No Quiet setting available.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_GREE
-
-#if SEND_HAIER_AC
-void IRac::haier(IRHaierAC *ac,
- const bool on, const stdAc::opmode_t mode, const float degrees,
- const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
- const bool filter, const int16_t sleep, const int16_t clock) {
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwing(ac->convertSwingV(swingv));
- // No Horizontal Swing setting available.
- // No Quiet setting available.
- // No Turbo setting available.
- // No Light setting available.
- ac->setHealth(filter);
- // No Clean setting available.
- // No Beep setting available.
- ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
- if (clock >=0) ac->setCurrTime(clock);
- if (on)
- ac->setCommand(kHaierAcCmdOn);
- else
- ac->setCommand(kHaierAcCmdOff);
- ac->send();
-}
-#endif // SEND_HAIER_AC
-
-#if SEND_HAIER_AC_YRW02
-void IRac::haierYrwo2(IRHaierACYRW02 *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const bool turbo,
- const bool filter, const int16_t sleep) {
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwing(ac->convertSwingV(swingv));
- // No Horizontal Swing setting available.
- // No Quiet setting available.
- ac->setTurbo(turbo);
- // No Light setting available.
- ac->setHealth(filter);
- // No Clean setting available.
- // No Beep setting available.
- ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
- ac->setPower(on);
- ac->send();
-}
-#endif // SEND_HAIER_AC_YRW02
-
-#if SEND_HITACHI_AC
-void IRac::hitachi(IRHitachiAc *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const stdAc::swingh_t swingh) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwingVertical(swingv != stdAc::swingv_t::kOff);
- ac->setSwingHorizontal(swingh != stdAc::swingh_t::kOff);
- // No Quiet setting available.
- // No Turbo setting available.
- // No Light setting available.
- // No Filter setting available.
- // No Clean setting available.
- // No Beep setting available.
- // No Sleep setting available.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_HITACHI_AC
-
-#if SEND_KELVINATOR
-void IRac::kelvinator(IRKelvinatorAC *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv,
- const stdAc::swingh_t swingh,
- const bool quiet, const bool turbo, const bool light,
- const bool filter, const bool clean) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan((uint8_t)fan); // No conversion needed.
- ac->setSwingVertical((int8_t)swingv >= 0);
- ac->setSwingHorizontal((int8_t)swingh >= 0);
- ac->setQuiet(quiet);
- ac->setTurbo(turbo);
- ac->setLight(light);
- ac->setIonFilter(filter);
- ac->setXFan(clean);
- // No Beep setting available.
- // No Sleep setting available.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_KELVINATOR
-
-#if SEND_MIDEA
-void IRac::midea(IRMideaAC *ac,
- const bool on, const stdAc::opmode_t mode, const float degrees,
- const stdAc::fanspeed_t fan, const int16_t sleep) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees, true); // true means use Celsius.
- ac->setFan(ac->convertFan(fan));
- // No Vertical swing setting available.
- // No Horizontal swing setting available.
- // No Quiet setting available.
- // No Turbo setting available.
- // No Light setting available.
- // No Filter setting available.
- // No Clean setting available.
- // No Beep setting available.
- ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_MIDEA
-
-#if SEND_MITSUBISHI_AC
-void IRac::mitsubishi(IRMitsubishiAC *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees,
- const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
- const bool quiet, const int16_t clock) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setVane(ac->convertSwingV(swingv));
- // No Horizontal swing setting available.
- if (quiet) ac->setFan(kMitsubishiAcFanSilent);
- // No Turbo setting available.
- // No Light setting available.
- // No Filter setting available.
- // No Clean setting available.
- // No Beep setting available.
- // No Sleep setting available.
- if (clock >= 0) ac->setClock(clock / 10); // Clock is in 10 min increments.
- ac->send();
-}
-#endif // SEND_MITSUBISHI_AC
-
-#if SEND_MITSUBISHIHEAVY
-void IRac::mitsubishiHeavy88(IRMitsubishiHeavy88Ac *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees,
- const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv,
- const stdAc::swingh_t swingh,
- const bool turbo, const bool econo,
- const bool clean) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwingVertical(ac->convertSwingV(swingv));
- ac->setSwingHorizontal(ac->convertSwingH(swingh));
- // No Quiet setting available.
- ac->setTurbo(turbo);
- // No Light setting available.
- ac->setEcono(econo);
- // No Filter setting available.
- ac->setClean(clean);
- // No Beep setting available.
- // No Sleep setting available.
- // No Clock setting available.
- ac->send();
-}
-
-void IRac::mitsubishiHeavy152(IRMitsubishiHeavy152Ac *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees,
- const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv,
- const stdAc::swingh_t swingh,
- const bool quiet, const bool turbo,
- const bool econo, const bool filter,
- const bool clean, const int16_t sleep) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwingVertical(ac->convertSwingV(swingv));
- ac->setSwingHorizontal(ac->convertSwingH(swingh));
- ac->setSilent(quiet);
- ac->setTurbo(turbo);
- // No Light setting available.
- ac->setEcono(econo);
- ac->setClean(clean);
- ac->setFilter(filter);
- // No Beep setting available.
- ac->setNight(sleep >= 0); // Sleep is either on/off, so convert to boolean.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_MITSUBISHIHEAVY
-
-#if SEND_PANASONIC_AC
-void IRac::panasonic(IRPanasonicAc *ac, const panasonic_ac_remote_model_t model,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool quiet, const bool turbo, const int16_t clock) {
- ac->setModel(model);
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwingVertical(ac->convertSwingV(swingv));
- ac->setSwingHorizontal(ac->convertSwingH(swingh));
- ac->setQuiet(quiet);
- ac->setPowerful(turbo);
- // No Light setting available.
- // No Econo setting available.
- // No Filter setting available.
- // No Clean setting available.
- // No Beep setting available.
- // No Sleep setting available.
- if (clock >= 0) ac->setClock(clock);
- ac->send();
-}
-#endif // SEND_PANASONIC_AC
-
-#if SEND_SAMSUNG_AC
-void IRac::samsung(IRSamsungAc *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees,
- const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
- const bool quiet, const bool turbo, const bool clean,
- const bool beep, const bool sendOnOffHack) {
- if (sendOnOffHack) {
- // Use a hack to for the unit on or off.
- // See: https://github.com/markszabo/IRremoteESP8266/issues/604#issuecomment-475020036
- if (on)
- ac->sendOn();
- else
- ac->sendOff();
- }
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwing(swingv != stdAc::swingv_t::kOff);
- // No Horizontal swing setting available.
- ac->setQuiet(quiet);
- if (turbo) ac->setFan(kSamsungAcFanTurbo);
- // No Light setting available.
- // No Econo setting available.
- // No Filter setting available.
- ac->setClean(clean);
- ac->setBeep(beep);
- // No Sleep setting available.
- // No Clock setting available.
- // Do setMode() again as it can affect fan speed.
- ac->setMode(ac->convertMode(mode));
- ac->send();
-}
-#endif // SEND_SAMSUNG_AC
-
-#if SEND_TCL112AC
-void IRac::tcl112(IRTcl112Ac *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool turbo, const bool light, const bool econo,
- const bool filter) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwingVertical(swingv != stdAc::swingv_t::kOff);
- ac->setSwingHorizontal(swingh != stdAc::swingh_t::kOff);
- // No Quiet setting available.
- ac->setTurbo(turbo);
- ac->setLight(light);
- ac->setEcono(econo);
- ac->setHealth(filter);
- // No Clean setting available.
- // No Beep setting available.
- // No Sleep setting available.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_TCL112AC
-
-#if SEND_TECO
-void IRac::teco(IRTecoAc *ac,
- const bool on, const stdAc::opmode_t mode, const float degrees,
- const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
- const int16_t sleep) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwing(swingv != stdAc::swingv_t::kOff);
- // No Horizontal swing setting available.
- // No Quiet setting available.
- // No Turbo setting available.
- // No Light setting available.
- // No Filter setting available.
- // No Clean setting available.
- // No Beep setting available.
- ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_TECO
-
-#if SEND_TOSHIBA_AC
-void IRac::toshiba(IRToshibaAC *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- // No Vertical swing setting available.
- // No Horizontal swing setting available.
- // No Quiet setting available.
- // No Turbo setting available.
- // No Light setting available.
- // No Filter setting available.
- // No Clean setting available.
- // No Beep setting available.
- // No Sleep setting available.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_TOSHIBA_AC
-
-#if SEND_TROTEC
-void IRac::trotec(IRTrotecESP *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees, const stdAc::fanspeed_t fan,
- const int16_t sleep) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setSpeed(ac->convertFan(fan));
- // No Vertical swing setting available.
- // No Horizontal swing setting available.
- // No Quiet setting available.
- // No Turbo setting available.
- // No Light setting available.
- // No Filter setting available.
- // No Clean setting available.
- // No Beep setting available.
- ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
- // No Clock setting available.
- ac->send();
-}
-#endif // SEND_TROTEC
-
-#if SEND_VESTEL_AC
-void IRac::vestel(IRVestelAc *ac,
- const bool on, const stdAc::opmode_t mode,
- const float degrees,
- const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
- const bool turbo, const bool filter, const int16_t sleep,
- const int16_t clock, const bool sendNormal) {
- ac->setPower(on);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwing(swingv != stdAc::swingv_t::kOff);
- // No Horizontal swing setting available.
- // No Quiet setting available.
- ac->setTurbo(turbo);
- // No Light setting available.
- ac->setIon(filter);
- // No Clean setting available.
- // No Beep setting available.
- ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
- if (sendNormal) ac->send(); // Send the normal message.
- if (clock >= 0) {
- ac->setTime(clock);
- ac->send(); // Setting the clock requires a different "timer" message.
- }
-}
-#endif // SEND_VESTEL_AC
-
-#if SEND_WHIRLPOOL_AC
-void IRac::whirlpool(IRWhirlpoolAc *ac, const whirlpool_ac_remote_model_t model,
- const bool on, const stdAc::opmode_t mode,
- const float degrees,
- const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
- const bool turbo, const bool light,
- const int16_t sleep, const int16_t clock) {
- ac->setModel(model);
- ac->setMode(ac->convertMode(mode));
- ac->setTemp(degrees);
- ac->setFan(ac->convertFan(fan));
- ac->setSwing(swingv != stdAc::swingv_t::kOff);
- // No Horizontal swing setting available.
- // No Quiet setting available.
- ac->setSuper(turbo);
- ac->setLight(light);
- // No Filter setting available
- // No Clean setting available.
- // No Beep setting available.
- ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
- if (clock >= 0) ac->setClock(clock);
- ac->setPowerToggle(on);
- ac->send();
-}
-#endif // SEND_WHIRLPOOL_AC
-
-// Send A/C message for a given device using common A/C settings.
-// Args:
-// vendor: The type of A/C protocol to use.
-// model: The specific model of A/C if supported/applicable.
-// on: Should the unit be powered on? (or in some cases, toggled)
-// mode: What operating mode should the unit perform? e.g. Cool, Heat etc.
-// degrees: What temperature should the unit be set to?
-// celsius: Use degreees Celsius, otherwise Fahrenheit.
-// fan: Fan speed.
-// The following args are all "if supported" by the underlying A/C classes.
-// swingv: Control the vertical swing of the vanes.
-// swingh: Control the horizontal swing of the vanes.
-// quiet: Set the unit to quiet (fan) operation mode.
-// turbo: Set the unit to turbo operating mode. e.g. Max fan & cooling etc.
-// econo: Set the unit to economical operating mode.
-// light: Turn on the display/LEDs etc.
-// filter: Turn on any particle/ion/allergy filter etc.
-// clean: Turn on any settings to reduce mold etc. (Not self-clean mode.)
-// beep: Control if the unit beeps upon receiving commands.
-// sleep: Nr. of mins of sleep mode, or use sleep mode. (< 0 means off.)
-// clock: Nr. of mins past midnight to set the clock to. (< 0 means off.)
-// Returns:
-// boolean: True, if accepted/converted/attempted. False, if unsupported.
-bool IRac::sendAc(const decode_type_t vendor, const int16_t model,
- const bool power, const stdAc::opmode_t mode,
- const float degrees, const bool celsius,
- const stdAc::fanspeed_t fan,
- const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool quiet, const bool turbo, const bool econo,
- const bool light, const bool filter, const bool clean,
- const bool beep, const int16_t sleep, const int16_t clock) {
- // Convert the temperature to Celsius.
- float degC;
- bool on = power;
- if (celsius)
- degC = degrees;
- else
- degC = (degrees - 32.0) * (5.0 / 9.0);
- // A hack for Home Assistant, it appears to need/want an Off opmode.
- if (mode == stdAc::opmode_t::kOff) on = false;
- // Per vendor settings & setup.
- switch (vendor) {
-#if SEND_ARGO
- case ARGO:
- {
- IRArgoAC ac(_pin);
- argo(&ac, on, mode, degC, fan, swingv, turbo, sleep);
- break;
- }
-#endif // SEND_DAIKIN
-#if SEND_COOLIX
- case COOLIX:
- {
- IRCoolixAC ac(_pin);
- coolix(&ac, on, mode, degC, fan, swingv, swingh,
- quiet, turbo, econo, clean);
- break;
- }
-#endif // SEND_DAIKIN
-#if SEND_DAIKIN
- case DAIKIN:
- {
- IRDaikinESP ac(_pin);
- daikin(&ac, on, mode, degC, fan, swingv, swingh,
- quiet, turbo, econo, clean);
- break;
- }
-#endif // SEND_DAIKIN
-#if SEND_DAIKIN2
- case DAIKIN2:
- {
- IRDaikin2 ac(_pin);
- daikin2(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo,
- light, econo, filter, clean, beep, sleep, clock);
- break;
- }
-#endif // SEND_DAIKIN216
-#if SEND_DAIKIN216
- case DAIKIN216:
- {
- IRDaikin216 ac(_pin);
- daikin216(&ac, on, mode, degC, fan, swingv, swingh, quiet);
- break;
- }
-#endif // SEND_DAIKIN216
-#if SEND_FUJITSU_AC
- case FUJITSU_AC:
- {
- IRFujitsuAC ac(_pin);
- ac.begin();
- fujitsu(&ac, (fujitsu_ac_remote_model_t)model, on, mode, degC, fan,
- swingv, swingh, quiet);
- break;
- }
-#endif // SEND_FUJITSU_AC
-#if SEND_GREE
- case GREE:
- {
- IRGreeAC ac(_pin);
- ac.begin();
- gree(&ac, on, mode, degC, fan, swingv, light, turbo, clean, sleep);
- break;
- }
-#endif // SEND_GREE
-#if SEND_HAIER_AC
- case HAIER_AC:
- {
- IRHaierAC ac(_pin);
- ac.begin();
- haier(&ac, on, mode, degC, fan, swingv, filter, sleep, clock);
- break;
- }
-#endif // SEND_HAIER_AC
-#if SEND_HAIER_AC_YRW02
- case HAIER_AC_YRW02:
- {
- IRHaierACYRW02 ac(_pin);
- ac.begin();
- haierYrwo2(&ac, on, mode, degC, fan, swingv, turbo, filter, sleep);
- break;
- }
-#endif // SEND_HAIER_AC_YRW02
-#if SEND_HITACHI_AC
- case HITACHI_AC:
- {
- IRHitachiAc ac(_pin);
- ac.begin();
- hitachi(&ac, on, mode, degC, fan, swingv, swingh);
- break;
- }
-#endif // SEND_HITACHI_AC
-#if SEND_KELVINATOR
- case KELVINATOR:
- {
- IRKelvinatorAC ac(_pin);
- ac.begin();
- kelvinator(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo,
- light, filter, clean);
- break;
- }
-#endif // SEND_KELVINATOR
-#if SEND_MIDEA
- case MIDEA:
- {
- IRMideaAC ac(_pin);
- ac.begin();
- midea(&ac, on, mode, degC, fan, sleep);
- break;
- }
-#endif // SEND_MIDEA
-#if SEND_MITSUBISHI_AC
- case MITSUBISHI_AC:
- {
- IRMitsubishiAC ac(_pin);
- ac.begin();
- mitsubishi(&ac, on, mode, degC, fan, swingv, quiet, clock);
- break;
- }
-#endif // SEND_MITSUBISHI_AC
-#if SEND_MITSUBISHIHEAVY
- case MITSUBISHI_HEAVY_88:
- {
- IRMitsubishiHeavy88Ac ac(_pin);
- ac.begin();
- mitsubishiHeavy88(&ac, on, mode, degC, fan, swingv, swingh,
- turbo, econo, clean);
- break;
- }
- case MITSUBISHI_HEAVY_152:
- {
- IRMitsubishiHeavy152Ac ac(_pin);
- ac.begin();
- mitsubishiHeavy152(&ac, on, mode, degC, fan, swingv, swingh,
- quiet, turbo, econo, filter, clean, sleep);
- break;
- }
-#endif // SEND_MITSUBISHIHEAVY
-#if SEND_PANASONIC_AC
- case PANASONIC_AC:
- {
- IRPanasonicAc ac(_pin);
- ac.begin();
- panasonic(&ac, (panasonic_ac_remote_model_t)model, on, mode, degC, fan,
- swingv, swingh, quiet, turbo, clock);
- break;
- }
-#endif // SEND_PANASONIC_AC
-#if SEND_SAMSUNG_AC
- case SAMSUNG_AC:
- {
- IRSamsungAc ac(_pin);
- ac.begin();
- samsung(&ac, on, mode, degC, fan, swingv, quiet, turbo, clean, beep);
- break;
- }
-#endif // SEND_SAMSUNG_AC
-#if SEND_TCL112AC
- case TCL112AC:
- {
- IRTcl112Ac ac(_pin);
- ac.begin();
- tcl112(&ac, on, mode, degC, fan, swingv, swingh, turbo, light, econo,
- filter);
- break;
- }
-#endif // SEND_TCL112AC
-#if SEND_TECO
- case TECO:
- {
- IRTecoAc ac(_pin);
- ac.begin();
- teco(&ac, on, mode, degC, fan, swingv, sleep);
- break;
- }
-#endif // SEND_TECO
-#if SEND_TOSHIBA_AC
- case TOSHIBA_AC:
- {
- IRToshibaAC ac(_pin);
- ac.begin();
- toshiba(&ac, on, mode, degC, fan);
- break;
- }
-#endif // SEND_TOSHIBA_AC
-#if SEND_TROTEC
- case TROTEC:
- {
- IRTrotecESP ac(_pin);
- ac.begin();
- trotec(&ac, on, mode, degC, fan, sleep);
- break;
- }
-#endif // SEND_TROTEC
-#if SEND_VESTEL_AC
- case VESTEL_AC:
- {
- IRVestelAc ac(_pin);
- ac.begin();
- vestel(&ac, on, mode, degC, fan, swingv, turbo, filter, sleep, clock);
- break;
- }
-#endif // SEND_VESTEL_AC
-#if SEND_WHIRLPOOL_AC
- case WHIRLPOOL_AC:
- {
- IRWhirlpoolAc ac(_pin);
- ac.begin();
- whirlpool(&ac, (whirlpool_ac_remote_model_t)model, on, mode, degC, fan,
- swingv, turbo, light, sleep, clock);
- break;
- }
-#endif // SEND_WHIRLPOOL_AC
- default:
- return false; // Fail, didn't match anything.
- }
- return true; // Success.
-}
-
-stdAc::opmode_t IRac::strToOpmode(const char *str,
- const stdAc::opmode_t def) {
- if (!strcmp(str, "AUTO") || !strcmp(str, "AUTOMATIC"))
- return stdAc::opmode_t::kAuto;
- else if (!strcmp(str, "OFF") || !strcmp(str, "STOP"))
- return stdAc::opmode_t::kOff;
- else if (!strcmp(str, "COOL") || !strcmp(str, "COOLING"))
- return stdAc::opmode_t::kCool;
- else if (!strcmp(str, "HEAT") || !strcmp(str, "HEATING"))
- return stdAc::opmode_t::kHeat;
- else if (!strcmp(str, "DRY") || !strcmp(str, "DRYING") ||
- !strcmp(str, "DEHUMIDIFY"))
- return stdAc::opmode_t::kDry;
- else if (!strcmp(str, "FAN") || !strcmp(str, "FANONLY") ||
- !strcmp(str, "FAN_ONLY"))
- return stdAc::opmode_t::kFan;
- else
- return def;
-}
-
-stdAc::fanspeed_t IRac::strToFanspeed(const char *str,
- const stdAc::fanspeed_t def) {
- if (!strcmp(str, "AUTO") || !strcmp(str, "AUTOMATIC"))
- return stdAc::fanspeed_t::kAuto;
- else if (!strcmp(str, "MIN") || !strcmp(str, "MINIMUM") ||
- !strcmp(str, "LOWEST"))
- return stdAc::fanspeed_t::kMin;
- else if (!strcmp(str, "LOW"))
- return stdAc::fanspeed_t::kLow;
- else if (!strcmp(str, "MED") || !strcmp(str, "MEDIUM") ||
- !strcmp(str, "MID"))
- return stdAc::fanspeed_t::kMedium;
- else if (!strcmp(str, "HIGH") || !strcmp(str, "HI"))
- return stdAc::fanspeed_t::kHigh;
- else if (!strcmp(str, "MAX") || !strcmp(str, "MAXIMUM") ||
- !strcmp(str, "HIGHEST"))
- return stdAc::fanspeed_t::kMax;
- else
- return def;
-}
-
-stdAc::swingv_t IRac::strToSwingV(const char *str,
- const stdAc::swingv_t def) {
- if (!strcmp(str, "AUTO") || !strcmp(str, "AUTOMATIC") ||
- !strcmp(str, "ON") || !strcmp(str, "SWING"))
- return stdAc::swingv_t::kAuto;
- else if (!strcmp(str, "OFF") || !strcmp(str, "STOP"))
- return stdAc::swingv_t::kOff;
- else if (!strcmp(str, "MIN") || !strcmp(str, "MINIMUM") ||
- !strcmp(str, "LOWEST") || !strcmp(str, "BOTTOM") ||
- !strcmp(str, "DOWN"))
- return stdAc::swingv_t::kLowest;
- else if (!strcmp(str, "LOW"))
- return stdAc::swingv_t::kLow;
- else if (!strcmp(str, "MID") || !strcmp(str, "MIDDLE") ||
- !strcmp(str, "MED") || !strcmp(str, "MEDIUM") ||
- !strcmp(str, "CENTRE") || !strcmp(str, "CENTER"))
- return stdAc::swingv_t::kMiddle;
- else if (!strcmp(str, "HIGH") || !strcmp(str, "HI"))
- return stdAc::swingv_t::kHigh;
- else if (!strcmp(str, "HIGHEST") || !strcmp(str, "MAX") ||
- !strcmp(str, "MAXIMUM") || !strcmp(str, "TOP") ||
- !strcmp(str, "UP"))
- return stdAc::swingv_t::kHighest;
- else
- return def;
-}
-
-stdAc::swingh_t IRac::strToSwingH(const char *str,
- const stdAc::swingh_t def) {
- if (!strcmp(str, "AUTO") || !strcmp(str, "AUTOMATIC") ||
- !strcmp(str, "ON") || !strcmp(str, "SWING"))
- return stdAc::swingh_t::kAuto;
- else if (!strcmp(str, "OFF") || !strcmp(str, "STOP"))
- return stdAc::swingh_t::kOff;
- else if (!strcmp(str, "LEFTMAX") || !strcmp(str, "LEFT MAX") ||
- !strcmp(str, "MAXLEFT") || !strcmp(str, "MAX LEFT") ||
- !strcmp(str, "FARLEFT") || !strcmp(str, "FAR LEFT"))
- return stdAc::swingh_t::kLeftMax;
- else if (!strcmp(str, "LEFT"))
- return stdAc::swingh_t::kLeft;
- else if (!strcmp(str, "MID") || !strcmp(str, "MIDDLE") ||
- !strcmp(str, "MED") || !strcmp(str, "MEDIUM") ||
- !strcmp(str, "CENTRE") || !strcmp(str, "CENTER"))
- return stdAc::swingh_t::kMiddle;
- else if (!strcmp(str, "RIGHT"))
- return stdAc::swingh_t::kRight;
- else if (!strcmp(str, "RIGHTMAX") || !strcmp(str, "RIGHT MAX") ||
- !strcmp(str, "MAXRIGHT") || !strcmp(str, "MAX RIGHT") ||
- !strcmp(str, "FARRIGHT") || !strcmp(str, "FAR RIGHT"))
- return stdAc::swingh_t::kRightMax;
- else
- return def;
-}
-
-// Assumes str is upper case or an integer >= 1.
-int16_t IRac::strToModel(const char *str, const int16_t def) {
- // Fujitsu A/C models
- if (!strcmp(str, "ARRAH2E")) {
- return fujitsu_ac_remote_model_t::ARRAH2E;
- } else if (!strcmp(str, "ARDB1")) {
- return fujitsu_ac_remote_model_t::ARDB1;
- // Panasonic A/C families
- } else if (!strcmp(str, "LKE") || !strcmp(str, "PANASONICLKE")) {
- return panasonic_ac_remote_model_t::kPanasonicLke;
- } else if (!strcmp(str, "NKE") || !strcmp(str, "PANASONICNKE")) {
- return panasonic_ac_remote_model_t::kPanasonicNke;
- } else if (!strcmp(str, "DKE") || !strcmp(str, "PANASONICDKE")) {
- return panasonic_ac_remote_model_t::kPanasonicDke;
- } else if (!strcmp(str, "JKE") || !strcmp(str, "PANASONICJKE")) {
- return panasonic_ac_remote_model_t::kPanasonicJke;
- } else if (!strcmp(str, "CKP") || !strcmp(str, "PANASONICCKP")) {
- return panasonic_ac_remote_model_t::kPanasonicCkp;
- } else if (!strcmp(str, "RKR") || !strcmp(str, "PANASONICRKR")) {
- return panasonic_ac_remote_model_t::kPanasonicRkr;
- // Whirlpool A/C models
- } else if (!strcmp(str, "DG11J13A") || !strcmp(str, "DG11J104") ||
- !strcmp(str, "DG11J1-04")) {
- return whirlpool_ac_remote_model_t::DG11J13A;
- } else if (!strcmp(str, "DG11J191")) {
- return whirlpool_ac_remote_model_t::DG11J191;
- } else {
- int16_t number = atoi(str);
- if (number > 0)
- return number;
- else
- return def;
- }
-}
-
-// Assumes str is upper case.
-bool IRac::strToBool(const char *str, const bool def) {
- if (!strcmp(str, "ON") || !strcmp(str, "1") || !strcmp(str, "YES") ||
- !strcmp(str, "TRUE"))
- return true;
- else if (!strcmp(str, "OFF") || !strcmp(str, "0") ||
- !strcmp(str, "NO") || !strcmp(str, "FALSE"))
- return false;
- else
- return def;
-}
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRutils.h b/lib/IRremoteESP8266-2.6.0/src/IRutils.h
deleted file mode 100644
index 0d0b677b5..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/IRutils.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef IRUTILS_H_
-#define IRUTILS_H_
-
-// Copyright 2017 David Conran
-
-#ifndef UNIT_TEST
-#include
-#endif
-#define __STDC_LIMIT_MACROS
-#include
-#ifndef ARDUINO
-#include
-#endif
-#include "IRremoteESP8266.h"
-#include "IRrecv.h"
-
-uint64_t reverseBits(uint64_t input, uint16_t nbits);
-#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist.
-String uint64ToString(uint64_t input, uint8_t base = 10);
-String typeToString(const decode_type_t protocol,
- const bool isRepeat = false);
-void serialPrintUint64(uint64_t input, uint8_t base = 10);
-String resultToSourceCode(const decode_results *results);
-String resultToTimingInfo(const decode_results *results);
-String resultToHumanReadableBasic(const decode_results *results);
-String resultToHexidecimal(const decode_results *result);
-String htmlEscape(const String unescaped);
-#else // ARDUINO
-std::string uint64ToString(uint64_t input, uint8_t base = 10);
-std::string typeToString(const decode_type_t protocol,
- const bool isRepeat = false);
-std::string resultToSourceCode(const decode_results *results);
-std::string resultToTimingInfo(const decode_results *results);
-std::string resultToHumanReadableBasic(const decode_results *results);
-std::string resultToHexidecimal(const decode_results *result);
-std::string htmlEscape(const std::string unescaped);
-#endif // ARDUINO
-bool hasACState(const decode_type_t protocol);
-uint16_t getCorrectedRawLength(const decode_results *results);
-uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init = 0);
-uint8_t xorBytes(uint8_t *start, const uint16_t length, const uint8_t init = 0);
-uint16_t countBits(const uint8_t *start, const uint16_t length,
- const bool ones = true, const uint16_t init = 0);
-uint16_t countBits(const uint64_t data, const uint8_t length,
- const bool ones = true, const uint16_t init = 0);
-uint64_t invertBits(const uint64_t data, const uint16_t nbits);
-decode_type_t strToDecodeType(const char *str);
-#endif // IRUTILS_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Argo.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Argo.cpp
deleted file mode 100644
index d6711acd3..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Argo.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
-Node MCU/ESP8266 Sketch to emulate Argo Ulisse 13 DCI remote
-Controls Argo Ulisse 13 DCI A/C
-Copyright 2017 Schmolders
-*/
-
-#include "ir_Argo.h"
-#include
-#include "IRremoteESP8266.h"
-#include "IRutils.h"
-
-// Constants
-// using SPACE modulation. MARK is always const 400u
-const uint16_t kArgoHdrMark = 6400;
-const uint16_t kArgoHdrSpace = 3300;
-const uint16_t kArgoBitMark = 400;
-const uint16_t kArgoOneSpace = 2200;
-const uint16_t kArgoZeroSpace = 900;
-
-#if SEND_ARGO
-// Send an Argo A/C message.
-//
-// Args:
-// data: An array of kArgoStateLength bytes containing the IR command.
-//
-// Status: ALPHA / Untested.
-
-void IRsend::sendArgo(unsigned char data[], uint16_t nbytes, uint16_t repeat) {
- // Check if we have enough bytes to send a proper message.
- if (nbytes < kArgoStateLength) return;
- // TODO(kaschmo): validate
- sendGeneric(kArgoHdrMark, kArgoHdrSpace, kArgoBitMark, kArgoOneSpace,
- kArgoBitMark, kArgoZeroSpace, 0, 0, // No Footer.
- data, nbytes, 38, false, repeat, kDutyDefault);
-}
-#endif // SEND_ARGO
-
-IRArgoAC::IRArgoAC(uint16_t pin) : _irsend(pin) { stateReset(); }
-
-void IRArgoAC::begin() { _irsend.begin(); }
-
-#if SEND_ARGO
-void IRArgoAC::send(const uint16_t repeat) {
- checksum(); // Create valid checksum before sending
- _irsend.sendArgo(argo, kArgoStateLength, repeat);
-}
-#endif // SEND_ARGO
-
-void IRArgoAC::checksum() {
- uint8_t sum = 2; // Corresponds to byte 11 being constant 0b01
- uint8_t i;
-
- // Only add up bytes to 9. byte 10 is 0b01 constant anyway.
- // Assume that argo array is MSB first (left)
- for (i = 0; i < 10; i++) sum += argo[i];
-
- sum = sum % 256; // modulo 256
- // Append sum to end of array
- // Set const part of checksum bit 10
- argo[10] = 0b00000010;
- argo[10] += sum << 2; // Shift up 2 bits and append to byte 10
- argo[11] = sum >> 6; // Shift down 6 bits and add in two LSBs of bit 11
-}
-
-void IRArgoAC::stateReset() {
- for (uint8_t i = 0; i < kArgoStateLength; i++) argo[i] = 0x0;
-
- // Argo Message. Store MSB left.
- // Default message:
- argo[0] = 0b10101100; // LSB first (as sent) 0b00110101; //const preamble
- argo[1] = 0b11110101; // LSB first: 0b10101111; //const preamble
- // Keep payload 2-9 at zero
- argo[10] = 0b00000010; // Const 01, checksum 6bit
- argo[11] = 0b00000000; // Checksum 2bit
-
- this->off();
- this->setTemp(20);
- this->setRoomTemp(25);
- this->setCoolMode(kArgoCoolAuto);
- this->setFan(kArgoFanAuto);
-}
-
-uint8_t* IRArgoAC::getRaw() {
- checksum(); // Ensure correct bit array before returning
- return argo;
-}
-
-void IRArgoAC::on() {
- // state = ON;
- ac_state = 1;
- // Bit 5 of byte 9 is on/off
- // in MSB first
- argo[9] = argo[9] | 0b00100000; // Set ON/OFF bit to 1
-}
-
-void IRArgoAC::off() {
- // state = OFF;
- ac_state = 0;
- // in MSB first
- // bit 5 of byte 9 to off
- argo[9] = argo[9] & 0b11011111; // Set on/off bit to 0
-}
-
-void IRArgoAC::setPower(bool state) {
- if (state)
- on();
- else
- off();
-}
-
-uint8_t IRArgoAC::getPower() { return ac_state; }
-
-void IRArgoAC::setMax(bool state) {
- max_mode = state;
- if (max_mode)
- argo[9] |= 0b00001000;
- else
- argo[9] &= 0b11110111;
-}
-
-bool IRArgoAC::getMax() { return max_mode; }
-
-// Set the temp in deg C
-// Sending 0 equals +4
-void IRArgoAC::setTemp(uint8_t temp) {
- if (temp < kArgoMinTemp)
- temp = kArgoMinTemp;
- else if (temp > kArgoMaxTemp)
- temp = kArgoMaxTemp;
-
- // Store in attributes
- set_temp = temp;
- // offset 4 degrees. "If I want 12 degrees, I need to send 8"
- temp -= 4;
- // Settemp = Bit 6,7 of byte 2, and bit 0-2 of byte 3
- // mask out bits
- // argo[13] & 0x00000100; // mask out ON/OFF Bit
- argo[2] &= 0b00111111;
- argo[3] &= 0b11111000;
-
- argo[2] += temp << 6; // append to bit 6,7
- argo[3] += temp >> 2; // remove lowest to bits and append in 0-2
-}
-
-uint8_t IRArgoAC::getTemp() { return set_temp; }
-
-// Set the speed of the fan
-void IRArgoAC::setFan(uint8_t fan) {
- // Set the fan speed bits, leave low 4 bits alone
- fan_mode = fan;
- // Mask out bits
- argo[3] &= 0b11100111;
- // Set fan mode at bit positions
- argo[3] += fan << 3;
-}
-
-uint8_t IRArgoAC::getFan() { return fan_mode; }
-
-void IRArgoAC::setFlap(uint8_t flap) {
- flap_mode = flap;
- // TODO(kaschmo): set correct bits for flap mode
-}
-
-uint8_t IRArgoAC::getFlap() { return flap_mode; }
-
-uint8_t IRArgoAC::getMode() {
- // return cooling 0, heating 1
- return ac_mode;
-}
-
-void IRArgoAC::setCoolMode(uint8_t mode) {
- ac_mode = 0; // Set ac mode to cooling
- cool_mode = mode;
- // Mask out bits, also leave bit 5 on 0 for cooling
- argo[2] &= 0b11000111;
-
- // Set cool mode at bit positions
- argo[2] += mode << 3;
-}
-
-uint8_t IRArgoAC::getCoolMode() { return cool_mode; }
-
-void IRArgoAC::setHeatMode(uint8_t mode) {
- ac_mode = 1; // Set ac mode to heating
- heat_mode = mode;
- // Mask out bits
- argo[2] &= 0b11000111;
- // Set heating bit
- argo[2] |= 0b00100000;
- // Set cool mode at bit positions
- argo[2] += mode << 3;
-}
-
-uint8_t IRArgoAC::getHeatMode() { return heat_mode; }
-
-void IRArgoAC::setNight(bool state) {
- night_mode = state;
- if (night_mode)
- // Set bit at night position: bit 2
- argo[9] |= 0b00000100;
- else
- argo[9] &= 0b11111011;
-}
-
-bool IRArgoAC::getNight() { return night_mode; }
-
-void IRArgoAC::setiFeel(bool state) {
- ifeel_mode = state;
- if (ifeel_mode)
- // Set bit at iFeel position: bit 7
- argo[9] |= 0b10000000;
- else
- argo[9] &= 0b01111111;
-}
-
-bool IRArgoAC::getiFeel() { return ifeel_mode; }
-
-void IRArgoAC::setTime() {
- // TODO(kaschmo): use function call from checksum to set time first
-}
-
-void IRArgoAC::setRoomTemp(uint8_t temp) {
- temp -= 4;
- // Mask out bits
- argo[3] &= 0b00011111;
- argo[4] &= 0b11111100;
-
- argo[3] += temp << 5; // Append to bit 5,6,7
- argo[4] += temp >> 3; // Remove lowest 3 bits and append in 0,1
-}
-
-// Convert a standard A/C Fan speed into its native fan speed.
-uint8_t IRArgoAC::convertFan(const stdAc::fanspeed_t speed) {
- switch (speed) {
- case stdAc::fanspeed_t::kMin:
- case stdAc::fanspeed_t::kLow:
- return kArgoFan1;
- case stdAc::fanspeed_t::kMedium:
- return kArgoFan2;
- case stdAc::fanspeed_t::kHigh:
- case stdAc::fanspeed_t::kMax:
- return kArgoFan3;
- default:
- return kArgoFanAuto;
- }
-}
-
-// Convert a standard A/C Fan speed into its native fan speed.
-uint8_t IRArgoAC::convertSwingV(const stdAc::swingv_t position) {
- switch (position) {
- case stdAc::swingv_t::kHighest:
- return kArgoFlapFull;
- case stdAc::swingv_t::kHigh:
- return kArgoFlap5;
- case stdAc::swingv_t::kMiddle:
- return kArgoFlap4;
- case stdAc::swingv_t::kLow:
- return kArgoFlap3;
- case stdAc::swingv_t::kLowest:
- return kArgoFlap1;
- default:
- return kArgoFlapAuto;
- }
-}
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.cpp
deleted file mode 100644
index 358dbd603..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.cpp
+++ /dev/null
@@ -1,1712 +0,0 @@
-/*
-An Arduino sketch to emulate IR Daikin ARC433** & ARC477A1 remote control unit
-Read more at:
-http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/
-
-Copyright 2016 sillyfrog
-Copyright 2017 sillyfrog, crankyoldgit
-Copyright 2018-2019 crankyoldgit
-*/
-
-#include "ir_Daikin.h"
-#include
-#ifndef ARDUINO
-#include
-#endif
-#include "IRrecv.h"
-#include "IRremoteESP8266.h"
-#include "IRsend.h"
-#ifdef UNIT_TEST
-#include "IRsend_test.h"
-#endif
-#include "IRutils.h"
-
-// DDDDD AAA IIIII KK KK IIIII NN NN
-// DD DD AAAAA III KK KK III NNN NN
-// DD DD AA AA III KKKK III NN N NN
-// DD DD AAAAAAA III KK KK III NN NNN
-// DDDDDD AA AA IIIII KK KK IIIII NN NN
-
-// Constants
-// Ref:
-// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
-// http://rdlab.cdmt.vn/project-2013/daikin-ir-protocol
-// https://github.com/markszabo/IRremoteESP8266/issues/582
-
-#if SEND_DAIKIN
-// Send a Daikin A/C message.
-//
-// Args:
-// data: An array of kDaikinStateLength bytes containing the IR command.
-//
-// Status: STABLE
-//
-// Ref:
-// IRDaikinESP.cpp
-// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
-// https://github.com/blafois/Daikin-IR-Reverse
-void IRsend::sendDaikin(const unsigned char data[], const uint16_t nbytes,
- const uint16_t repeat) {
- if (nbytes < kDaikinStateLengthShort)
- return; // Not enough bytes to send a proper message.
-
- for (uint16_t r = 0; r <= repeat; r++) {
- uint16_t offset = 0;
- // Send the header, 0b00000
- sendGeneric(0, 0, // No header for the header
- kDaikinBitMark, kDaikinOneSpace, kDaikinBitMark,
- kDaikinZeroSpace, kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
- (uint64_t)0b00000, kDaikinHeaderLength, 38, false, 0, 50);
- // Data #1
- if (nbytes < kDaikinStateLength) { // Are we using the legacy size?
- // Do this as a constant to save RAM and keep in flash memory
- sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
- kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
- kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
- kDaikinFirstHeader64, 64, 38, false, 0, 50);
- } else { // We are using the newer/more correct size.
- sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
- kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
- kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
- data, kDaikinSection1Length, 38, false, 0, 50);
- offset += kDaikinSection1Length;
- }
- // Data #2
- sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
- kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
- kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
- data + offset, kDaikinSection2Length, 38, false, 0, 50);
- offset += kDaikinSection2Length;
- // Data #3
- sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
- kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
- kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
- data + offset, nbytes - offset, 38, false, 0, 50);
- }
-}
-#endif // SEND_DAIKIN
-
-IRDaikinESP::IRDaikinESP(uint16_t pin) : _irsend(pin) { stateReset(); }
-
-void IRDaikinESP::begin(void) { _irsend.begin(); }
-
-#if SEND_DAIKIN
-void IRDaikinESP::send(const uint16_t repeat) {
- this->checksum();
- _irsend.sendDaikin(remote, kDaikinStateLength, repeat);
-}
-#endif // SEND_DAIKIN
-
-// Verify the checksums are valid for a given state.
-// Args:
-// state: The array to verify the checksums of.
-// length: The size of the state.
-// Returns:
-// A boolean.
-bool IRDaikinESP::validChecksum(uint8_t state[], const uint16_t length) {
- // Data #1
- if (length < kDaikinSection1Length ||
- state[kDaikinByteChecksum1] != sumBytes(state, kDaikinSection1Length - 1))
- return false;
- // Data #2
- if (length < kDaikinSection1Length + kDaikinSection2Length ||
- state[kDaikinByteChecksum2] != sumBytes(state + kDaikinSection1Length,
- kDaikinSection2Length - 1))
- return false;
- // Data #3
- if (length < kDaikinSection1Length + kDaikinSection2Length + 2 ||
- state[length - 1] != sumBytes(state + kDaikinSection1Length +
- kDaikinSection2Length,
- length - (kDaikinSection1Length +
- kDaikinSection2Length) - 1))
- return false;
- return true;
-}
-
-// Calculate and set the checksum values for the internal state.
-void IRDaikinESP::checksum(void) {
- remote[kDaikinByteChecksum1] = sumBytes(remote, kDaikinSection1Length - 1);
- remote[kDaikinByteChecksum2] = sumBytes(remote + kDaikinSection1Length,
- kDaikinSection2Length - 1);
- remote[kDaikinByteChecksum3] = sumBytes(remote + kDaikinSection1Length +
- kDaikinSection2Length,
- kDaikinSection3Length - 1);
-}
-
-void IRDaikinESP::stateReset(void) {
- for (uint8_t i = 0; i < kDaikinStateLength; i++) remote[i] = 0x0;
-
- remote[0] = 0x11;
- remote[1] = 0xDA;
- remote[2] = 0x27;
- remote[4] = 0xC5;
- // remote[7] is a checksum byte, it will be set by checksum().
-
- remote[8] = 0x11;
- remote[9] = 0xDA;
- remote[10] = 0x27;
- remote[12] = 0x42;
- // remote[15] is a checksum byte, it will be set by checksum().
- remote[16] = 0x11;
- remote[17] = 0xDA;
- remote[18] = 0x27;
- remote[21] = 0x49;
- remote[22] = 0x1E;
- remote[24] = 0xB0;
- remote[27] = 0x06;
- remote[28] = 0x60;
- remote[31] = 0xC0;
- // remote[34] is a checksum byte, it will be set by checksum().
- this->checksum();
-}
-
-uint8_t *IRDaikinESP::getRaw(void) {
- this->checksum(); // Ensure correct settings before sending.
- return remote;
-}
-
-void IRDaikinESP::setRaw(const uint8_t new_code[], const uint16_t length) {
- uint8_t offset = 0;
- if (length == kDaikinStateLengthShort) { // Handle the "short" length case.
- offset = kDaikinStateLength - kDaikinStateLengthShort;
- this->stateReset();
- }
- for (uint8_t i = 0; i < length && i < kDaikinStateLength; i++)
- remote[i + offset] = new_code[i];
-}
-
-void IRDaikinESP::on(void) { remote[kDaikinBytePower] |= kDaikinBitPower; }
-
-void IRDaikinESP::off(void) { remote[kDaikinBytePower] &= ~kDaikinBitPower; }
-
-void IRDaikinESP::setPower(const bool on) {
- if (on)
- this->on();
- else
- this->off();
-}
-
-bool IRDaikinESP::getPower(void) {
- return remote[kDaikinBytePower] & kDaikinBitPower;
-}
-
-// Set the temp in deg C
-void IRDaikinESP::setTemp(const uint8_t temp) {
- uint8_t degrees = std::max(temp, kDaikinMinTemp);
- degrees = std::min(degrees, kDaikinMaxTemp);
- remote[kDaikinByteTemp] = degrees << 1;
-}
-
-uint8_t IRDaikinESP::getTemp(void) { return remote[kDaikinByteTemp] >> 1; }
-
-// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet
-void IRDaikinESP::setFan(const uint8_t fan) {
- // Set the fan speed bits, leave low 4 bits alone
- uint8_t fanset;
- if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto)
- fanset = fan;
- else if (fan < kDaikinFanMin || fan > kDaikinFanMax)
- fanset = kDaikinFanAuto;
- else
- fanset = 2 + fan;
- remote[kDaikinByteFan] &= 0x0F;
- remote[kDaikinByteFan] |= (fanset << 4);
-}
-
-uint8_t IRDaikinESP::getFan(void) {
- uint8_t fan = remote[kDaikinByteFan] >> 4;
- if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2;
- return fan;
-}
-
-uint8_t IRDaikinESP::getMode(void) { return remote[kDaikinBytePower] >> 4; }
-
-void IRDaikinESP::setMode(const uint8_t mode) {
- switch (mode) {
- case kDaikinAuto:
- case kDaikinCool:
- case kDaikinHeat:
- case kDaikinFan:
- case kDaikinDry:
- remote[kDaikinBytePower] &= 0b10001111;
- remote[kDaikinBytePower] |= (mode << 4);
- break;
- default:
- this->setMode(kDaikinAuto);
- }
-}
-
-void IRDaikinESP::setSwingVertical(const bool on) {
- if (on)
- remote[kDaikinByteFan] |= 0x0F;
- else
- remote[kDaikinByteFan] &= 0xF0;
-}
-
-bool IRDaikinESP::getSwingVertical(void) {
- return remote[kDaikinByteFan] & 0x0F;
-}
-
-void IRDaikinESP::setSwingHorizontal(const bool on) {
- if (on)
- remote[kDaikinByteSwingH] |= 0x0F;
- else
- remote[kDaikinByteSwingH] &= 0xF0;
-}
-
-bool IRDaikinESP::getSwingHorizontal(void) {
- return remote[kDaikinByteSwingH] & 0x0F;
-}
-
-void IRDaikinESP::setQuiet(const bool on) {
- if (on) {
- remote[kDaikinByteSilent] |= kDaikinBitSilent;
- // Powerful & Quiet mode being on are mutually exclusive.
- this->setPowerful(false);
- } else {
- remote[kDaikinByteSilent] &= ~kDaikinBitSilent;
- }
-}
-
-bool IRDaikinESP::getQuiet(void) {
- return remote[kDaikinByteSilent] & kDaikinBitSilent;
-}
-
-void IRDaikinESP::setPowerful(const bool on) {
- if (on) {
- remote[kDaikinBytePowerful] |= kDaikinBitPowerful;
- // Powerful, Quiet, & Econo mode being on are mutually exclusive.
- this->setQuiet(false);
- this->setEcono(false);
- } else {
- remote[kDaikinBytePowerful] &= ~kDaikinBitPowerful;
- }
-}
-
-bool IRDaikinESP::getPowerful(void) {
- return remote[kDaikinBytePowerful] & kDaikinBitPowerful;
-}
-
-void IRDaikinESP::setSensor(const bool on) {
- if (on)
- remote[kDaikinByteSensor] |= kDaikinBitSensor;
- else
- remote[kDaikinByteSensor] &= ~kDaikinBitSensor;
-}
-
-bool IRDaikinESP::getSensor(void) {
- return remote[kDaikinByteSensor] & kDaikinBitSensor;
-}
-
-void IRDaikinESP::setEcono(const bool on) {
- if (on) {
- remote[kDaikinByteEcono] |= kDaikinBitEcono;
- // Powerful & Econo mode being on are mutually exclusive.
- this->setPowerful(false);
- } else {
- remote[kDaikinByteEcono] &= ~kDaikinBitEcono;
- }
-}
-
-bool IRDaikinESP::getEcono(void) {
- return remote[kDaikinByteEcono] & kDaikinBitEcono;
-}
-
-void IRDaikinESP::setEye(const bool on) {
- if (on)
- remote[kDaikinByteEye] |= kDaikinBitEye;
- else
- remote[kDaikinByteEye] &= ~kDaikinBitEye;
-}
-
-bool IRDaikinESP::getEye(void) {
- return remote[kDaikinByteEye] & kDaikinBitEye;
-}
-
-void IRDaikinESP::setMold(const bool on) {
- if (on)
- remote[kDaikinByteMold] |= kDaikinBitMold;
- else
- remote[kDaikinByteMold] &= ~kDaikinBitMold;
-}
-
-bool IRDaikinESP::getMold(void) {
- return remote[kDaikinByteMold] & kDaikinBitMold;
-}
-
-void IRDaikinESP::setComfort(const bool on) {
- if (on)
- remote[kDaikinByteComfort] |= kDaikinBitComfort;
- else
- remote[kDaikinByteComfort] &= ~kDaikinBitComfort;
-}
-
-bool IRDaikinESP::getComfort(void) {
- return remote[kDaikinByteComfort] & kDaikinBitComfort;
-}
-
-// starttime: Number of minutes after midnight.
-void IRDaikinESP::enableOnTimer(const uint16_t starttime) {
- remote[kDaikinByteOnTimer] |= kDaikinBitOnTimer;
- remote[kDaikinByteOnTimerMinsLow] = starttime;
- // only keep 4 bits
- remote[kDaikinByteOnTimerMinsHigh] &= 0xF0;
- remote[kDaikinByteOnTimerMinsHigh] |= ((starttime >> 8) & 0x0F);
-}
-
-void IRDaikinESP::disableOnTimer(void) {
- this->enableOnTimer(kDaikinUnusedTime);
- remote[kDaikinByteOnTimer] &= ~kDaikinBitOnTimer;
-}
-
-uint16_t IRDaikinESP::getOnTime(void) {
- return ((remote[kDaikinByteOnTimerMinsHigh] & 0x0F) << 8) +
- remote[kDaikinByteOnTimerMinsLow];
-}
-
-bool IRDaikinESP::getOnTimerEnabled(void) {
- return remote[kDaikinByteOnTimer] & kDaikinBitOnTimer;
-}
-
-// endtime: Number of minutes after midnight.
-void IRDaikinESP::enableOffTimer(const uint16_t endtime) {
- remote[kDaikinByteOffTimer] |= kDaikinBitOffTimer;
- remote[kDaikinByteOffTimerMinsHigh] = endtime >> 4;
- remote[kDaikinByteOffTimerMinsLow] &= 0x0F;
- remote[kDaikinByteOffTimerMinsLow] |= ((endtime & 0x0F) << 4);
-}
-
-void IRDaikinESP::disableOffTimer(void) {
- this->enableOffTimer(kDaikinUnusedTime);
- remote[kDaikinByteOffTimer] &= ~kDaikinBitOffTimer;
-}
-
-uint16_t IRDaikinESP::getOffTime(void) {
- return (remote[kDaikinByteOffTimerMinsHigh] << 4) +
- ((remote[kDaikinByteOffTimerMinsLow] & 0xF0) >> 4);
-}
-
-bool IRDaikinESP::getOffTimerEnabled(void) {
- return remote[kDaikinByteOffTimer] & kDaikinBitOffTimer;
-}
-
-void IRDaikinESP::setCurrentTime(const uint16_t mins_since_midnight) {
- uint16_t mins = mins_since_midnight;
- if (mins > 24 * 60) mins = 0; // If > 23:59, set to 00:00
- remote[kDaikinByteClockMinsLow] = mins;
- // only keep 4 bits
- remote[kDaikinByteClockMinsHigh] &= 0xF0;
- remote[kDaikinByteClockMinsHigh] |= ((mins >> 8) & 0x0F);
-}
-
-uint16_t IRDaikinESP::getCurrentTime(void) {
- return ((remote[kDaikinByteClockMinsHigh] & 0x0F) << 8) +
- remote[kDaikinByteClockMinsLow];
-}
-
-#ifdef ARDUINO
-String IRDaikinESP::renderTime(const uint16_t timemins) {
- String ret;
-#else // ARDUINO
-std::string IRDaikinESP::renderTime(const uint16_t timemins) {
- std::string ret;
-#endif // ARDUINO
- ret = uint64ToString(timemins / 60) + ':';
- uint8_t mins = timemins % 60;
- if (mins < 10) ret += '0';
- ret += uint64ToString(mins);
- return ret;
-}
-
-// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRDaikinESP::toString(void) {
- String result = "";
-#else // ARDUINO
-std::string IRDaikinESP::toString(void) {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- result += this->getPower() ? F("On") : F("Off");
- result += F(", Mode: ");
- result += uint64ToString(this->getMode());
- switch (this->getMode()) {
- case kDaikinAuto:
- result += F(" (AUTO)");
- break;
- case kDaikinCool:
- result += F(" (COOL)");
- break;
- case kDaikinHeat:
- result += F(" (HEAT)");
- break;
- case kDaikinDry:
- result += F(" (DRY)");
- break;
- case kDaikinFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(this->getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(this->getFan());
- switch (this->getFan()) {
- case kDaikinFanAuto:
- result += F(" (AUTO)");
- break;
- case kDaikinFanQuiet:
- result += F(" (QUIET)");
- break;
- case kDaikinFanMin:
- result += F(" (MIN)");
- break;
- case kDaikinFanMax:
- result += F(" (MAX)");
- break;
- }
- result += F(", Powerful: ");
- result += this->getPowerful() ? F("On") : F("Off");
- result += F(", Quiet: ");
- result += this->getQuiet() ? F("On") : F("Off");
- result += F(", Sensor: ");
- result += this->getSensor() ? F("On") : F("Off");
- result += F(", Eye: ");
- result += this->getEye() ? F("On") : F("Off");
- result += F(", Mold: ");
- result += this->getMold() ? F("On") : F("Off");
- result += F(", Comfort: ");
- result += this->getComfort() ? F("On") : F("Off");
- result += F(", Swing (Horizontal): ");
- result += this->getSwingHorizontal() ? F("On") : F("Off");
- result += F(", Swing (Vertical): ");
- result += this->getSwingVertical() ? F("On") : F("Off");
- result += F(", Current Time: ");
- result += this->renderTime(this->getCurrentTime());
- result += F(", On Time: ");
- if (this->getOnTimerEnabled())
- result += this->renderTime(this->getOnTime());
- else
- result += F("Off");
- result += F(", Off Time: ");
- if (this->getOffTimerEnabled())
- result += this->renderTime(this->getOffTime());
- else
- result += F("Off");
- return result;
-}
-
-// Convert a standard A/C mode into its native mode.
-uint8_t IRDaikinESP::convertMode(const stdAc::opmode_t mode) {
- switch (mode) {
- case stdAc::opmode_t::kCool:
- return kDaikinCool;
- case stdAc::opmode_t::kHeat:
- return kDaikinHeat;
- case stdAc::opmode_t::kDry:
- return kDaikinDry;
- case stdAc::opmode_t::kFan:
- return kDaikinFan;
- default:
- return kDaikinAuto;
- }
-}
-
-// Convert a standard A/C Fan speed into its native fan speed.
-uint8_t IRDaikinESP::convertFan(const stdAc::fanspeed_t speed) {
- switch (speed) {
- case stdAc::fanspeed_t::kMin:
- return kDaikinFanQuiet;
- case stdAc::fanspeed_t::kLow:
- return kDaikinFanMin;
- case stdAc::fanspeed_t::kMedium:
- return kDaikinFanMin + 1;
- case stdAc::fanspeed_t::kHigh:
- return kDaikinFanMax - 1;
- case stdAc::fanspeed_t::kMax:
- return kDaikinFanMax;
- default:
- return kDaikinFanAuto;
- }
-}
-
-#if DECODE_DAIKIN
-// Decode the supplied Daikin A/C message.
-// Args:
-// results: Ptr to the data to decode and where to store the decode result.
-// nbits: Nr. of bits to expect in the data portion. (kDaikinBits)
-// strict: Flag to indicate if we strictly adhere to the specification.
-// Returns:
-// boolean: True if it can decode it, false if it can't.
-//
-// Status: BETA / Should be working.
-//
-// Ref:
-// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
-bool IRrecv::decodeDaikin(decode_results *results, const uint16_t nbits,
- const bool strict) {
- // Is there enough data to match successfully?
- if (results->rawlen < (2 * (nbits + kDaikinHeaderLength) +
- kDaikinSections * (kHeader + kFooter) + kFooter - 1))
- return false;
-
- // Compliance
- if (strict && nbits != kDaikinBits) return false;
-
- uint16_t offset = kStartOffset;
- match_result_t data_result;
- uint16_t dataBitsSoFar = 0;
- uint16_t i = 0;
-
- // Header #1 - Doesn't count as data.
- data_result = matchData(&(results->rawbuf[offset]), kDaikinHeaderLength,
- kDaikinBitMark, kDaikinOneSpace,
- kDaikinBitMark, kDaikinZeroSpace,
- kDaikinTolerance, kDaikinMarkExcess, false);
- offset += data_result.used;
- if (data_result.success == false) return false; // Fail
- if (data_result.data) return false; // The header bits should be zero.
-
- // Read the Data sections.
- // Keep reading bytes until we either run out of section or state to fill.
- const uint8_t kSectionSize[kDaikinSections] = {
- kDaikinSection1Length, kDaikinSection2Length, kDaikinSection3Length};
- for (uint8_t section = 0, pos = 0; section < kDaikinSections;
- section++) {
- pos += kSectionSize[section];
- // Section Footer
- if (!matchMark(results->rawbuf[offset++], kDaikinBitMark,
- kDaikinTolerance, kDaikinMarkExcess)) return false;
- if (!matchSpace(results->rawbuf[offset++], kDaikinZeroSpace + kDaikinGap,
- kDaikinTolerance, kDaikinMarkExcess)) return false;
- // Section Header
- if (!matchMark(results->rawbuf[offset++], kDaikinHdrMark,
- kDaikinTolerance, kDaikinMarkExcess)) return false;
- if (!matchSpace(results->rawbuf[offset++], kDaikinHdrSpace,
- kDaikinTolerance, kDaikinMarkExcess)) return false;
-
- // Section Data
- for (; offset <= results->rawlen - 16 && i < pos;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- // Read in a byte at a time.
- data_result =
- matchData(&(results->rawbuf[offset]), 8,
- kDaikinBitMark, kDaikinOneSpace,
- kDaikinBitMark, kDaikinZeroSpace,
- kDaikinTolerance, kDaikinMarkExcess, false);
- if (data_result.success == false) break; // Fail
- results->state[i] = (uint8_t)data_result.data;
- }
- }
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kDaikinGap))
- return false;
-
- // Compliance
- if (strict) {
- // Re-check we got the correct size/length due to the way we read the data.
- if (dataBitsSoFar != kDaikinBits) return false;
- // Validate the checksum.
- if (!IRDaikinESP::validChecksum(results->state)) return false;
- }
-
- // Success
- results->decode_type = DAIKIN;
- results->bits = dataBitsSoFar;
- // No need to record the state as we stored it as we decoded it.
- // As we use result->state, we don't record value, address, or command as it
- // is a union data type.
- return true;
-}
-#endif // DECODE_DAIKIN
-
-#if SEND_DAIKIN2
-// Send a Daikin2 A/C message.
-//
-// Args:
-// data: An array of kDaikin2StateLength bytes containing the IR command.
-//
-// Status: BETA/Appears to work.
-//
-// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/582
-void IRsend::sendDaikin2(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
- if (nbytes < kDaikin2Section1Length)
- return; // Not enough bytes to send a partial message.
-
- for (uint16_t r = 0; r <= repeat; r++) {
- // Leader
- sendGeneric(kDaikin2LeaderMark, kDaikin2LeaderSpace,
- 0, 0, 0, 0, 0, 0, (uint64_t) 0, // No data payload.
- 0, kDaikin2Freq, false, 0, 50);
- // Section #1
- sendGeneric(kDaikin2HdrMark, kDaikin2HdrSpace, kDaikin2BitMark,
- kDaikin2OneSpace, kDaikin2BitMark, kDaikin2ZeroSpace,
- kDaikin2BitMark, kDaikin2Gap, data, kDaikin2Section1Length,
- kDaikin2Freq, false, 0, 50);
- // Section #2
- sendGeneric(kDaikin2HdrMark, kDaikin2HdrSpace, kDaikin2BitMark,
- kDaikin2OneSpace, kDaikin2BitMark, kDaikin2ZeroSpace,
- kDaikin2BitMark, kDaikin2Gap, data + kDaikin2Section1Length,
- nbytes - kDaikin2Section1Length,
- kDaikin2Freq, false, 0, 50);
- }
-}
-#endif // SEND_DAIKIN2
-
-// Class for handling Daikin2 A/C messages.
-//
-// Code by crankyoldgit, Reverse engineering analysis by sheppy99
-//
-// Supported Remotes: Daikin ARC477A1 remote
-//
-// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/582
-// https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit?usp=sharing
-// https://www.daikin.co.nz/sites/default/files/daikin-split-system-US7-FTXZ25-50NV1B.pdf
-IRDaikin2::IRDaikin2(uint16_t pin) : _irsend(pin) { stateReset(); }
-
-void IRDaikin2::begin() { _irsend.begin(); }
-
-#if SEND_DAIKIN2
-void IRDaikin2::send(const uint16_t repeat) {
- checksum();
- _irsend.sendDaikin2(remote_state, kDaikin2StateLength, repeat);
-}
-#endif // SEND_DAIKIN2
-
-// Verify the checksum is valid for a given state.
-// Args:
-// state: The array to verify the checksum of.
-// length: The size of the state.
-// Returns:
-// A boolean.
-bool IRDaikin2::validChecksum(uint8_t state[], const uint16_t length) {
- // Validate the checksum of section #1.
- if (length <= kDaikin2Section1Length - 1 ||
- state[kDaikin2Section1Length - 1] != sumBytes(state,
- kDaikin2Section1Length - 1))
- return false;
- // Validate the checksum of section #2 (a.k.a. the rest)
- if (length <= kDaikin2Section1Length + 1 ||
- state[length - 1] != sumBytes(state + kDaikin2Section1Length,
- length - kDaikin2Section1Length - 1))
- return false;
- return true;
-}
-
-// Calculate and set the checksum values for the internal state.
-void IRDaikin2::checksum() {
- remote_state[kDaikin2Section1Length - 1] = sumBytes(
- remote_state, kDaikin2Section1Length - 1);
- remote_state[kDaikin2StateLength -1 ] = sumBytes(
- remote_state + kDaikin2Section1Length, kDaikin2Section2Length - 1);
-}
-
-void IRDaikin2::stateReset() {
- for (uint8_t i = 0; i < kDaikin2StateLength; i++) remote_state[i] = 0x0;
-
- remote_state[0] = 0x11;
- remote_state[1] = 0xDA;
- remote_state[2] = 0x27;
- remote_state[4] = 0x01;
- remote_state[6] = 0xC0;
- remote_state[7] = 0x70;
- remote_state[8] = 0x08;
- remote_state[9] = 0x0C;
- remote_state[10] = 0x80;
- remote_state[11] = 0x04;
- remote_state[12] = 0xB0;
- remote_state[13] = 0x16;
- remote_state[14] = 0x24;
- remote_state[17] = 0xBE;
- remote_state[18] = 0xD0;
- // remote_state[19] is a checksum byte, it will be set by checksum().
- remote_state[20] = 0x11;
- remote_state[21] = 0xDA;
- remote_state[22] = 0x27;
- remote_state[25] = 0x08;
- remote_state[28] = 0xA0;
- remote_state[35] = 0xC1;
- remote_state[36] = 0x80;
- remote_state[37] = 0x60;
- // remote_state[38] is a checksum byte, it will be set by checksum().
- disableOnTimer();
- disableOffTimer();
- disableSleepTimer();
- checksum();
-}
-
-uint8_t *IRDaikin2::getRaw() {
- checksum(); // Ensure correct settings before sending.
- return remote_state;
-}
-
-void IRDaikin2::setRaw(const uint8_t new_code[]) {
- for (uint8_t i = 0; i < kDaikin2StateLength; i++)
- remote_state[i] = new_code[i];
-}
-
-void IRDaikin2::on() {
- remote_state[25] |= kDaikinBitPower;
- remote_state[6] &= ~kDaikin2BitPower;
-}
-
-void IRDaikin2::off() {
- remote_state[25] &= ~kDaikinBitPower;
- remote_state[6] |= kDaikin2BitPower;
-}
-
-void IRDaikin2::setPower(const bool state) {
- if (state)
- on();
- else
- off();
-}
-
-bool IRDaikin2::getPower() {
- return (remote_state[25] & kDaikinBitPower) &&
- !(remote_state[6] & kDaikin2BitPower);
-}
-
-uint8_t IRDaikin2::getMode() { return remote_state[25] >> 4; }
-
-void IRDaikin2::setMode(const uint8_t desired_mode) {
- uint8_t mode = desired_mode;
- switch (mode) {
- case kDaikinCool:
- case kDaikinHeat:
- case kDaikinFan:
- case kDaikinDry:
- break;
- default:
- mode = kDaikinAuto;
- }
- remote_state[25] &= 0b10001111;
- remote_state[25] |= (mode << 4);
- // Redo the temp setting as Cool mode has a different min temp.
- if (mode == kDaikinCool) this->setTemp(this->getTemp());
-}
-
-// Set the temp in deg C
-void IRDaikin2::setTemp(const uint8_t desired) {
- // The A/C has a different min temp if in cool mode.
- uint8_t temp = std::max(
- (this->getMode() == kDaikinCool) ? kDaikin2MinCoolTemp : kDaikinMinTemp,
- desired);
- temp = std::min(kDaikinMaxTemp, temp);
- remote_state[26] = temp * 2;
-}
-
-// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet
-void IRDaikin2::setFan(const uint8_t fan) {
- // Set the fan speed bits, leave low 4 bits alone
- uint8_t fanset;
- if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto)
- fanset = fan;
- else if (fan < kDaikinFanMin || fan > kDaikinFanMax)
- fanset = kDaikinFanAuto;
- else
- fanset = 2 + fan;
- remote_state[28] &= 0x0F;
- remote_state[28] |= (fanset << 4);
-}
-
-uint8_t IRDaikin2::getFan() {
- uint8_t fan = remote_state[28] >> 4;
- if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2;
- return fan;
-}
-
-uint8_t IRDaikin2::getTemp() { return remote_state[26] / 2; }
-
-void IRDaikin2::setSwingVertical(const uint8_t position) {
- switch (position) {
- case kDaikin2SwingVHigh:
- case 2:
- case 3:
- case 4:
- case 5:
- case kDaikin2SwingVLow:
- case kDaikin2SwingVBreeze:
- case kDaikin2SwingVCirculate:
- case kDaikin2SwingVAuto:
- remote_state[18] &= 0xF0;
- remote_state[18] |= (position & 0x0F);
- }
-}
-
-uint8_t IRDaikin2::getSwingVertical() { return remote_state[18] & 0x0F; }
-
-void IRDaikin2::setSwingHorizontal(const uint8_t position) {
- remote_state[17] = position;
-}
-
-uint8_t IRDaikin2::getSwingHorizontal() { return remote_state[17]; }
-
-void IRDaikin2::setCurrentTime(const uint16_t numMins) {
- uint16_t mins = numMins;
- if (numMins > 24 * 60) mins = 0; // If > 23:59, set to 00:00
- remote_state[5] = (uint8_t)(mins & 0xFF);
- // only keep 4 bits
- remote_state[6] &= 0xF0;
- remote_state[6] |= (uint8_t)((mins >> 8) & 0x0F);
-}
-
-uint16_t IRDaikin2::getCurrentTime() {
- return ((remote_state[6] & 0x0F) << 8) + remote_state[5];
-}
-
-// starttime: Number of minutes after midnight.
-// Note: Timer location is shared with sleep timer.
-void IRDaikin2::enableOnTimer(const uint16_t starttime) {
- clearSleepTimerFlag();
- remote_state[25] |= kDaikinBitOnTimer; // Set the On Timer flag.
- remote_state[30] = (uint8_t)(starttime & 0xFF);
- // only keep 4 bits
- remote_state[31] &= 0xF0;
- remote_state[31] |= (uint8_t)((starttime >> 8) & 0x0F);
-}
-
-void IRDaikin2::clearOnTimerFlag() {
- remote_state[25] &= ~kDaikinBitOnTimer;
-}
-
-void IRDaikin2::disableOnTimer() {
- enableOnTimer(kDaikinUnusedTime);
- clearOnTimerFlag();
- clearSleepTimerFlag();
-}
-
-uint16_t IRDaikin2::getOnTime() {
- return ((remote_state[31] & 0x0F) << 8) + remote_state[30];
-}
-
-bool IRDaikin2::getOnTimerEnabled() {
- return remote_state[25] & kDaikinBitOnTimer;
-}
-
-// endtime: Number of minutes after midnight.
-void IRDaikin2::enableOffTimer(const uint16_t endtime) {
- remote_state[25] |= kDaikinBitOffTimer; // Set the Off Timer flag.
- remote_state[32] = (uint8_t)((endtime >> 4) & 0xFF);
- remote_state[31] &= 0x0F;
- remote_state[31] |= (uint8_t)((endtime & 0xF) << 4);
-}
-
-void IRDaikin2::disableOffTimer() {
- enableOffTimer(kDaikinUnusedTime);
- remote_state[25] &= ~kDaikinBitOffTimer; // Clear the Off Timer flag.
-}
-
-uint16_t IRDaikin2::getOffTime() {
- return (remote_state[32] << 4) + (remote_state[31] >> 4);
-}
-
-bool IRDaikin2::getOffTimerEnabled() {
- return remote_state[25] & kDaikinBitOffTimer;
-}
-
-uint8_t IRDaikin2::getBeep() {
- return remote_state[7] >> 6;
-}
-
-void IRDaikin2::setBeep(const uint8_t beep) {
- remote_state[7] &= ~kDaikin2BeepMask;
- remote_state[7] |= ((beep << 6) & kDaikin2BeepMask);
-}
-
-uint8_t IRDaikin2::getLight() {
- return (remote_state[7] & kDaikin2LightMask) >> 4;
-}
-
-void IRDaikin2::setLight(const uint8_t light) {
- remote_state[7] &= ~kDaikin2LightMask;
- remote_state[7] |= ((light << 4) & kDaikin2LightMask);
-}
-
-void IRDaikin2::setMold(const bool on) {
- if (on)
- remote_state[8] |= kDaikin2BitMold;
- else
- remote_state[8] &= ~kDaikin2BitMold;
-}
-
-bool IRDaikin2::getMold() {
- return remote_state[8] & kDaikin2BitMold;
-}
-
-// Auto clean setting.
-void IRDaikin2::setClean(const bool on) {
- if (on)
- remote_state[8] |= kDaikin2BitClean;
- else
- remote_state[8] &= ~kDaikin2BitClean;
-}
-
-bool IRDaikin2::getClean() {
- return remote_state[8] & kDaikin2BitClean;
-}
-
-// Fresh Air settings.
-void IRDaikin2::setFreshAir(const bool on) {
- if (on)
- remote_state[8] |= kDaikin2BitFreshAir;
- else
- remote_state[8] &= ~kDaikin2BitFreshAir;
-}
-
-bool IRDaikin2::getFreshAir() {
- return remote_state[8] & kDaikin2BitFreshAir;
-}
-
-void IRDaikin2::setFreshAirHigh(const bool on) {
- if (on)
- remote_state[8] |= kDaikin2BitFreshAirHigh;
- else
- remote_state[8] &= ~kDaikin2BitFreshAirHigh;
-}
-
-bool IRDaikin2::getFreshAirHigh() {
- return remote_state[8] & kDaikin2BitFreshAirHigh;
-}
-
-void IRDaikin2::setEyeAuto(bool on) {
- if (on)
- remote_state[13] |= kDaikin2BitEyeAuto;
- else
- remote_state[13] &= ~kDaikin2BitEyeAuto;
-}
-
-bool IRDaikin2::getEyeAuto() {
- return remote_state[13] & kDaikin2BitEyeAuto;
-}
-
-void IRDaikin2::setEye(bool on) {
- if (on)
- remote_state[36] |= kDaikin2BitEye;
- else
- remote_state[36] &= ~kDaikin2BitEye;
-}
-
-bool IRDaikin2::getEye() {
- return remote_state[36] & kDaikin2BitEye;
-}
-
-void IRDaikin2::setEcono(bool on) {
- if (on)
- remote_state[36] |= kDaikinBitEcono;
- else
- remote_state[36] &= ~kDaikinBitEcono;
-}
-
-bool IRDaikin2::getEcono() {
- return remote_state[36] & kDaikinBitEcono;
-}
-
-// sleeptime: Number of minutes.
-// Note: Timer location is shared with On Timer.
-void IRDaikin2::enableSleepTimer(const uint16_t sleeptime) {
- enableOnTimer(sleeptime);
- clearOnTimerFlag();
- remote_state[36] |= kDaikin2BitSleepTimer; // Set the Sleep Timer flag.
-}
-
-void IRDaikin2::clearSleepTimerFlag() {
- remote_state[36] &= ~kDaikin2BitSleepTimer;
-}
-
-void IRDaikin2::disableSleepTimer() {
- disableOnTimer();
-}
-
-uint16_t IRDaikin2::getSleepTime() {
- return getOnTime();
-}
-
-bool IRDaikin2::getSleepTimerEnabled() {
- return remote_state[36] & kDaikin2BitSleepTimer;
-}
-
-void IRDaikin2::setQuiet(const bool on) {
- if (on) {
- remote_state[33] |= kDaikinBitSilent;
- // Powerful & Quiet mode being on are mutually exclusive.
- setPowerful(false);
- } else {
- remote_state[33] &= ~kDaikinBitSilent;
- }
-}
-
-bool IRDaikin2::getQuiet() { return remote_state[33] & kDaikinBitSilent; }
-
-void IRDaikin2::setPowerful(const bool on) {
- if (on) {
- remote_state[33] |= kDaikinBitPowerful;
- // Powerful & Quiet mode being on are mutually exclusive.
- setQuiet(false);
- } else {
- remote_state[33] &= ~kDaikinBitPowerful;
- }
-}
-
-bool IRDaikin2::getPowerful() { return remote_state[33] & kDaikinBitPowerful; }
-
-void IRDaikin2::setPurify(const bool on) {
- if (on)
- remote_state[36] |= kDaikin2BitPurify;
- else
- remote_state[36] &= ~kDaikin2BitPurify;
-}
-
-bool IRDaikin2::getPurify() { return remote_state[36] & kDaikin2BitPurify; }
-
-// Convert a standard A/C mode into its native mode.
-uint8_t IRDaikin2::convertMode(const stdAc::opmode_t mode) {
- return IRDaikinESP::convertMode(mode);
-}
-
-// Convert a standard A/C Fan speed into its native fan speed.
-uint8_t IRDaikin2::convertFan(const stdAc::fanspeed_t speed) {
- return IRDaikinESP::convertFan(speed);
-}
-
-// Convert a standard A/C vertical swing into its native version.
-uint8_t IRDaikin2::convertSwingV(const stdAc::swingv_t position) {
- switch (position) {
- case stdAc::swingv_t::kHighest:
- case stdAc::swingv_t::kHigh:
- case stdAc::swingv_t::kMiddle:
- case stdAc::swingv_t::kLow:
- case stdAc::swingv_t::kLowest:
- return (uint8_t)position + kDaikin2SwingVHigh;
- default:
- return kDaikin2SwingVAuto;
- }
-}
-
-// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRDaikin2::toString() {
- String result = "";
-#else // ARDUINO
-std::string IRDaikin2::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kDaikinAuto:
- result += F(" (AUTO)");
- break;
- case kDaikinCool:
- result += F(" (COOL)");
- break;
- case kDaikinHeat:
- result += F(" (HEAT)");
- break;
- case kDaikinDry:
- result += F(" (DRY)");
- break;
- case kDaikinFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kDaikinFanAuto:
- result += F(" (Auto)");
- break;
- case kDaikinFanQuiet:
- result += F(" (Quiet)");
- break;
- case kDaikinFanMin:
- result += F(" (Min)");
- break;
- case kDaikinFanMax:
- result += F(" (Max)");
- break;
- }
- result += F(", Swing (V): ");
- result += uint64ToString(getSwingVertical());
- switch (getSwingVertical()) {
- case kDaikin2SwingVHigh:
- result += F(" (Highest)");
- break;
- case 2:
- case 3:
- case 4:
- case 5:
- break;
- case kDaikin2SwingVLow:
- result += F(" (Lowest)");
- break;
- case kDaikin2SwingVBreeze:
- result += F(" (Breeze)");
- break;
- case kDaikin2SwingVCirculate:
- result += F(" (Circulate)");
- break;
- case kDaikin2SwingVAuto:
- result += F(" (Auto)");
- break;
- default:
- result += F(" (Unknown)");
- }
- result += F(", Swing (H): ");
- result += uint64ToString(getSwingHorizontal());
- switch (getSwingHorizontal()) {
- case kDaikin2SwingHAuto:
- result += F(" (Auto)");
- break;
- case kDaikin2SwingHSwing:
- result += F(" (Swing)");
- break;
- }
- result += F(", Clock: ");
- result += IRDaikinESP::renderTime(getCurrentTime());
- result += F(", On Time: ");
- if (getOnTimerEnabled())
- result += IRDaikinESP::renderTime(getOnTime());
- else
- result += F("Off");
- result += F(", Off Time: ");
- if (getOffTimerEnabled())
- result += IRDaikinESP::renderTime(getOffTime());
- else
- result += F("Off");
- result += F(", Sleep Time: ");
- if (getSleepTimerEnabled())
- result += IRDaikinESP::renderTime(getSleepTime());
- else
- result += F("Off");
- result += F(", Beep: ");
- result += uint64ToString(getBeep());
- switch (getBeep()) {
- case kDaikinBeepLoud:
- result += F(" (Loud)");
- break;
- case kDaikinBeepQuiet:
- result += F(" (Quiet)");
- break;
- case kDaikinBeepOff:
- result += F(" (Off)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Light: ");
- result += uint64ToString(getLight());
- switch (getLight()) {
- case kDaikinLightBright:
- result += F(" (Bright)");
- break;
- case kDaikinLightDim:
- result += F(" (Dim)");
- break;
- case kDaikinLightOff:
- result += F(" (Off)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Mold: ");
- result += (getMold() ? F("On") : F("Off"));
- result += F(", Clean: ");
- result += (getClean() ? F("On") : F("Off"));
- result += F(", Fresh Air: ");
- if (getFreshAir())
- result += (getFreshAirHigh() ? "High" : "On");
- else
- result += F("Off");
- result += F(", Eye: ");
- result += (getEye() ? F("On") : F("Off"));
- result += F(", Eye Auto: ");
- result += (getEyeAuto() ? F("On") : F("Off"));
- result += F(", Quiet: ");
- result += (getQuiet() ? F("On") : F("Off"));
- result += F(", Powerful: ");
- result += (getPowerful() ? F("On") : F("Off"));
- result += ", Purify: ";
- result += (getPurify() ? F("On") : F("Off"));
- result += F(", Econo: ");
- result += (getEcono() ? F("On") : F("Off"));
- return result;
-}
-
-#if DECODE_DAIKIN2
-// Decode the supplied Daikin2 A/C message.
-// Args:
-// results: Ptr to the data to decode and where to store the decode result.
-// nbits: Nr. of bits to expect in the data portion. (kDaikin2Bits)
-// strict: Flag to indicate if we strictly adhere to the specification.
-// Returns:
-// boolean: True if it can decode it, false if it can't.
-//
-// Supported devices:
-// - Daikin FTXZ25NV1B, FTXZ35NV1B, FTXZ50NV1B Aircon
-// - Daikin ARC477A1 remote
-//
-// Status: BETA / Work as expected.
-//
-// Ref:
-// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
-bool IRrecv::decodeDaikin2(decode_results *results, uint16_t nbits,
- bool strict) {
- if (results->rawlen < 2 * (nbits + kHeader + kFooter) + kHeader - 1)
- return false;
-
- // Compliance
- if (strict && nbits != kDaikin2Bits) return false;
-
- uint16_t offset = kStartOffset;
- uint16_t dataBitsSoFar = 0;
- uint16_t i = 0;
- match_result_t data_result;
- uint8_t sectionSize[kDaikin2Sections] = {kDaikin2Section1Length,
- kDaikin2Section2Length};
-
- // Leader
- if (!matchMark(results->rawbuf[offset++], kDaikin2LeaderMark,
- kDaikin2Tolerance)) return false;
- if (!matchSpace(results->rawbuf[offset++], kDaikin2LeaderSpace,
- kDaikin2Tolerance)) return false;
-
- // Sections
- // Keep reading bytes until we either run out of section or state to fill.
- for (uint8_t section = 0, pos = 0; section < kDaikin2Sections;
- section++) {
- pos += sectionSize[section];
-
- // Section Header
- if (!matchMark(results->rawbuf[offset++], kDaikin2HdrMark,
- kDaikin2Tolerance)) return false;
- if (!matchSpace(results->rawbuf[offset++], kDaikin2HdrSpace,
- kDaikin2Tolerance)) return false;
-
- // Section Data
- for (; offset <= results->rawlen - 16 && i < pos;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- // Read in a byte at a time.
- data_result =
- matchData(&(results->rawbuf[offset]), 8, kDaikin2BitMark,
- kDaikin2OneSpace, kDaikin2BitMark,
- kDaikin2ZeroSpace, kDaikin2Tolerance, kMarkExcess, false);
- if (data_result.success == false) break; // Fail
- results->state[i] = (uint8_t)data_result.data;
- }
-
- // Section Footer
- if (!matchMark(results->rawbuf[offset++], kDaikin2BitMark,
- kDaikin2Tolerance)) return false;
- if (section < kDaikin2Sections - 1) { // Inter-section gaps.
- if (!matchSpace(results->rawbuf[offset++], kDaikin2Gap,
- kDaikin2Tolerance)) return false;
- } else { // Last section / End of message gap.
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kDaikin2Gap,
- kDaikin2Tolerance)) return false;
- }
- }
-
- // Compliance
- if (strict) {
- // Re-check we got the correct size/length due to the way we read the data.
- if (dataBitsSoFar != kDaikin2Bits) return false;
- // Validate the checksum.
- if (!IRDaikin2::validChecksum(results->state)) return false;
- }
-
- // Success
- results->decode_type = DAIKIN2;
- results->bits = dataBitsSoFar;
- // No need to record the state as we stored it as we decoded it.
- // As we use result->state, we don't record value, address, or command as it
- // is a union data type.
- return true;
-}
-#endif // DECODE_DAIKIN2
-
-#if SEND_DAIKIN216
-// Send a Daikin 216 bit A/C message.
-//
-// Args:
-// data: An array of kDaikin216StateLength bytes containing the IR command.
-//
-// Status: Alpha/Untested on a real device.
-//
-// Supported devices:
-// - Daikin ARC433B69 remote.
-//
-// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/689
-// https://github.com/danny-source/Arduino_DY_IRDaikin
-void IRsend::sendDaikin216(const unsigned char data[], const uint16_t nbytes,
- const uint16_t repeat) {
- if (nbytes < kDaikin216Section1Length)
- return; // Not enough bytes to send a partial message.
-
- for (uint16_t r = 0; r <= repeat; r++) {
- // Section #1
- sendGeneric(kDaikin216HdrMark, kDaikin216HdrSpace, kDaikin216BitMark,
- kDaikin216OneSpace, kDaikin216BitMark, kDaikin216ZeroSpace,
- kDaikin216BitMark, kDaikin216Gap, data,
- kDaikin216Section1Length,
- kDaikin216Freq, false, 0, kDutyDefault);
- // Section #2
- sendGeneric(kDaikin216HdrMark, kDaikin216HdrSpace, kDaikin216BitMark,
- kDaikin216OneSpace, kDaikin216BitMark, kDaikin216ZeroSpace,
- kDaikin216BitMark, kDaikin216Gap,
- data + kDaikin216Section1Length,
- nbytes - kDaikin216Section1Length,
- kDaikin216Freq, false, 0, kDutyDefault);
- }
-}
-#endif // SEND_DAIKIN216
-
-// Class for handling Daikin 216 bit / 27 byte A/C messages.
-//
-// Code by crankyoldgit.
-//
-// Supported Remotes: Daikin ARC433B69 remote
-//
-// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/689
-// https://github.com/danny-source/Arduino_DY_IRDaikin
-IRDaikin216::IRDaikin216(uint16_t pin) : _irsend(pin) { stateReset(); }
-
-void IRDaikin216::begin() { _irsend.begin(); }
-
-#if SEND_DAIKIN216
-void IRDaikin216::send(const uint16_t repeat) {
- checksum();
- _irsend.sendDaikin216(remote_state, kDaikin216StateLength, repeat);
-}
-#endif // SEND_DAIKIN216
-
-// Verify the checksum is valid for a given state.
-// Args:
-// state: The array to verify the checksum of.
-// length: The size of the state.
-// Returns:
-// A boolean.
-bool IRDaikin216::validChecksum(uint8_t state[], const uint16_t length) {
- // Validate the checksum of section #1.
- if (length <= kDaikin216Section1Length - 1 ||
- state[kDaikin216Section1Length - 1] != sumBytes(
- state, kDaikin216Section1Length - 1))
- return false;
- // Validate the checksum of section #2 (a.k.a. the rest)
- if (length <= kDaikin216Section1Length + 1 ||
- state[length - 1] != sumBytes(state + kDaikin216Section1Length,
- length - kDaikin216Section1Length - 1))
- return false;
- return true;
-}
-
-// Calculate and set the checksum values for the internal state.
-void IRDaikin216::checksum() {
- remote_state[kDaikin216Section1Length - 1] = sumBytes(
- remote_state, kDaikin216Section1Length - 1);
- remote_state[kDaikin216StateLength - 1] = sumBytes(
- remote_state + kDaikin216Section1Length, kDaikin216Section2Length - 1);
-}
-
-void IRDaikin216::stateReset() {
- for (uint8_t i = 0; i < kDaikin216StateLength; i++) remote_state[i] = 0x00;
- remote_state[0] = 0x11;
- remote_state[1] = 0xDA;
- remote_state[2] = 0x27;
- remote_state[3] = 0xF0;
- // remote_state[7] is a checksum byte, it will be set by checksum().
- remote_state[8] = 0x11;
- remote_state[9] = 0xDA;
- remote_state[10] = 0x27;
- remote_state[23] = 0xC0;
- // remote_state[26] is a checksum byte, it will be set by checksum().
-}
-
-uint8_t *IRDaikin216::getRaw() {
- checksum(); // Ensure correct settings before sending.
- return remote_state;
-}
-
-void IRDaikin216::setRaw(const uint8_t new_code[]) {
- for (uint8_t i = 0; i < kDaikin216StateLength; i++)
- remote_state[i] = new_code[i];
-}
-
-
-void IRDaikin216::on() {
- remote_state[kDaikin216BytePower] |= kDaikinBitPower;
-}
-
-void IRDaikin216::off() {
- remote_state[kDaikin216BytePower] &= ~kDaikinBitPower;
-}
-
-void IRDaikin216::setPower(const bool state) {
- if (state)
- on();
- else
- off();
-}
-
-bool IRDaikin216::getPower() {
- return remote_state[kDaikin216BytePower] & kDaikinBitPower;
-}
-
-uint8_t IRDaikin216::getMode() {
- return (remote_state[kDaikin216ByteMode] & kDaikin216MaskMode) >> 4;
-}
-
-void IRDaikin216::setMode(const uint8_t mode) {
- switch (mode) {
- case kDaikinAuto:
- case kDaikinCool:
- case kDaikinHeat:
- case kDaikinFan:
- case kDaikinDry:
- remote_state[kDaikin216ByteMode] &= ~kDaikin216MaskMode;
- remote_state[kDaikin216ByteMode] |= (mode << 4);
- break;
- default:
- this->setMode(kDaikinAuto);
- }
-}
-
-// Convert a standard A/C mode into its native mode.
-uint8_t IRDaikin216::convertMode(const stdAc::opmode_t mode) {
- return IRDaikinESP::convertMode(mode);
-}
-
-// Set the temp in deg C
-void IRDaikin216::setTemp(const uint8_t temp) {
- uint8_t degrees = std::max(temp, kDaikinMinTemp);
- degrees = std::min(degrees, kDaikinMaxTemp);
- remote_state[kDaikin216ByteTemp] &= ~kDaikin216MaskTemp;
- remote_state[kDaikin216ByteTemp] |= (degrees << 1);
-}
-
-uint8_t IRDaikin216::getTemp(void) {
- return (remote_state[kDaikin216ByteTemp] & kDaikin216MaskTemp) >> 1;
-}
-
-// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet
-void IRDaikin216::setFan(const uint8_t fan) {
- // Set the fan speed bits, leave low 4 bits alone
- uint8_t fanset;
- if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto)
- fanset = fan;
- else if (fan < kDaikinFanMin || fan > kDaikinFanMax)
- fanset = kDaikinFanAuto;
- else
- fanset = 2 + fan;
- remote_state[kDaikin216ByteFan] &= ~kDaikin216MaskFan;
- remote_state[kDaikin216ByteFan] |= (fanset << 4);
-}
-
-uint8_t IRDaikin216::getFan() {
- uint8_t fan = remote_state[kDaikin216ByteFan] >> 4;
- if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2;
- return fan;
-}
-
-// Convert a standard A/C Fan speed into its native fan speed.
-uint8_t IRDaikin216::convertFan(const stdAc::fanspeed_t speed) {
- return IRDaikinESP::convertFan(speed);
-}
-
-void IRDaikin216::setSwingVertical(const bool on) {
- if (on)
- remote_state[kDaikin216ByteSwingV] |= kDaikin216MaskSwingV;
- else
- remote_state[kDaikin216ByteSwingV] &= ~kDaikin216MaskSwingV;
-}
-
-bool IRDaikin216::getSwingVertical(void) {
- return remote_state[kDaikin216ByteSwingV] & kDaikin216MaskSwingV;
-}
-
-void IRDaikin216::setSwingHorizontal(const bool on) {
- if (on)
- remote_state[kDaikin216ByteSwingH] |= kDaikin216MaskSwingH;
- else
- remote_state[kDaikin216ByteSwingH] &= ~kDaikin216MaskSwingH;
-}
-
-bool IRDaikin216::getSwingHorizontal(void) {
- return remote_state[kDaikin216ByteSwingH] & kDaikin216MaskSwingH;
-}
-
-// This is a horrible hack till someone works out the quiet mode bit.
-void IRDaikin216::setQuiet(const bool on) {
- if (on)
- this->setFan(kDaikinFanQuiet);
- else if (this->getFan() == kDaikinFanQuiet)
- this->setFan(kDaikinFanAuto);
-}
-
-// This is a horrible hack till someone works out the quiet mode bit.
-bool IRDaikin216::getQuiet(void) {
- return this->getFan() == kDaikinFanQuiet;
-}
-
-// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRDaikin216::toString() {
- String result = "";
-#else // ARDUINO
-std::string IRDaikin216::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (this->getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(this->getMode());
- switch (getMode()) {
- case kDaikinAuto:
- result += F(" (AUTO)");
- break;
- case kDaikinCool:
- result += F(" (COOL)");
- break;
- case kDaikinHeat:
- result += F(" (HEAT)");
- break;
- case kDaikinDry:
- result += F(" (DRY)");
- break;
- case kDaikinFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(this->getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(this->getFan());
- switch (this->getFan()) {
- case kDaikinFanAuto:
- result += F(" (AUTO)");
- break;
- case kDaikinFanQuiet:
- result += F(" (QUIET)");
- break;
- case kDaikinFanMin:
- result += F(" (MIN)");
- break;
- case kDaikinFanMax:
- result += F(" (MAX)");
- break;
- }
- result += F(", Swing (Horizontal): ");
- result += this->getSwingHorizontal() ? F("On") : F("Off");
- result += F(", Swing (Vertical): ");
- result += this->getSwingVertical() ? F("On") : F("Off");
- result += F(", Quiet: ");
- result += (getQuiet() ? F("On") : F("Off"));
- return result;
-}
-
-#if DECODE_DAIKIN216
-// Decode the supplied Daikin 216 bit A/C message.
-// Args:
-// results: Ptr to the data to decode and where to store the decode result.
-// nbits: Nr. of bits to expect in the data portion. (kDaikin216Bits)
-// strict: Flag to indicate if we strictly adhere to the specification.
-// Returns:
-// boolean: True if it can decode it, false if it can't.
-//
-// Supported devices:
-// - Daikin ARC433B69 remote.
-//
-// Status: BETA / Should be working.
-//
-// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/689
-// https://github.com/danny-source/Arduino_DY_IRDaikin
-bool IRrecv::decodeDaikin216(decode_results *results, const uint16_t nbits,
- const bool strict) {
- if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1)
- return false;
-
- // Compliance
- if (strict && nbits != kDaikin216Bits) return false;
-
- uint16_t offset = kStartOffset;
- uint16_t dataBitsSoFar = 0;
- uint16_t i = 0;
- match_result_t data_result;
- uint8_t sectionSize[kDaikin216Sections] = {kDaikin216Section1Length,
- kDaikin216Section2Length};
-
- // Sections
- // Keep reading bytes until we either run out of section or state to fill.
- for (uint8_t section = 0, pos = 0; section < kDaikin216Sections;
- section++) {
- pos += sectionSize[section];
-
- // Section Header
- if (!matchMark(results->rawbuf[offset++], kDaikin216HdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kDaikin2HdrSpace)) return false;
-
- // Section Data
- for (; offset <= results->rawlen - 16 && i < pos;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- // Read in a byte at a time.
- data_result =
- matchData(&(results->rawbuf[offset]), 8, kDaikin216BitMark,
- kDaikin216OneSpace, kDaikin216BitMark,
- kDaikin216ZeroSpace, kTolerance, kMarkExcess, false);
- if (data_result.success == false) break; // Fail
- results->state[i] = (uint8_t)data_result.data;
- }
-
- // Section Footer
- if (!matchMark(results->rawbuf[offset++], kDaikin216BitMark)) return false;
- if (section < kDaikin216Sections - 1) { // Inter-section gaps.
- if (!matchSpace(results->rawbuf[offset++], kDaikin216Gap)) return false;
- } else { // Last section / End of message gap.
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kDaikin216Gap)) return false;
- }
- }
-
- // Compliance
- if (strict) {
- // Re-check we got the correct size/length due to the way we read the data.
- if (dataBitsSoFar != kDaikin216Bits) return false;
- // Validate the checksum.
- if (!IRDaikin216::validChecksum(results->state)) return false;
- }
-
- // Success
- results->decode_type = decode_type_t::DAIKIN216;
- results->bits = dataBitsSoFar;
- // No need to record the state as we stored it as we decoded it.
- // As we use result->state, we don't record value, address, or command as it
- // is a union data type.
- return true;
-}
-#endif // DECODE_DAIKIN216
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.h b/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.h
deleted file mode 100644
index 038e8edd9..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.h
+++ /dev/null
@@ -1,444 +0,0 @@
-// Copyright 2016 sillyfrog
-// Copyright 2017 sillyfrog, crankyoldgit
-// Copyright 2018-2019 crankyoldgit
-#ifndef IR_DAIKIN_H_
-#define IR_DAIKIN_H_
-
-#ifndef UNIT_TEST
-#include
-#else
-#include
-#endif
-#include "IRrecv.h"
-#include "IRremoteESP8266.h"
-#include "IRsend.h"
-#ifdef UNIT_TEST
-#include "IRsend_test.h"
-#endif
-
-// DDDDD AAA IIIII KK KK IIIII NN NN
-// DD DD AAAAA III KK KK III NNN NN
-// DD DD AA AA III KKKK III NN N NN
-// DD DD AAAAAAA III KK KK III NN NNN
-// DDDDDD AA AA IIIII KK KK IIIII NN NN
-
-/*
- Daikin AC map
- byte 6=
- b4:Comfort
- byte 7= checksum of the first part (and last byte before a 29ms pause)
- byte 13=Current time, mins past midnight, low bits
- byte 14
- b0-b3=Current time, mins past midnight, high bits
- byte 15= checksum of the second part (and last byte before a 29ms pause)
- byte 21=mode
- b7 = 0
- b6+b5+b4 = Mode
- Modes: b6+b5+b4
- 011 = Cool
- 100 = Heat (temp 23)
- 110 = FAN (temp not shown, but 25)
- 000 = Fully Automatic (temp 25)
- 010 = DRY (temp 0xc0 = 96 degrees c)
- b3 = 1
- b2 = OFF timer set
- b1 = ON timer set
- b0 = Air Conditioner ON
- byte 22=temp*2 (Temp should be between 10 - 32)
- byte 24=Fan
- FAN control
- b7+b6+b5+b4 = Fan speed
- Fan: b7+b6+b5+b4
- 0Ć3 = 1 bar
- 0Ć4 = 2 bar
- 0Ć5 = 3 bar
- 0Ć6 = 4 bar
- 0Ć7 = 5 bar
- 0xa = Auto
- 0xb = Quite
- b3+b2+b1+b0 = Swing control up/down
- Swing control up/down:
- 0000 = Swing up/down off
- 1111 = Swing up/down on
- byte 25
- Swing control left/right:
- 0000 = Swing left/right off
- 1111 = Swing left/right on
- byte 26=On timer mins past midnight, low bits
- byte 27
- b0-b3=On timer mins past midnight, high bits
- b4-b7=Off timer mins past midnight, low bits
- byte 28=Off timer mins past midnight, high bits
- byte 29=Aux -> Powerful (bit 1), Silent (bit 5)
- byte 32=Aux2
- b1: Sensor
- b2: Econo mode
- b7: Intelligent eye on
- byte 33=Aux3
- b1: Mold Proof
- byte 34= checksum of the third part
-*/
-
-// Constants
-const uint8_t kDaikinAuto = 0b000;
-const uint8_t kDaikinDry = 0b010;
-const uint8_t kDaikinCool = 0b011;
-const uint8_t kDaikinHeat = 0b100;
-const uint8_t kDaikinFan = 0b110;
-const uint8_t kDaikinMinTemp = 10; // Celsius
-const uint8_t kDaikinMaxTemp = 32; // Celsius
-const uint8_t kDaikinFanMin = 1;
-const uint8_t kDaikinFanMax = 5;
-const uint8_t kDaikinFanAuto = 0b1010;
-const uint8_t kDaikinFanQuiet = 0b1011;
-const uint16_t kDaikinHeaderLength = 5;
-const uint8_t kDaikinSections = 3;
-const uint8_t kDaikinSection1Length = 8;
-const uint8_t kDaikinSection2Length = 8;
-const uint8_t kDaikinSection3Length =
- kDaikinStateLength - kDaikinSection1Length - kDaikinSection2Length;
-const uint8_t kDaikinByteComfort = 6;
-const uint8_t kDaikinByteChecksum1 = 7;
-const uint8_t kDaikinBitComfort = 0b00010000;
-const uint8_t kDaikinByteClockMinsLow = 13;
-const uint8_t kDaikinByteClockMinsHigh = 14;
-const uint8_t kDaikinByteChecksum2 = 15;
-const uint8_t kDaikinBytePower = 21;
-const uint8_t kDaikinBitPower = 0b00000001;
-const uint8_t kDaikinByteTemp = 22;
-const uint8_t kDaikinByteFan = 24;
-const uint8_t kDaikinByteSwingH = 25;
-const uint8_t kDaikinByteOnTimerMinsLow = 26;
-const uint8_t kDaikinByteOnTimerMinsHigh = 27;
-const uint8_t kDaikinByteOffTimerMinsLow = kDaikinByteOnTimerMinsHigh;
-const uint8_t kDaikinByteOffTimerMinsHigh = 28;
-const uint8_t kDaikinBytePowerful = 29;
-const uint8_t kDaikinBitPowerful = 0b00000001;
-const uint8_t kDaikinByteSilent = kDaikinBytePowerful;
-const uint8_t kDaikinBitSilent = 0b00100000;
-const uint8_t kDaikinByteSensor = 32;
-const uint8_t kDaikinBitSensor = 0b00000010;
-const uint8_t kDaikinByteEcono = kDaikinByteSensor;
-const uint8_t kDaikinBitEcono = 0b00000100;
-const uint8_t kDaikinByteEye = kDaikinByteSensor;
-const uint8_t kDaikinBitEye = 0b10000000;
-const uint8_t kDaikinByteMold = 33;
-const uint8_t kDaikinBitMold = 0b00000010;
-const uint8_t kDaikinByteOffTimer = kDaikinBytePower;
-const uint8_t kDaikinBitOffTimer = 0b00000100;
-const uint8_t kDaikinByteOnTimer = kDaikinByteOffTimer;
-const uint8_t kDaikinBitOnTimer = 0b00000010;
-const uint8_t kDaikinByteChecksum3 = kDaikinStateLength - 1;
-const uint16_t kDaikinUnusedTime = 0x600;
-const uint8_t kDaikinBeepQuiet = 1;
-const uint8_t kDaikinBeepLoud = 2;
-const uint8_t kDaikinBeepOff = 3;
-const uint8_t kDaikinLightBright = 1;
-const uint8_t kDaikinLightDim = 2;
-const uint8_t kDaikinLightOff = 3;
-const uint8_t kDaikinCurBit = kDaikinStateLength;
-const uint8_t kDaikinCurIndex = kDaikinStateLength + 1;
-const uint8_t kDaikinTolerance = 35;
-const uint16_t kDaikinMarkExcess = kMarkExcess;
-const uint16_t kDaikinHdrMark = 3650; // kDaikinBitMark * 8
-const uint16_t kDaikinHdrSpace = 1623; // kDaikinBitMark * 4
-const uint16_t kDaikinBitMark = 428;
-const uint16_t kDaikinZeroSpace = 428;
-const uint16_t kDaikinOneSpace = 1280;
-const uint16_t kDaikinGap = 29000;
-// Note bits in each octet swapped so can be sent as a single value
-const uint64_t kDaikinFirstHeader64 =
- 0b1101011100000000000000001100010100000000001001111101101000010001;
-
-// Another variant of the protocol for the Daikin ARC477A1 remote.
-const uint16_t kDaikin2Freq = 36700; // Modulation Frequency in Hz.
-const uint16_t kDaikin2LeaderMark = 10024;
-const uint16_t kDaikin2LeaderSpace = 25180;
-const uint16_t kDaikin2Gap = kDaikin2LeaderMark + kDaikin2LeaderSpace;
-const uint16_t kDaikin2HdrMark = 3500;
-const uint16_t kDaikin2HdrSpace = 1728;
-const uint16_t kDaikin2BitMark = 460;
-const uint16_t kDaikin2OneSpace = 1270;
-const uint16_t kDaikin2ZeroSpace = 420;
-const uint16_t kDaikin2Sections = 2;
-const uint16_t kDaikin2Section1Length = 20;
-const uint16_t kDaikin2Section2Length = 19;
-const uint8_t kDaikin2Tolerance = kTolerance + 5;
-
-const uint8_t kDaikin2BitSleepTimer = 0b00100000;
-const uint8_t kDaikin2BitPurify = 0b00010000;
-const uint8_t kDaikin2BitEye = 0b00000010;
-const uint8_t kDaikin2BitEyeAuto = 0b10000000;
-const uint8_t kDaikin2BitMold = 0b00001000;
-const uint8_t kDaikin2BitClean = 0b00100000;
-const uint8_t kDaikin2BitFreshAir = 0b00000001;
-const uint8_t kDaikin2BitFreshAirHigh = 0b10000000;
-const uint8_t kDaikin2BitPower = 0b10000000;
-const uint8_t kDaikin2LightMask = 0b00110000;
-const uint8_t kDaikin2BeepMask = 0b11000000;
-const uint8_t kDaikin2SwingVHigh = 0x1;
-const uint8_t kDaikin2SwingVLow = 0x6;
-const uint8_t kDaikin2SwingVBreeze = 0xC;
-const uint8_t kDaikin2SwingVCirculate = 0xD;
-const uint8_t kDaikin2SwingVAuto = 0xE;
-const uint8_t kDaikin2SwingHAuto = 0xBE;
-const uint8_t kDaikin2SwingHSwing = 0xBF;
-const uint8_t kDaikin2MinCoolTemp = 18; // Min temp (in C) when in Cool mode.
-
-// Another variant of the protocol for the Daikin ARC433B69 remote.
-const uint16_t kDaikin216Freq = 38000; // Modulation Frequency in Hz.
-const uint16_t kDaikin216HdrMark = 3400;
-const uint16_t kDaikin216HdrSpace = 1800;
-const uint16_t kDaikin216BitMark = 380;
-const uint16_t kDaikin216OneSpace = 1350;
-const uint16_t kDaikin216ZeroSpace = 480;
-const uint16_t kDaikin216Gap = 29650;
-const uint16_t kDaikin216Sections = 2;
-const uint16_t kDaikin216Section1Length = 8;
-const uint16_t kDaikin216Section2Length = kDaikin216StateLength -
- kDaikin216Section1Length;
-const uint8_t kDaikin216BytePower = 13;
-const uint8_t kDaikin216ByteMode = kDaikin216BytePower;
-const uint8_t kDaikin216MaskMode = 0b01110000;
-const uint8_t kDaikin216ByteTemp = 14;
-const uint8_t kDaikin216MaskTemp = 0b01111110;
-const uint8_t kDaikin216ByteFan = 16;
-const uint8_t kDaikin216MaskFan = 0b11110000;
-const uint8_t kDaikin216ByteSwingV = 16;
-const uint8_t kDaikin216MaskSwingV = 0b00001111;
-const uint8_t kDaikin216ByteSwingH = 17;
-const uint8_t kDaikin216MaskSwingH = kDaikin216MaskSwingV;
-
-
-// Legacy defines.
-#define DAIKIN_COOL kDaikinCool
-#define DAIKIN_HEAT kDaikinHeat
-#define DAIKIN_FAN kDaikinFan
-#define DAIKIN_AUTO kDaikinAuto
-#define DAIKIN_DRY kDaikinDry
-#define DAIKIN_MIN_TEMP kDaikinMinTemp
-#define DAIKIN_MAX_TEMP kDaikinMaxTemp
-#define DAIKIN_FAN_MIN kDaikinFanMin
-#define DAIKIN_FAN_MAX kDaikinFanMax
-#define DAIKIN_FAN_AUTO kDaikinFanAuto
-#define DAIKIN_FAN_QUIET kDaikinFanQuiet
-
-class IRDaikinESP {
- public:
- explicit IRDaikinESP(uint16_t pin);
-
-#if SEND_DAIKIN
- void send(const uint16_t repeat = kDaikinDefaultRepeat);
-#endif
- void begin(void);
- void on(void);
- void off(void);
- void setPower(const bool on);
- bool getPower(void);
- void setTemp(const uint8_t temp);
- uint8_t getTemp();
- void setFan(const uint8_t fan);
- uint8_t getFan(void);
- void setMode(const uint8_t mode);
- uint8_t getMode(void);
- void setSwingVertical(const bool on);
- bool getSwingVertical(void);
- void setSwingHorizontal(const bool on);
- bool getSwingHorizontal(void);
- bool getQuiet(void);
- void setQuiet(const bool on);
- bool getPowerful(void);
- void setPowerful(const bool on);
- void setSensor(const bool on);
- bool getSensor(void);
- void setEcono(const bool on);
- bool getEcono(void);
- void setEye(const bool on);
- bool getEye(void);
- void setMold(const bool on);
- bool getMold(void);
- void setComfort(const bool on);
- bool getComfort(void);
- void enableOnTimer(const uint16_t starttime);
- void disableOnTimer(void);
- uint16_t getOnTime(void);
- bool getOnTimerEnabled();
- void enableOffTimer(const uint16_t endtime);
- void disableOffTimer(void);
- uint16_t getOffTime(void);
- bool getOffTimerEnabled(void);
- void setCurrentTime(const uint16_t mins_since_midnight);
- uint16_t getCurrentTime(void);
- uint8_t* getRaw(void);
- void setRaw(const uint8_t new_code[],
- const uint16_t length = kDaikinStateLength);
- static bool validChecksum(uint8_t state[],
- const uint16_t length = kDaikinStateLength);
- static uint8_t convertMode(const stdAc::opmode_t mode);
- static uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
- String toString(void);
- static String renderTime(const uint16_t timemins);
-#else
- std::string toString(void);
- static std::string renderTime(const uint16_t timemins);
-#endif
-#ifndef UNIT_TEST
-
- private:
- IRsend _irsend;
-#else
- IRsendTest _irsend;
-#endif
- // # of bytes per command
- uint8_t remote[kDaikinStateLength];
- void stateReset(void);
- void checksum(void);
-};
-
-// Class to emulate a Daikin ARC477A1 remote.
-class IRDaikin2 {
- public:
- explicit IRDaikin2(uint16_t pin);
-
-#if SEND_DAIKIN2
- void send(const uint16_t repeat = kDaikin2DefaultRepeat);
-#endif
- void begin();
- void on();
- void off();
- void setPower(const bool state);
- bool getPower();
- void setTemp(const uint8_t temp);
- uint8_t getTemp();
- void setFan(const uint8_t fan);
- uint8_t getFan();
- uint8_t getMode();
- void setMode(const uint8_t mode);
- void setSwingVertical(const uint8_t position);
- uint8_t getSwingVertical();
- void setSwingHorizontal(const uint8_t position);
- uint8_t getSwingHorizontal();
- bool getQuiet();
- void setQuiet(const bool on);
- bool getPowerful();
- void setPowerful(const bool on);
- void setSensor(const bool on);
- bool getSensor();
- void setEcono(const bool on);
- bool getEcono();
- void setEye(const bool on);
- bool getEye();
- void setEyeAuto(const bool on);
- bool getEyeAuto();
- void setPurify(const bool on);
- bool getPurify();
- void setMold(const bool on);
- bool getMold();
- void enableOnTimer(const uint16_t starttime);
- void disableOnTimer();
- uint16_t getOnTime();
- bool getOnTimerEnabled();
- void enableSleepTimer(const uint16_t sleeptime);
- void disableSleepTimer();
- uint16_t getSleepTime();
- bool getSleepTimerEnabled();
- void enableOffTimer(const uint16_t endtime);
- void disableOffTimer();
- uint16_t getOffTime();
- bool getOffTimerEnabled();
- void setCurrentTime(const uint16_t time);
- uint16_t getCurrentTime();
- void setBeep(const uint8_t beep);
- uint8_t getBeep();
- void setLight(const uint8_t light);
- uint8_t getLight();
- void setClean(const bool on);
- bool getClean();
- void setFreshAir(const bool on);
- bool getFreshAir();
- void setFreshAirHigh(const bool on);
- bool getFreshAirHigh();
- uint8_t* getRaw();
- void setRaw(const uint8_t new_code[]);
- uint32_t getCommand();
- void setCommand(uint32_t value);
- static bool validChecksum(uint8_t state[],
- const uint16_t length = kDaikin2StateLength);
- static uint8_t convertMode(const stdAc::opmode_t mode);
- static uint8_t convertFan(const stdAc::fanspeed_t speed);
- uint8_t convertSwingV(const stdAc::swingv_t position);
-#ifdef ARDUINO
- String toString();
- static String renderTime(uint16_t timemins);
-#else
- std::string toString();
- static std::string renderTime(uint16_t timemins);
-#endif
-#ifndef UNIT_TEST
-
- private:
- IRsend _irsend;
-#else
- IRsendTest _irsend;
-#endif
- // # of bytes per command
- uint8_t remote_state[kDaikin2StateLength];
- void stateReset();
- void checksum();
- void clearOnTimerFlag();
- void clearSleepTimerFlag();
-};
-
-// Class to emulate a Daikin ARC433B69 remote.
-class IRDaikin216 {
- public:
- explicit IRDaikin216(uint16_t pin);
-
-#if SEND_DAIKIN216
- void send(const uint16_t repeat = kDaikin216DefaultRepeat);
-#endif
- void begin();
- uint8_t* getRaw();
- void setRaw(const uint8_t new_code[]);
- static bool validChecksum(uint8_t state[],
- const uint16_t length = kDaikin216StateLength);
- void on(void);
- void off(void);
- void setPower(const bool on);
- bool getPower(void);
- void setTemp(const uint8_t temp);
- uint8_t getTemp();
- void setMode(const uint8_t mode);
- uint8_t getMode(void);
- static uint8_t convertMode(const stdAc::opmode_t mode);
- void setFan(const uint8_t fan);
- uint8_t getFan(void);
- static uint8_t convertFan(const stdAc::fanspeed_t speed);
- void setSwingVertical(const bool on);
- bool getSwingVertical(void);
- void setSwingHorizontal(const bool on);
- bool getSwingHorizontal(void);
- void setQuiet(const bool on);
- bool getQuiet(void);
-#ifdef ARDUINO
- String toString(void);
- static String renderTime(const uint16_t timemins);
-#else
- std::string toString(void);
- static std::string renderTime(const uint16_t timemins);
-#endif
-#ifndef UNIT_TEST
-
- private:
- IRsend _irsend;
-#else
- IRsendTest _irsend;
-#endif
- // # of bytes per command
- uint8_t remote_state[kDaikin216StateLength];
- void stateReset();
- void checksum();
-};
-
-#endif // IR_DAIKIN_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Electra.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Electra.cpp
deleted file mode 100644
index 0700ab698..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Electra.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2018, 2019 David Conran
-
-#include "IRrecv.h"
-#include "IRsend.h"
-#include "IRutils.h"
-
-// EEEEEEE LL EEEEEEE CCCCC TTTTTTT RRRRRR AAA
-// EE LL EE CC C TTT RR RR AAAAA
-// EEEEE LL EEEEE CC TTT RRRRRR AA AA
-// EE LL EE CC C TTT RR RR AAAAAAA
-// EEEEEEE LLLLLLL EEEEEEE CCCCC TTT RR RR AA AA
-
-// Electra A/C added by crankyoldgit
-//
-// Equipment it seems compatible with:
-// *
-
-// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/527
-// https://github.com/markszabo/IRremoteESP8266/issues/642
-
-// Constants
-const uint16_t kElectraAcHdrMark = 9166;
-const uint16_t kElectraAcBitMark = 646;
-const uint16_t kElectraAcHdrSpace = 4470;
-const uint16_t kElectraAcOneSpace = 1647;
-const uint16_t kElectraAcZeroSpace = 547;
-const uint32_t kElectraAcMessageGap = kDefaultMessageGap; // Just a guess.
-
-#if SEND_ELECTRA_AC
-// Send a Electra message
-//
-// Args:
-// data: Contents of the message to be sent. (Guessing MSBF order)
-// nbits: Nr. of bits of data to be sent. Typically kElectraAcBits.
-// repeat: Nr. of additional times the message is to be sent.
-//
-// Status: Alpha / Needs testing against a real device.
-//
-void IRsend::sendElectraAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) {
- for (uint16_t r = 0; r <= repeat; r++)
- sendGeneric(kElectraAcHdrMark, kElectraAcHdrSpace, kElectraAcBitMark,
- kElectraAcOneSpace, kElectraAcBitMark, kElectraAcZeroSpace,
- kElectraAcBitMark, kElectraAcMessageGap, data, nbytes,
- 38000, // Complete guess of the modulation frequency.
- false, // Send data in LSB order per byte
- 0, 50);
-}
-#endif
-
-#if DECODE_ELECTRA_AC
-// Decode the supplied Electra A/C message.
-//
-// Args:
-// results: Ptr to the data to decode and where to store the decode result.
-// nbits: The number of data bits to expect. Typically kElectraAcBits.
-// strict: Flag indicating if we should perform strict matching.
-// Returns:
-// boolean: True if it can decode it, false if it can't.
-//
-// Status: Beta / Probably works.
-//
-bool IRrecv::decodeElectraAC(decode_results *results, uint16_t nbits,
- bool strict) {
- if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte.
- return false;
-
- if (strict) {
- if (nbits != kElectraAcBits)
- return false; // Not strictly a ELECTRA_AC message.
- }
-
- if (results->rawlen < 2 * nbits + kHeader + kFooter - 1)
- return false; // Can't possibly be a valid ELECTRA_AC message.
-
- uint16_t offset = kStartOffset;
-
- // Message Header
- if (!matchMark(results->rawbuf[offset++], kElectraAcHdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kElectraAcHdrSpace)) return false;
-
- // Data Section
- match_result_t data_result;
- uint16_t dataBitsSoFar = 0;
- // Keep reading bytes until we either run out of section or state to fill.
- for (uint16_t i = 0; offset <= results->rawlen - 16 && i < nbits / 8;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- data_result = matchData(&(results->rawbuf[offset]), 8, kElectraAcBitMark,
- kElectraAcOneSpace, kElectraAcBitMark,
- kElectraAcZeroSpace, kTolerance, 0, false);
- if (data_result.success == false) return false; // Fail
- results->state[i] = data_result.data;
- }
-
- // Message Footer
- if (!matchMark(results->rawbuf[offset++], kElectraAcBitMark)) return false;
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kElectraAcMessageGap))
- return false;
-
- // Compliance
- if (strict) {
- if (dataBitsSoFar != nbits) return false;
- // Verify the checksum.
- if (sumBytes(results->state, (dataBitsSoFar / 8) - 1) !=
- results->state[(dataBitsSoFar / 8) - 1]) return false;
- }
-
- // Success
- results->decode_type = ELECTRA_AC;
- results->bits = dataBitsSoFar;
- // No need to record the state as we stored it as we decoded it.
- // As we use result->state, we don't record value, address, or command as it
- // is a union data type.
- return true;
-}
-#endif // DECODE_ELECTRA_AC
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.cpp
deleted file mode 100644
index de1b97e87..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.cpp
+++ /dev/null
@@ -1,556 +0,0 @@
-// Copyright 2017 Jonny Graham, David Conran
-#include "ir_Fujitsu.h"
-#include
-#ifndef ARDUINO
-#include
-#endif
-#include "IRsend.h"
-#include "IRutils.h"
-
-// Fujitsu A/C support added by Jonny Graham & David Conran
-
-// Equipment it seems compatible with:
-// * Fujitsu ASYG30LFCA with remote AR-RAH2E
-// * Fujitsu AST9RSGCW with remote AR-DB1
-// *
-
-// Ref:
-// These values are based on averages of measurements
-const uint16_t kFujitsuAcHdrMark = 3324;
-const uint16_t kFujitsuAcHdrSpace = 1574;
-const uint16_t kFujitsuAcBitMark = 448;
-const uint16_t kFujitsuAcOneSpace = 1182;
-const uint16_t kFujitsuAcZeroSpace = 390;
-const uint16_t kFujitsuAcMinGap = 8100;
-
-#if SEND_FUJITSU_AC
-// Send a Fujitsu A/C message.
-//
-// Args:
-// data: An array of bytes containing the IR command.
-// nbytes: Nr. of bytes of data in the array. Typically one of:
-// kFujitsuAcStateLength
-// kFujitsuAcStateLength - 1
-// kFujitsuAcStateLengthShort
-// kFujitsuAcStateLengthShort - 1
-// repeat: Nr. of times the message is to be repeated.
-// (Default = kFujitsuAcMinRepeat).
-//
-// Status: BETA / Appears to be working.
-//
-void IRsend::sendFujitsuAC(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
- sendGeneric(kFujitsuAcHdrMark, kFujitsuAcHdrSpace, kFujitsuAcBitMark,
- kFujitsuAcOneSpace, kFujitsuAcBitMark, kFujitsuAcZeroSpace,
- kFujitsuAcBitMark, kFujitsuAcMinGap, data, nbytes, 38, false,
- repeat, 50);
-}
-#endif // SEND_FUJITSU_AC
-
-// Code to emulate Fujitsu A/C IR remote control unit.
-
-// Initialise the object.
-IRFujitsuAC::IRFujitsuAC(uint16_t pin, fujitsu_ac_remote_model_t model)
- : _irsend(pin) {
- setModel(model);
- stateReset();
-}
-
-void IRFujitsuAC::setModel(fujitsu_ac_remote_model_t model) {
- _model = model;
- switch (model) {
- case ARDB1:
- _state_length = kFujitsuAcStateLength - 1;
- _state_length_short = kFujitsuAcStateLengthShort - 1;
- break;
- default:
- _state_length = kFujitsuAcStateLength;
- _state_length_short = kFujitsuAcStateLengthShort;
- }
-}
-
-// Reset the state of the remote to a known good state/sequence.
-void IRFujitsuAC::stateReset() {
- _temp = 24;
- _fanSpeed = kFujitsuAcFanHigh;
- _mode = kFujitsuAcModeCool;
- _swingMode = kFujitsuAcSwingBoth;
- _cmd = kFujitsuAcCmdTurnOn;
- buildState();
-}
-
-// Configure the pin for output.
-void IRFujitsuAC::begin() { _irsend.begin(); }
-
-#if SEND_FUJITSU_AC
-// Send the current desired state to the IR LED.
-void IRFujitsuAC::send(const uint16_t repeat) {
- getRaw();
- _irsend.sendFujitsuAC(remote_state, getStateLength(), repeat);
-}
-#endif // SEND_FUJITSU_AC
-
-void IRFujitsuAC::buildState() {
- remote_state[0] = 0x14;
- remote_state[1] = 0x63;
- remote_state[2] = 0x00;
- remote_state[3] = 0x10;
- remote_state[4] = 0x10;
- bool fullCmd = false;
- switch (_cmd) {
- case kFujitsuAcCmdTurnOff:
- remote_state[5] = 0x02;
- break;
- case kFujitsuAcCmdStepHoriz:
- remote_state[5] = 0x79;
- break;
- case kFujitsuAcCmdStepVert:
- remote_state[5] = 0x6C;
- break;
- default:
- switch (_model) {
- case ARRAH2E:
- remote_state[5] = 0xFE;
- break;
- case ARDB1:
- remote_state[5] = 0xFC;
- break;
- }
- fullCmd = true;
- break;
- }
- if (fullCmd) { // long codes
- uint8_t tempByte = _temp - kFujitsuAcMinTemp;
- // Nr. of bytes in the message after this byte.
- remote_state[6] = _state_length - 7;
-
- remote_state[7] = 0x30;
- remote_state[8] = (_cmd == kFujitsuAcCmdTurnOn) | (tempByte << 4);
- remote_state[9] = _mode | 0 << 4; // timer off
- remote_state[10] = _fanSpeed | _swingMode << 4;
- remote_state[11] = 0; // timerOff values
- remote_state[12] = 0; // timerOff/On values
- remote_state[13] = 0; // timerOn values
- if (_model == ARRAH2E)
- remote_state[14] = 0x20;
- else
- remote_state[14] = 0x00;
-
- uint8_t checksum = 0;
- uint8_t checksum_complement = 0;
- if (_model == ARRAH2E) {
- checksum = sumBytes(remote_state + _state_length_short,
- _state_length - _state_length_short - 1);
- } else if (_model == ARDB1) {
- checksum = sumBytes(remote_state, _state_length - 1);
- checksum_complement = 0x9B;
- }
- // and negate the checksum and store it in the last byte.
- remote_state[_state_length - 1] = checksum_complement - checksum;
- } else { // short codes
- if (_model == ARRAH2E)
- // The last byte is the inverse of penultimate byte
- remote_state[_state_length_short - 1] =
- ~remote_state[_state_length_short - 2];
- // Zero the rest of the state.
- for (uint8_t i = _state_length_short; i < kFujitsuAcStateLength; i++)
- remote_state[i] = 0;
- }
-}
-
-uint8_t IRFujitsuAC::getStateLength() {
- buildState(); // Force an update of the internal state.
- if ((_model == ARRAH2E && remote_state[5] != 0xFE) ||
- (_model == ARDB1 && remote_state[5] != 0xFC))
- return _state_length_short;
- else
- return _state_length;
-}
-
-// Return a pointer to the internal state date of the remote.
-uint8_t* IRFujitsuAC::getRaw() {
- buildState();
- return remote_state;
-}
-
-void IRFujitsuAC::buildFromState(const uint16_t length) {
- switch (length) {
- case kFujitsuAcStateLength - 1:
- case kFujitsuAcStateLengthShort - 1:
- setModel(ARDB1);
- break;
- default:
- setModel(ARRAH2E);
- }
- switch (remote_state[6]) {
- case 8:
- setModel(ARDB1);
- break;
- case 9:
- setModel(ARRAH2E);
- break;
- }
- setTemp((remote_state[8] >> 4) + kFujitsuAcMinTemp);
- if (remote_state[8] & 0x1)
- setCmd(kFujitsuAcCmdTurnOn);
- else
- setCmd(kFujitsuAcCmdStayOn);
- setMode(remote_state[9] & 0b111);
- setFanSpeed(remote_state[10] & 0b111);
- setSwing(remote_state[10] >> 4);
- switch (remote_state[5]) {
- case kFujitsuAcCmdTurnOff:
- case kFujitsuAcCmdStepHoriz:
- case kFujitsuAcCmdStepVert:
- setCmd(remote_state[5]);
- break;
- }
-}
-
-bool IRFujitsuAC::setRaw(const uint8_t newState[], const uint16_t length) {
- if (length > kFujitsuAcStateLength) return false;
- for (uint16_t i = 0; i < kFujitsuAcStateLength; i++) {
- if (i < length)
- remote_state[i] = newState[i];
- else
- remote_state[i] = 0;
- }
- buildFromState(length);
- return true;
-}
-
-// Set the requested power state of the A/C to off.
-void IRFujitsuAC::off() { _cmd = kFujitsuAcCmdTurnOff; }
-
-void IRFujitsuAC::stepHoriz() {
- switch (_model) {
- case ARDB1:
- break; // This remote doesn't have a horizontal option.
- default:
- _cmd = kFujitsuAcCmdStepHoriz;
- }
-}
-
-void IRFujitsuAC::stepVert() { _cmd = kFujitsuAcCmdStepVert; }
-
-// Set the requested command of the A/C.
-void IRFujitsuAC::setCmd(uint8_t cmd) {
- switch (cmd) {
- case kFujitsuAcCmdTurnOff:
- case kFujitsuAcCmdTurnOn:
- case kFujitsuAcCmdStayOn:
- case kFujitsuAcCmdStepVert:
- _cmd = cmd;
- break;
- case kFujitsuAcCmdStepHoriz:
- if (_model != ARDB1) // AR-DB1 remote doesn't have step horizontal.
- _cmd = cmd;
- // FALLTHRU
- default:
- _cmd = kFujitsuAcCmdStayOn;
- break;
- }
-}
-
-uint8_t IRFujitsuAC::getCmd() { return _cmd; }
-
-bool IRFujitsuAC::getPower() { return _cmd != kFujitsuAcCmdTurnOff; }
-
-// Set the temp. in deg C
-void IRFujitsuAC::setTemp(uint8_t temp) {
- temp = std::max((uint8_t)kFujitsuAcMinTemp, temp);
- temp = std::min((uint8_t)kFujitsuAcMaxTemp, temp);
- _temp = temp;
-}
-
-uint8_t IRFujitsuAC::getTemp() { return _temp; }
-
-// Set the speed of the fan
-void IRFujitsuAC::setFanSpeed(uint8_t fanSpeed) {
- if (fanSpeed > kFujitsuAcFanQuiet)
- fanSpeed = kFujitsuAcFanHigh; // Set the fan to maximum if out of range.
- _fanSpeed = fanSpeed;
-}
-uint8_t IRFujitsuAC::getFanSpeed() { return _fanSpeed; }
-
-// Set the requested climate operation mode of the a/c unit.
-void IRFujitsuAC::setMode(uint8_t mode) {
- if (mode > kFujitsuAcModeHeat)
- mode = kFujitsuAcModeHeat; // Set the mode to maximum if out of range.
- _mode = mode;
-}
-
-uint8_t IRFujitsuAC::getMode() { return _mode; }
-
-// Set the requested swing operation mode of the a/c unit.
-void IRFujitsuAC::setSwing(uint8_t swingMode) {
- switch (_model) {
- case ARDB1:
- // Set the mode to max if out of range
- if (swingMode > kFujitsuAcSwingVert) swingMode = kFujitsuAcSwingVert;
- break;
- case ARRAH2E:
- default:
- // Set the mode to max if out of range
- if (swingMode > kFujitsuAcSwingBoth) swingMode = kFujitsuAcSwingBoth;
- }
- _swingMode = swingMode;
-}
-
-uint8_t IRFujitsuAC::getSwing() { return _swingMode; }
-
-bool IRFujitsuAC::validChecksum(uint8_t state[], uint16_t length) {
- uint8_t sum = 0;
- uint8_t sum_complement = 0;
- uint8_t checksum = state[length - 1];
- switch (length) {
- case kFujitsuAcStateLengthShort: // ARRAH2E
- return state[length - 1] == (uint8_t)~state[length - 2];
- case kFujitsuAcStateLength - 1: // ARDB1
- sum = sumBytes(state, length - 1);
- sum_complement = 0x9B;
- break;
- case kFujitsuAcStateLength: // ARRAH2E
- sum = sumBytes(state + kFujitsuAcStateLengthShort,
- length - 1 - kFujitsuAcStateLengthShort);
- break;
- default: // Includes ARDB1 short.
- return true; // Assume the checksum is valid for other lengths.
- }
- return checksum == (uint8_t)(sum_complement - sum); // Does it match?
-}
-
-// Convert a standard A/C mode into its native mode.
-uint8_t IRFujitsuAC::convertMode(const stdAc::opmode_t mode) {
- switch (mode) {
- case stdAc::opmode_t::kCool:
- return kFujitsuAcModeCool;
- case stdAc::opmode_t::kHeat:
- return kFujitsuAcModeHeat;
- case stdAc::opmode_t::kDry:
- return kFujitsuAcModeDry;
- case stdAc::opmode_t::kFan:
- return kFujitsuAcModeFan;
- default:
- return kFujitsuAcModeAuto;
- }
-}
-
-// Convert a standard A/C Fan speed into its native fan speed.
-uint8_t IRFujitsuAC::convertFan(stdAc::fanspeed_t speed) {
- switch (speed) {
- case stdAc::fanspeed_t::kMin:
- return kFujitsuAcFanQuiet;
- case stdAc::fanspeed_t::kLow:
- return kFujitsuAcFanLow;
- case stdAc::fanspeed_t::kMedium:
- return kFujitsuAcFanMed;
- case stdAc::fanspeed_t::kHigh:
- case stdAc::fanspeed_t::kMax:
- return kFujitsuAcFanHigh;
- default:
- return kFujitsuAcFanAuto;
- }
-}
-
-// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRFujitsuAC::toString() {
- String result = "";
-#else
-std::string IRFujitsuAC::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kFujitsuAcModeAuto:
- result += F(" (AUTO)");
- break;
- case kFujitsuAcModeCool:
- result += F(" (COOL)");
- break;
- case kFujitsuAcModeHeat:
- result += F(" (HEAT)");
- break;
- case kFujitsuAcModeDry:
- result += F(" (DRY)");
- break;
- case kFujitsuAcModeFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFanSpeed());
- switch (getFanSpeed()) {
- case kFujitsuAcFanAuto:
- result += F(" (AUTO)");
- break;
- case kFujitsuAcFanHigh:
- result += F(" (HIGH)");
- break;
- case kFujitsuAcFanMed:
- result += F(" (MED)");
- break;
- case kFujitsuAcFanLow:
- result += F(" (LOW)");
- break;
- case kFujitsuAcFanQuiet:
- result += F(" (QUIET)");
- break;
- }
- result += F(", Swing: ");
- switch (getSwing()) {
- case kFujitsuAcSwingOff:
- result += F("Off");
- break;
- case kFujitsuAcSwingVert:
- result += F("Vert");
- break;
- case kFujitsuAcSwingHoriz:
- result += F("Horiz");
- break;
- case kFujitsuAcSwingBoth:
- result += F("Vert + Horiz");
- break;
- default:
- result += F("UNKNOWN");
- }
- result += F(", Command: ");
- switch (getCmd()) {
- case kFujitsuAcCmdStepHoriz:
- result += F("Step vane horizontally");
- break;
- case kFujitsuAcCmdStepVert:
- result += F("Step vane vertically");
- break;
- default:
- result += F("N/A");
- }
- return result;
-}
-
-#if DECODE_FUJITSU_AC
-// Decode a Fujitsu AC IR message if possible.
-// Places successful decode information in the results pointer.
-// Args:
-// results: Ptr to the data to decode and where to store the decode result.
-// nbits: The number of data bits to expect. Typically kFujitsuAcBits.
-// strict: Flag to indicate if we strictly adhere to the specification.
-// Returns:
-// boolean: True if it can decode it, false if it can't.
-//
-// Status: ALPHA / Untested.
-//
-// Ref:
-//
-bool IRrecv::decodeFujitsuAC(decode_results* results, uint16_t nbits,
- bool strict) {
- uint16_t offset = kStartOffset;
- uint16_t dataBitsSoFar = 0;
-
- // Have we got enough data to successfully decode?
- if (results->rawlen < (2 * kFujitsuAcMinBits) + kHeader + kFooter - 1)
- return false; // Can't possibly be a valid message.
-
- // Compliance
- if (strict) {
- switch (nbits) {
- case kFujitsuAcBits:
- case kFujitsuAcBits - 8:
- case kFujitsuAcMinBits:
- case kFujitsuAcMinBits + 8:
- break;
- default:
- return false; // Must be called with the correct nr. of bits.
- }
- }
-
- // Header
- if (!matchMark(results->rawbuf[offset++], kFujitsuAcHdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kFujitsuAcHdrSpace)) return false;
-
- // Data (Fixed signature)
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), kFujitsuAcMinBits - 8,
- kFujitsuAcBitMark, kFujitsuAcOneSpace, kFujitsuAcBitMark,
- kFujitsuAcZeroSpace, kTolerance, kMarkExcess, false);
- if (data_result.success == false) return false; // Fail
- if (data_result.data != 0x1010006314) return false; // Signature failed.
- dataBitsSoFar += kFujitsuAcMinBits - 8;
- offset += data_result.used;
- results->state[0] = 0x14;
- results->state[1] = 0x63;
- results->state[2] = 0x00;
- results->state[3] = 0x10;
- results->state[4] = 0x10;
-
- // Keep reading bytes until we either run out of message or state to fill.
- for (uint16_t i = 5;
- offset <= results->rawlen - 16 && i < kFujitsuAcStateLength;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- data_result = matchData(
- &(results->rawbuf[offset]), 8, kFujitsuAcBitMark, kFujitsuAcOneSpace,
- kFujitsuAcBitMark, kFujitsuAcZeroSpace, kTolerance, kMarkExcess, false);
- if (data_result.success == false) break; // Fail
- results->state[i] = data_result.data;
- }
-
- // Footer
- if (offset > results->rawlen ||
- !matchMark(results->rawbuf[offset++], kFujitsuAcBitMark))
- return false;
- // The space is optional if we are out of capture.
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kFujitsuAcMinGap))
- return false;
-
- // Compliance
- if (strict) {
- if (dataBitsSoFar != nbits) return false;
- }
-
- results->decode_type = FUJITSU_AC;
- results->bits = dataBitsSoFar;
-
- // Compliance
- switch (dataBitsSoFar) {
- case kFujitsuAcMinBits:
- // Check if this values indicate that this should have been a long state
- // message.
- if (results->state[5] == 0xFC) return false;
- return true; // Success
- case kFujitsuAcMinBits + 8:
- // Check if this values indicate that this should have been a long state
- // message.
- if (results->state[5] == 0xFE) return false;
- // The last byte needs to be the inverse of the penultimate byte.
- if (results->state[5] != (uint8_t)~results->state[6]) return false;
- return true; // Success
- case kFujitsuAcBits - 8:
- // Long messages of this size require this byte be correct.
- if (results->state[5] != 0xFC) return false;
- break;
- case kFujitsuAcBits:
- // Long messages of this size require this byte be correct.
- if (results->state[5] != 0xFE) return false;
- break;
- default:
- return false; // Unexpected size.
- }
- if (!IRFujitsuAC::validChecksum(results->state, dataBitsSoFar / 8))
- return false;
-
- // Success
- return true; // All good.
-}
-#endif // DECODE_FUJITSU_AC
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Gree.h b/lib/IRremoteESP8266-2.6.0/src/ir_Gree.h
deleted file mode 100644
index c3c5916dc..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Gree.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// Kelvinator A/C
-//
-// Copyright 2016 David Conran
-
-#ifndef IR_GREE_H_
-#define IR_GREE_H_
-
-#define __STDC_LIMIT_MACROS
-#include
-#ifndef UNIT_TEST
-#include
-#else
-#include
-#endif
-#include "IRremoteESP8266.h"
-#include "IRsend.h"
-#ifdef UNIT_TEST
-#include "IRsend_test.h"
-#endif
-
-// GGGG RRRRRR EEEEEEE EEEEEEE
-// GG GG RR RR EE EE
-// GG RRRRRR EEEEE EEEEE
-// GG GG RR RR EE EE
-// GGGGGG RR RR EEEEEEE EEEEEEE
-
-// Constants
-const uint8_t kGreeAuto = 0;
-const uint8_t kGreeCool = 1;
-const uint8_t kGreeDry = 2;
-const uint8_t kGreeFan = 3;
-const uint8_t kGreeHeat = 4;
-
-// Byte 0
-const uint8_t kGreeModeMask = 0b00000111;
-const uint8_t kGreePower1Mask = 0b00001000;
-const uint8_t kGreeFanMask = 0b00110000;
-const uint8_t kGreeSwingAutoMask = 0b01000000;
-const uint8_t kGreeSleepMask = 0b10000000;
-// Byte 2
-const uint8_t kGreeTurboMask = 0b00010000;
-const uint8_t kGreeLightMask = 0b00100000;
-const uint8_t kGreePower2Mask = 0b01000000;
-const uint8_t kGreeXfanMask = 0b10000000;
-// Byte 4
-const uint8_t kGreeSwingPosMask = 0b00001111;
-
-const uint8_t kGreeMinTemp = 16; // Celsius
-const uint8_t kGreeMaxTemp = 30; // Celsius
-const uint8_t kGreeFanAuto = 0;
-const uint8_t kGreeFanMin = 1;
-const uint8_t kGreeFanMax = 3;
-
-const uint8_t kGreeSwingLastPos = 0b00000000;
-const uint8_t kGreeSwingAuto = 0b00000001;
-const uint8_t kGreeSwingUp = 0b00000010;
-const uint8_t kGreeSwingMiddleUp = 0b00000011;
-const uint8_t kGreeSwingMiddle = 0b00000100;
-const uint8_t kGreeSwingMiddleDown = 0b00000101;
-const uint8_t kGreeSwingDown = 0b00000110;
-const uint8_t kGreeSwingDownAuto = 0b00000111;
-const uint8_t kGreeSwingMiddleAuto = 0b00001001;
-const uint8_t kGreeSwingUpAuto = 0b00001011;
-
-// Legacy defines.
-#define GREE_AUTO kGreeAuto
-#define GREE_COOL kGreeCool
-#define GREE_DRY kGreeDry
-#define GREE_FAN kGreeFan
-#define GREE_HEAT kGreeHeat
-#define GREE_MIN_TEMP kGreeMinTemp
-#define GREE_MAX_TEMP kGreeMaxTemp
-#define GREE_FAN_MAX kGreeFanMax
-#define GREE_SWING_LAST_POS kGreeSwingLastPos
-#define GREE_SWING_AUTO kGreeSwingAuto
-#define GREE_SWING_UP kGreeSwingUp
-#define GREE_SWING_MIDDLE_UP kGreeSwingMiddleUp
-#define GREE_SWING_MIDDLE kGreeSwingMiddle
-#define GREE_SWING_MIDDLE_DOWN kGreeSwingMiddleDown
-#define GREE_SWING_DOWN kGreeSwingDown
-#define GREE_SWING_DOWN_AUTO kGreeSwingDownAuto
-#define GREE_SWING_MIDDLE_AUTO kGreeSwingMiddleAuto
-#define GREE_SWING_UP_AUTO kGreeSwingUpAuto
-
-// Classes
-class IRGreeAC {
- public:
- explicit IRGreeAC(uint16_t pin);
-
- void stateReset();
-#if SEND_GREE
- void send(const uint16_t repeat = kGreeDefaultRepeat);
-#endif // SEND_GREE
- void begin();
- void on();
- void off();
- void setPower(const bool state);
- bool getPower();
- void setTemp(const uint8_t temp);
- uint8_t getTemp();
- void setFan(const uint8_t speed);
- uint8_t getFan();
- void setMode(const uint8_t new_mode);
- uint8_t getMode();
- void setLight(const bool state);
- bool getLight();
- void setXFan(const bool state);
- bool getXFan();
- void setSleep(const bool state);
- bool getSleep();
- void setTurbo(const bool state);
- bool getTurbo();
- void setSwingVertical(const bool automatic, const uint8_t position);
- bool getSwingVerticalAuto();
- uint8_t getSwingVerticalPosition();
- uint8_t convertMode(const stdAc::opmode_t mode);
- uint8_t convertFan(const stdAc::fanspeed_t speed);
- uint8_t convertSwingV(const stdAc::swingv_t swingv);
- uint8_t* getRaw();
- void setRaw(uint8_t new_code[]);
- static bool validChecksum(const uint8_t state[],
- const uint16_t length = kGreeStateLength);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
-#ifndef UNIT_TEST
-
- private:
- IRsend _irsend;
-#else // UNIT_TEST
- IRsendTest _irsend;
-#endif // UNIT_TEST
- // The state of the IR remote in IR code form.
- uint8_t remote_state[kGreeStateLength];
- void checksum(const uint16_t length = kGreeStateLength);
- void fixup();
-};
-
-#endif // IR_GREE_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_LG.h b/lib/IRremoteESP8266-2.6.0/src/ir_LG.h
deleted file mode 100644
index 25d56bc26..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/ir_LG.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2017 David Conran
-
-#ifndef IR_LG_H_
-#define IR_LG_H_
-
-// L GGGG
-// L G
-// L G GG
-// L G G
-// LLLLL GGG
-
-#define __STDC_LIMIT_MACROS
-#include
-
-uint8_t calcLGChecksum(uint16_t data);
-
-#endif // IR_LG_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Sharp.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Sharp.cpp
deleted file mode 100644
index ae1b59c74..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Sharp.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright 2009 Ken Shirriff
-// Copyright 2017 David Conran
-
-#include
-#include "IRrecv.h"
-#include "IRsend.h"
-#include "IRutils.h"
-
-// SSSS H H AAA RRRR PPPP
-// S H H A A R R P P
-// SSS HHHHH AAAAA RRRR PPPP
-// S H H A A R R P
-// SSSS H H A A R R P
-
-// Equipment it seems compatible with:
-// * Sharp LC-52D62U
-// *
-//
-
-// Constants
-// period time = 1/38000Hz = 26.316 microseconds.
-// Ref:
-// GlobalCache's IR Control Tower data.
-// http://www.sbprojects.com/knowledge/ir/sharp.php
-const uint16_t kSharpTick = 26;
-const uint16_t kSharpBitMarkTicks = 10;
-const uint16_t kSharpBitMark = kSharpBitMarkTicks * kSharpTick;
-const uint16_t kSharpOneSpaceTicks = 70;
-const uint16_t kSharpOneSpace = kSharpOneSpaceTicks * kSharpTick;
-const uint16_t kSharpZeroSpaceTicks = 30;
-const uint16_t kSharpZeroSpace = kSharpZeroSpaceTicks * kSharpTick;
-const uint16_t kSharpGapTicks = 1677;
-const uint16_t kSharpGap = kSharpGapTicks * kSharpTick;
-// Address(5) + Command(8) + Expansion(1) + Check(1)
-const uint64_t kSharpToggleMask =
- ((uint64_t)1 << (kSharpBits - kSharpAddressBits)) - 1;
-const uint64_t kSharpAddressMask = ((uint64_t)1 << kSharpAddressBits) - 1;
-const uint64_t kSharpCommandMask = ((uint64_t)1 << kSharpCommandBits) - 1;
-
-#if (SEND_SHARP || SEND_DENON)
-// Send a (raw) Sharp message
-//
-// Args:
-// data: Contents of the message to be sent.
-// nbits: Nr. of bits of data to be sent. Typically kSharpBits.
-// repeat: Nr. of additional times the message is to be sent.
-//
-// Status: BETA / Previously working fine.
-//
-// Notes:
-// This procedure handles the inversion of bits required per protocol.
-// The protocol spec says to send the LSB first, but legacy code & usage
-// has us sending the MSB first. Grrrr. Normal invocation of encodeSharp()
-// handles this for you, assuming you are using the correct/standard values.
-// e.g. sendSharpRaw(encodeSharp(address, command));
-//
-// Ref:
-// http://www.sbprojects.com/knowledge/ir/sharp.htm
-// http://lirc.sourceforge.net/remotes/sharp/GA538WJSA
-// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf
-// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp
-void IRsend::sendSharpRaw(uint64_t data, uint16_t nbits, uint16_t repeat) {
- for (uint16_t i = 0; i <= repeat; i++) {
- // Protocol demands that the data be sent twice; once normally,
- // then with all but the address bits inverted.
- // Note: Previously this used to be performed 3 times (normal, inverted,
- // normal), however all data points to that being incorrect.
- for (uint8_t n = 0; n < 2; n++) {
- sendGeneric(0, 0, // No Header
- kSharpBitMark, kSharpOneSpace, kSharpBitMark, kSharpZeroSpace,
- kSharpBitMark, kSharpGap, data, nbits, 38, true,
- 0, // Repeats are handled already.
- 33);
- // Invert the data per protocol. This is always called twice, so it's
- // retured to original upon exiting the inner loop.
- data ^= kSharpToggleMask;
- }
- }
-}
-
-// Encode a (raw) Sharp message from it's components.
-//
-// Args:
-// address: The value of the address to be sent.
-// command: The value of the address to be sent. (8 bits)
-// expansion: The value of the expansion bit to use. (0 or 1, typically 1)
-// check: The value of the check bit to use. (0 or 1, typically 0)
-// MSBfirst: Flag indicating MSB first or LSB first order. (Default: false)
-// Returns:
-// An uint32_t containing the raw Sharp message for sendSharpRaw().
-//
-// Status: BETA / Should work okay.
-//
-// Notes:
-// Assumes the standard Sharp bit sizes.
-// Historically sendSharp() sends address & command in
-// MSB first order. This is actually incorrect. It should be sent in LSB
-// order. The behaviour of sendSharp() hasn't been changed to maintain
-// backward compatibility.
-//
-// Ref:
-// http://www.sbprojects.com/knowledge/ir/sharp.htm
-// http://lirc.sourceforge.net/remotes/sharp/GA538WJSA
-// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf
-uint32_t IRsend::encodeSharp(uint16_t address, uint16_t command,
- uint16_t expansion, uint16_t check,
- bool MSBfirst) {
- // Mask any unexpected bits.
- address &= ((1 << kSharpAddressBits) - 1);
- command &= ((1 << kSharpCommandBits) - 1);
- expansion &= 1;
- check &= 1;
-
- if (!MSBfirst) { // Correct bit order if needed.
- address = reverseBits(address, kSharpAddressBits);
- command = reverseBits(command, kSharpCommandBits);
- }
- // Concatinate all the bits.
- return (address << (kSharpCommandBits + 2)) | (command << 2) |
- (expansion << 1) | check;
-}
-
-// Send a Sharp message
-//
-// Args:
-// address: Address value to be sent.
-// command: Command value to be sent.
-// nbits: Nr. of bits of data to be sent. Typically kSharpBits.
-// repeat: Nr. of additional times the message is to be sent.
-//
-// Status: DEPRICATED / Previously working fine.
-//
-// Notes:
-// This procedure has a non-standard invocation style compared to similar
-// sendProtocol() routines. This is due to legacy, compatibility, & historic
-// reasons. Normally the calling syntax version is like sendSharpRaw().
-// This procedure transmits the address & command in MSB first order, which is
-// incorrect. This behaviour is left as-is to maintain backward
-// compatibility with legacy code.
-// In short, you should use sendSharpRaw(), encodeSharp(), and the correct
-// values of address & command instead of using this, & the wrong values.
-//
-// Ref:
-// http://www.sbprojects.com/knowledge/ir/sharp.htm
-// http://lirc.sourceforge.net/remotes/sharp/GA538WJSA
-// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf
-void IRsend::sendSharp(uint16_t address, uint16_t command, uint16_t nbits,
- uint16_t repeat) {
- sendSharpRaw(encodeSharp(address, command, 1, 0, true), nbits, repeat);
-}
-#endif // (SEND_SHARP || SEND_DENON)
-
-#if (DECODE_SHARP || DECODE_DENON)
-// Decode the supplied Sharp message.
-//
-// Args:
-// results: Ptr to the data to decode and where to store the decode result.
-// nbits: Nr. of data bits to expect. Typically kSharpBits.
-// strict: Flag indicating if we should perform strict matching.
-// expansion: Should we expect the expansion bit to be set. Default is true.
-// Returns:
-// boolean: True if it can decode it, false if it can't.
-//
-// Status: STABLE / Working fine.
-//
-// Note:
-// This procedure returns a value suitable for use in sendSharpRaw().
-// TODO(crankyoldgit): Need to ensure capture of the inverted message as it can
-// be missed due to the interrupt timeout used to detect an end of message.
-// Several compliance checks are disabled until that is resolved.
-// Ref:
-// http://www.sbprojects.com/knowledge/ir/sharp.php
-// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf
-// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp
-bool IRrecv::decodeSharp(decode_results *results, uint16_t nbits, bool strict,
- bool expansion) {
- if (results->rawlen < 2 * nbits + kFooter - 1)
- return false; // Not enough entries to be a Sharp message.
- // Compliance
- if (strict) {
- if (nbits != kSharpBits) return false; // Request is out of spec.
- // DISABLED - See TODO
-#ifdef UNIT_TEST
- // An in spec message has the data sent normally, then inverted. So we
- // expect twice as many entries than to just get the results.
- if (results->rawlen < 2 * (2 * nbits + kFooter)) return false;
-#endif
- }
-
- uint64_t data = 0;
- uint16_t offset = kStartOffset;
-
- // No header
- // But try to auto-calibrate off the initial mark signal.
- if (!matchMark(results->rawbuf[offset], kSharpBitMark, 35)) return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t tick = results->rawbuf[offset] * kRawTick / kSharpBitMarkTicks;
- // Data
- for (uint16_t i = 0; i < nbits; i++, offset++) {
- // Use a higher tolerance value for kSharpBitMark as it is quite small.
- if (!matchMark(results->rawbuf[offset++], kSharpBitMarkTicks * tick, 35))
- return false;
- if (matchSpace(results->rawbuf[offset], kSharpOneSpaceTicks * tick))
- data = (data << 1) | 1; // 1
- else if (matchSpace(results->rawbuf[offset], kSharpZeroSpaceTicks * tick))
- data <<= 1; // 0
- else
- return false;
- }
-
- // Footer
- if (!match(results->rawbuf[offset++], kSharpBitMarkTicks * tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kSharpGapTicks * tick))
- return false;
-
- // Compliance
- if (strict) {
- // Check the state of the expansion bit is what we expect.
- if ((data & 0b10) >> 1 != expansion) return false;
- // The check bit should be cleared in a normal message.
- if (data & 0b1) return false;
- // DISABLED - See TODO
-#ifdef UNIT_TEST
- // Grab the second copy of the data (i.e. inverted)
- // Header
- // i.e. The inter-data/command repeat gap.
- if (!matchSpace(results->rawbuf[offset++], kSharpGapTicks * tick))
- return false;
-
- // Data
- uint64_t second_data = 0;
- for (uint16_t i = 0; i < nbits; i++, offset++) {
- // Use a higher tolerance value for kSharpBitMark as it is quite small.
- if (!matchMark(results->rawbuf[offset++], kSharpBitMarkTicks * tick, 35))
- return false;
- if (matchSpace(results->rawbuf[offset], kSharpOneSpaceTicks * tick))
- second_data = (second_data << 1) | 1; // 1
- else if (matchSpace(results->rawbuf[offset], kSharpZeroSpaceTicks * tick))
- second_data <<= 1; // 0
- else
- return false;
- }
- // Footer
- if (!match(results->rawbuf[offset++], kSharpBitMarkTicks * tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kSharpGapTicks * tick))
- return false;
-
- // Check that second_data has been inverted correctly.
- if (data != (second_data ^ kSharpToggleMask)) return false;
-#endif // UNIT_TEST
- }
-
- // Success
- results->decode_type = SHARP;
- results->bits = nbits;
- results->value = data;
- // Address & command are actually transmitted in LSB first order.
- results->address = reverseBits(data, nbits) & kSharpAddressMask;
- results->command =
- reverseBits((data >> 2) & kSharpCommandMask, kSharpCommandBits);
- return true;
-}
-#endif // (DECODE_SHARP || DECODE_DENON)
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.cpp
deleted file mode 100644
index b5c15e7fd..000000000
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2017 stufisher
-
-#include "ir_Trotec.h"
-#include
-#include "IRremoteESP8266.h"
-#include "IRutils.h"
-
-// Constants
-const uint16_t kTrotecHdrMark = 5952;
-const uint16_t kTrotecHdrSpace = 7364;
-const uint16_t kTrotecOneMark = 592;
-const uint16_t kTrotecOneSpace = 1560;
-const uint16_t kTrotecZeroMark = 592;
-const uint16_t kTrotecZeroSpace = 592;
-const uint16_t kTrotecGap = 6184;
-const uint16_t kTrotecGapEnd = 1500; // made up value
-
-#if SEND_TROTEC
-
-void IRsend::sendTrotec(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
- if (nbytes < kTrotecStateLength) return;
-
- for (uint16_t r = 0; r <= repeat; r++) {
- sendGeneric(kTrotecHdrMark, kTrotecHdrSpace, kTrotecOneMark,
- kTrotecOneSpace, kTrotecZeroMark, kTrotecZeroSpace,
- kTrotecOneMark, kTrotecGap, data, nbytes, 36, false,
- 0, // Repeats handled elsewhere
- 50);
- // More footer
- enableIROut(36);
- mark(kTrotecOneMark);
- space(kTrotecGapEnd);
- }
-}
-#endif // SEND_TROTEC
-
-IRTrotecESP::IRTrotecESP(uint16_t pin) : _irsend(pin) { stateReset(); }
-
-void IRTrotecESP::begin() { _irsend.begin(); }
-
-#if SEND_TROTEC
-void IRTrotecESP::send(const uint16_t repeat) {
- checksum();
- _irsend.sendTrotec(remote_state, kTrotecStateLength, repeat);
-}
-#endif // SEND_TROTEC
-
-void IRTrotecESP::checksum() {
- uint8_t sum = 0;
-
- for (uint8_t i = 2; i < 8; i++) sum += remote_state[i];
- remote_state[8] = sum & 0xFF;
-}
-
-void IRTrotecESP::stateReset() {
- for (uint8_t i = 2; i < kTrotecStateLength; i++) remote_state[i] = 0x0;
-
- remote_state[0] = kTrotecIntro1;
- remote_state[1] = kTrotecIntro2;
-
- setPower(false);
- setTemp(kTrotecDefTemp);
- setSpeed(kTrotecFanMed);
- setMode(kTrotecAuto);
-}
-
-uint8_t* IRTrotecESP::getRaw() {
- checksum();
- return remote_state;
-}
-
-void IRTrotecESP::setPower(const bool on) {
- if (on)
- remote_state[2] |= kTrotecPowerBit;
- else
- remote_state[2] &= ~kTrotecPowerBit;
-}
-
-bool IRTrotecESP::getPower() { return remote_state[2] & kTrotecPowerBit; }
-
-void IRTrotecESP::setSpeed(const uint8_t fan) {
- uint8_t speed = std::min(fan, kTrotecFanHigh);
- remote_state[2] = (remote_state[2] & 0b11001111) | (speed << 4);
-}
-
-uint8_t IRTrotecESP::getSpeed() { return (remote_state[2] & 0b00110000) >> 4; }
-
-void IRTrotecESP::setMode(const uint8_t mode) {
- switch (mode) {
- case kTrotecAuto:
- case kTrotecCool:
- case kTrotecDry:
- case kTrotecFan:
- remote_state[2] = (remote_state[2] & 0b11111100) | mode;
- return;
- default:
- this->setMode(kTrotecAuto);
- }
-}
-
-uint8_t IRTrotecESP::getMode() { return remote_state[2] & 0b00000011; }
-
-void IRTrotecESP::setTemp(const uint8_t celsius) {
- uint8_t temp = std::max(celsius, kTrotecMinTemp);
- temp = std::min(temp, kTrotecMaxTemp);
- remote_state[3] = (remote_state[3] & 0x80) | (temp - kTrotecMinTemp);
-}
-
-uint8_t IRTrotecESP::getTemp() {
- return (remote_state[3] & 0b01111111) + kTrotecMinTemp;
-}
-
-void IRTrotecESP::setSleep(bool sleep) {
- if (sleep)
- remote_state[3] |= kTrotecSleepBit;
- else
- remote_state[3] &= ~kTrotecSleepBit;
-}
-
-bool IRTrotecESP::getSleep(void) { return remote_state[3] & kTrotecSleepBit; }
-
-void IRTrotecESP::setTimer(const uint8_t timer) {
- if (timer)
- remote_state[5] |= kTrotecTimerBit;
- else
- remote_state[5] &= ~kTrotecTimerBit;
- remote_state[6] = (timer > kTrotecMaxTimer) ? kTrotecMaxTimer : timer;
-}
-
-uint8_t IRTrotecESP::getTimer() { return remote_state[6]; }
-
-// Convert a standard A/C mode into its native mode.
-uint8_t IRTrotecESP::convertMode(const stdAc::opmode_t mode) {
- switch (mode) {
- case stdAc::opmode_t::kCool:
- return kTrotecCool;
- case stdAc::opmode_t::kDry:
- return kTrotecDry;
- case stdAc::opmode_t::kFan:
- return kTrotecFan;
- // Note: No Heat mode.
- default:
- return kTrotecAuto;
- }
-}
-
-// Convert a standard A/C Fan speed into its native fan speed.
-uint8_t IRTrotecESP::convertFan(const stdAc::fanspeed_t speed) {
- switch (speed) {
- case stdAc::fanspeed_t::kMin:
- case stdAc::fanspeed_t::kLow:
- return kTrotecFanLow;
- case stdAc::fanspeed_t::kMedium:
- return kTrotecFanMed;
- case stdAc::fanspeed_t::kHigh:
- case stdAc::fanspeed_t::kMax:
- return kTrotecFanHigh;
- default:
- return kTrotecFanMed;
- }
-}
diff --git a/lib/IRremoteESP8266-2.6.0/test/IRrecv_test.cpp b/lib/IRremoteESP8266-2.6.0/test/IRrecv_test.cpp
deleted file mode 100644
index 85b6685f0..000000000
--- a/lib/IRremoteESP8266-2.6.0/test/IRrecv_test.cpp
+++ /dev/null
@@ -1,561 +0,0 @@
-// Copyright 2017 David Conran
-
-#include "IRrecv_test.h"
-#include "IRrecv.h"
-#include "IRremoteESP8266.h"
-#include "IRsend.h"
-#include "IRsend_test.h"
-#include "gtest/gtest.h"
-
-// Tests for the IRrecv object.
-TEST(TestIRrecv, DefaultBufferSize) {
- IRrecv irrecv_default(1);
- EXPECT_EQ(kRawBuf, irrecv_default.getBufSize());
-}
-
-TEST(TestIRrecv, LargeBufferSize) {
- IRrecv irrecv_large(3, 1024);
- EXPECT_EQ(1024, irrecv_large.getBufSize());
-}
-
-TEST(TestIRrecv, SmallBufferSize) {
- IRrecv irrecv_small(4, 80);
- EXPECT_EQ(80, irrecv_small.getBufSize());
-}
-
-TEST(TestIRrecv, MediumBufferSize) {
- IRrecv irrecv_medium(4, 512);
- EXPECT_EQ(512, irrecv_medium.getBufSize());
-}
-
-TEST(TestIRrecv, IRrecvDestructor) {
- IRrecv *irrecv_ptr = new IRrecv(1);
- EXPECT_EQ(kRawBuf, irrecv_ptr->getBufSize());
-
- delete irrecv_ptr;
- irrecv_ptr = new IRrecv(1, 1234);
- EXPECT_EQ(1234, irrecv_ptr->getBufSize());
- delete irrecv_ptr;
-
- irrecv_ptr = new IRrecv(1, 123);
- EXPECT_EQ(123, irrecv_ptr->getBufSize());
- delete irrecv_ptr;
-}
-
-// Tests for copyIrParams()
-
-TEST(TestCopyIrParams, CopyEmpty) {
- irparams_t src;
- irparams_t dst;
- uint16_t test_size = 1234;
- src.bufsize = test_size;
- src.rawlen = 0;
- src.rawbuf = new uint16_t[test_size];
- src.overflow = false;
- dst.bufsize = 4567;
- dst.rawlen = 123;
- dst.rawbuf = new uint16_t[test_size];
- dst.overflow = true;
- // Confirm we are looking at different memory for the buffers.
- ASSERT_NE(src.rawbuf, dst.rawbuf);
-
- IRrecv irrecv(4);
- irrecv.copyIrParams(&src, &dst);
-
- ASSERT_EQ(src.bufsize, dst.bufsize);
- ASSERT_EQ(src.rawlen, dst.rawlen);
- ASSERT_NE(src.rawbuf, dst.rawbuf); // Pointers, not content.
- ASSERT_EQ(src.overflow, dst.overflow);
- // Contents of the buffers needs to match.
- EXPECT_EQ(0, memcmp(src.rawbuf, dst.rawbuf, src.bufsize * sizeof(uint16_t)));
-}
-
-TEST(TestCopyIrParams, CopyNonEmpty) {
- irparams_t src;
- irparams_t dst;
- uint16_t test_size = 1234;
- src.bufsize = test_size;
- src.rawlen = 67;
- src.rawbuf = new uint16_t[test_size];
- src.rawbuf[0] = 0xF00D;
- src.rawbuf[1] = 0xBEEF;
- src.rawbuf[test_size - 1] = 0xDEAD;
- src.overflow = true;
- dst.bufsize = 0;
- dst.rawlen = 0;
- dst.rawbuf = new uint16_t[test_size];
- dst.overflow = false;
- // Confirm we are looking at different memory for the buffers.
- ASSERT_NE(src.rawbuf, dst.rawbuf);
- // and that they differ before we test.
- EXPECT_NE(0, memcmp(src.rawbuf, dst.rawbuf, src.bufsize * sizeof(uint16_t)));
-
- IRrecv irrecv(4);
- irrecv.copyIrParams(&src, &dst);
-
- ASSERT_EQ(src.bufsize, dst.bufsize);
- EXPECT_EQ(test_size, dst.bufsize);
- ASSERT_EQ(src.rawlen, dst.rawlen);
- EXPECT_EQ(67, dst.rawlen);
- ASSERT_EQ(src.overflow, dst.overflow);
- EXPECT_TRUE(dst.overflow);
- ASSERT_NE(src.rawbuf, dst.rawbuf); // Pointers, not content.
- // Contents of the buffers needs to match.
- EXPECT_EQ(0, memcmp(src.rawbuf, dst.rawbuf, src.bufsize * sizeof(uint16_t)));
- // Check the canary values.
- EXPECT_EQ(0xF00D, dst.rawbuf[0]);
- EXPECT_EQ(0xBEEF, dst.rawbuf[1]);
- EXPECT_EQ(0xDEAD, dst.rawbuf[test_size - 1]);
-}
-
-// Tests for decode().
-
-// Test decode of a NEC message.
-TEST(TestDecode, DecodeNEC) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendNEC(0x807F40BF);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(NEC, irsend.capture.decode_type);
- EXPECT_EQ(kNECBits, irsend.capture.bits);
- EXPECT_EQ(0x807F40BF, irsend.capture.value);
-}
-
-// Test decode of a JVC message.
-TEST(TestDecode, DecodeJVC) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendJVC(0xC2B8);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(JVC, irsend.capture.decode_type);
- EXPECT_EQ(kJvcBits, irsend.capture.bits);
- EXPECT_EQ(0xC2B8, irsend.capture.value);
-}
-
-// Test decode of a LG message.
-TEST(TestDecode, DecodeLG) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendLG(0x4B4AE51);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(LG, irsend.capture.decode_type);
- EXPECT_EQ(kLgBits, irsend.capture.bits);
- EXPECT_EQ(0x4B4AE51, irsend.capture.value);
-
- irsend.reset();
- irsend.sendLG(0xB4B4AE51, kLg32Bits);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(LG, irsend.capture.decode_type);
- EXPECT_EQ(kLg32Bits, irsend.capture.bits);
- EXPECT_EQ(0xB4B4AE51, irsend.capture.value);
-}
-
-// Test decode of a Panasonic message.
-TEST(TestDecode, DecodePanasonic) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendPanasonic64(0x40040190ED7C);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true));
- EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
- EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
- EXPECT_EQ(0x40040190ED7C, irsend.capture.value);
-}
-
-// Test decode of a Samsun message.
-TEST(TestDecode, DecodeSamsung) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendSAMSUNG(0xE0E09966);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(SAMSUNG, irsend.capture.decode_type);
- EXPECT_EQ(kSamsungBits, irsend.capture.bits);
- EXPECT_EQ(0xE0E09966, irsend.capture.value);
-}
-
-// Test decode of a Sherwood message.
-TEST(TestDecode, DecodeSherwood) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendSherwood(0x807F40BF);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- // Sherwood codes are really NEC codes.
- EXPECT_EQ(NEC, irsend.capture.decode_type);
- EXPECT_EQ(kNECBits, irsend.capture.bits);
- EXPECT_EQ(0x807F40BF, irsend.capture.value);
-}
-
-// Test decode of a Whynter message.
-TEST(TestDecode, DecodeWhynter) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendWhynter(0x87654321);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(WHYNTER, irsend.capture.decode_type);
- EXPECT_EQ(kWhynterBits, irsend.capture.bits);
- EXPECT_EQ(0x87654321, irsend.capture.value);
-}
-
-// Test decode of Sony messages.
-TEST(TestDecode, DecodeSony) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
-
- // Synthesised Normal Sony 20-bit message.
- irsend.reset();
- irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1));
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(SONY, irsend.capture.decode_type);
- EXPECT_EQ(kSony20Bits, irsend.capture.bits);
- EXPECT_EQ(0x81080, irsend.capture.value);
-
- // Synthesised Normal Sony 15-bit message.
- irsend.reset();
- irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(SONY, irsend.capture.decode_type);
- EXPECT_EQ(kSony15Bits, irsend.capture.bits);
- EXPECT_EQ(0x5480, irsend.capture.value);
-
- // Synthesised Normal Sony 12-bit message.
- irsend.reset();
- irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(SONY, irsend.capture.decode_type);
- EXPECT_EQ(kSony12Bits, irsend.capture.bits);
- EXPECT_EQ(0xA90, irsend.capture.value);
-}
-
-// Test decode of Sharp messages.
-TEST(TestDecode, DecodeSharp) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendSharpRaw(0x454A);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(SHARP, irsend.capture.decode_type);
- EXPECT_EQ(kSharpBits, irsend.capture.bits);
- EXPECT_EQ(0x454A, irsend.capture.value);
-}
-
-// Test decode of Sanyo messages.
-TEST(TestDecode, DecodeSanyo) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendSanyoLC7461(0x2468DCB56A9);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type);
- EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits);
- EXPECT_EQ(0x2468DCB56A9, irsend.capture.value);
-}
-
-// Test decode of RC-MM messages.
-TEST(TestDecode, DecodeRCMM) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
-
- // Normal RCMM 24-bit message.
- irsend.reset();
- irsend.sendRCMM(0xe0a600);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(RCMM, irsend.capture.decode_type);
- EXPECT_EQ(kRCMMBits, irsend.capture.bits);
- EXPECT_EQ(0xe0a600, irsend.capture.value);
-
- // Normal RCMM 12-bit message.
- irsend.reset();
- irsend.sendRCMM(0x600, 12);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(RCMM, irsend.capture.decode_type);
- EXPECT_EQ(12, irsend.capture.bits);
- EXPECT_EQ(0x600, irsend.capture.value);
-
- // Normal RCMM 32-bit message.
- irsend.reset();
- irsend.sendRCMM(0x28e0a600, 32);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(RCMM, irsend.capture.decode_type);
- EXPECT_EQ(32, irsend.capture.bits);
- EXPECT_EQ(0x28e0a600, irsend.capture.value);
-}
-
-// Test decode of Mitsubishi messages.
-TEST(TestDecode, DecodeMitsubishi) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendMitsubishi(0xC2B8);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type);
- EXPECT_EQ(kMitsubishiBits, irsend.capture.bits);
- EXPECT_EQ(0xC2B8, irsend.capture.value);
-}
-
-// Test decode of RC-5/RC-5X messages.
-TEST(TestDecode, DecodeRC5) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- // Normal RC-5 12-bit message.
- irsend.reset();
- irsend.sendRC5(0x175);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(RC5, irsend.capture.decode_type);
- EXPECT_EQ(kRC5Bits, irsend.capture.bits);
- EXPECT_EQ(0x175, irsend.capture.value);
- // Synthesised Normal RC-5X 13-bit message.
- irsend.reset();
- irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(RC5X, irsend.capture.decode_type);
- EXPECT_EQ(kRC5XBits, irsend.capture.bits);
- EXPECT_EQ(0x1881, irsend.capture.value);
-}
-
-// Test decode of RC-6 messages.
-TEST(TestDecode, DecodeRC6) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- // Normal RC-6 Mode 0 (20-bit) message.
- irsend.reset();
- irsend.sendRC6(0x175);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(RC6, irsend.capture.decode_type);
- EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits);
- EXPECT_EQ(0x175, irsend.capture.value);
-
- // Normal RC-6 36-bit message.
- irsend.reset();
- irsend.sendRC6(0xC800F742A, kRC6_36Bits);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(RC6, irsend.capture.decode_type);
- EXPECT_EQ(kRC6_36Bits, irsend.capture.bits);
- EXPECT_EQ(0xC800F742A, irsend.capture.value);
-}
-
-// Test decode of Dish messages.
-TEST(TestDecode, DecodeDish) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendDISH(0x9C00);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(DISH, irsend.capture.decode_type);
- EXPECT_EQ(kDishBits, irsend.capture.bits);
- EXPECT_EQ(0x9C00, irsend.capture.value);
-}
-
-// Test decode of Denon messages.
-TEST(TestDecode, DecodeDenon) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- // Normal Denon 15-bit message. (Sharp)
- irsend.reset();
- irsend.sendDenon(0x2278);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(DENON, irsend.capture.decode_type);
- EXPECT_EQ(DENON_BITS, irsend.capture.bits);
- EXPECT_EQ(0x2278, irsend.capture.value);
- // Legacy Denon 14-bit message.
- irsend.reset();
- irsend.sendDenon(0x1278, kDenonLegacyBits);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(DENON, irsend.capture.decode_type);
- EXPECT_EQ(DENON_BITS, irsend.capture.bits);
- EXPECT_EQ(0x1278, irsend.capture.value);
- // Normal Denon 48-bit message. (Panasonic/Kaseikyo)
- irsend.reset();
- irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(DENON, irsend.capture.decode_type);
- EXPECT_EQ(DENON_48_BITS, irsend.capture.bits);
- EXPECT_EQ(0x2A4C028D6CE3, irsend.capture.value);
-}
-
-// Test decode of Coolix messages.
-TEST(TestDecode, DecodeCoolix) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendCOOLIX(0x123456);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(COOLIX, irsend.capture.decode_type);
- EXPECT_EQ(kCoolixBits, irsend.capture.bits);
- EXPECT_EQ(0x123456, irsend.capture.value);
-}
-
-// Test decode of Aiwa messages.
-TEST(TestDecode, DecodeAiwa) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
- irsend.reset();
- irsend.sendAiwaRCT501(0x7F);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type);
- EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits);
- EXPECT_EQ(0x7F, irsend.capture.value);
-}
-
-// Test matchData() on space encoded data.
-TEST(TestMatchData, SpaceEncoded) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
-
- uint16_t space_encoded_raw[11] = {500, 500, 500, 1500, 499, 499,
- 501, 1501, 499, 1490, 500};
- match_result_t result;
-
- irsend.reset();
- irsend.sendRaw(space_encoded_raw, 11, 38000);
- irsend.makeDecodeResult();
- result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 500, 1500, 500, 500);
- ASSERT_TRUE(result.success);
- EXPECT_EQ(0b01011, result.data);
- EXPECT_EQ(10, result.used);
-
- irsend.reset();
- irsend.sendRaw(space_encoded_raw, 11, 38000);
- irsend.makeDecodeResult();
- result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 500, 1000, 500, 500);
- ASSERT_FALSE(result.success);
-}
-
-// Test matchData() on mark encoded data.
-TEST(TestMatchData, MarkEncoded) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
-
- uint16_t mark_encoded_raw[11] = {500, 500, 1500, 500, 499, 499,
- 1501, 501, 1499, 490, 500};
- match_result_t result;
-
- irsend.reset();
- irsend.sendRaw(mark_encoded_raw, 11, 38000);
- irsend.makeDecodeResult();
- // MSBF order.
- result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 500);
- ASSERT_TRUE(result.success);
- EXPECT_EQ(0b01011, result.data);
- EXPECT_EQ(10, result.used);
- // LSBF order.
- result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 500,
- kTolerance, kMarkExcess, false);
- ASSERT_TRUE(result.success);
- EXPECT_EQ(0b11010, result.data); // Bits reversed of the previous test.
- EXPECT_EQ(10, result.used);
-
- irsend.reset();
- irsend.sendRaw(mark_encoded_raw, 11, 38000);
- irsend.makeDecodeResult();
- // MSBF order.
- result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 500);
- ASSERT_FALSE(result.success);
- // LSBF order.
- result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 500,
- kTolerance, kMarkExcess, false);
- ASSERT_FALSE(result.success);
-}
-
-// Test matchData() on "equal total bit time" encoded data.
-TEST(TestMatchData, EqualTotalBitTimeEncoded) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
-
- uint16_t equal_encoded_raw[11] = {500, 1500, 1500, 500, 499, 1499,
- 1501, 501, 1499, 490, 500};
- match_result_t result;
-
- irsend.reset();
- irsend.sendRaw(equal_encoded_raw, 11, 38000);
- irsend.makeDecodeResult();
- result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 1500);
- ASSERT_TRUE(result.success);
- EXPECT_EQ(0b01011, result.data);
- EXPECT_EQ(10, result.used);
-
- irsend.reset();
- irsend.sendRaw(equal_encoded_raw, 11, 38000);
- irsend.makeDecodeResult();
- result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 1000);
- ASSERT_FALSE(result.success);
-}
-
-// Test matchData() on arbitrary encoded data.
-TEST(TestMatchData, ArbitraryEncoded) {
- IRsendTest irsend(0);
- IRrecv irrecv(1);
- irsend.begin();
-
- uint16_t arbitrary_encoded_raw[11] = {500, 1500, 3000, 1000, 499, 1499,
- 3001, 1001, 2999, 990, 500};
- match_result_t result;
-
- irsend.reset();
- irsend.sendRaw(arbitrary_encoded_raw, 11, 38000);
- irsend.makeDecodeResult();
- result =
- irrecv.matchData(irsend.capture.rawbuf + 1, 5, 3000, 1000, 500, 1500);
- ASSERT_TRUE(result.success);
- EXPECT_EQ(0b01011, result.data);
- EXPECT_EQ(10, result.used);
-
- irsend.reset();
- irsend.sendRaw(arbitrary_encoded_raw, 11, 38000);
- irsend.makeDecodeResult();
- result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 1000);
- ASSERT_FALSE(result.success);
-}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Electra_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Electra_test.cpp
deleted file mode 100644
index 7d6d0c915..000000000
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Electra_test.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2018 David Conran
-
-#include "IRrecv.h"
-#include "IRrecv_test.h"
-#include "IRsend.h"
-#include "IRsend_test.h"
-#include "gtest/gtest.h"
-
-// Tests for sendElectraAC().
-
-// Test sending typical data only.
-TEST(TestSendElectraAC, SendDataOnly) {
- IRsendTest irsend(0);
- irsend.begin();
- uint8_t data[kElectraAcStateLength] = {0xC3, 0x87, 0xF6, 0x28, 0x60,
- 0x00, 0x20, 0x00, 0x00, 0x20,
- 0x00, 0x05, 0x0D};
-
- irsend.sendElectraAC(data);
- EXPECT_EQ(
- "f38000d50"
- "m9166s4470"
- "m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647m646s1647"
- "m646s1647m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647"
- "m646s547m646s1647m646s1647m646s547m646s1647m646s1647m646s1647m646s1647"
- "m646s547m646s547m646s547m646s1647m646s547m646s1647m646s547m646s547"
- "m646s547m646s547m646s547m646s547m646s547m646s1647m646s1647m646s547"
- "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547"
- "m646s547m646s547m646s547m646s547m646s547m646s1647m646s547m646s547"
- "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547"
- "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547"
- "m646s547m646s547m646s547m646s547m646s547m646s1647m646s547m646s547"
- "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547"
- "m646s1647m646s547m646s1647m646s547m646s547m646s547m646s547m646s547"
- "m646s1647m646s547m646s1647m646s1647m646s547m646s547m646s547m646s547"
- "m646s100000",
- irsend.outputStr());
-}
-
-// Tests for decodeElectraAC().
-// Decode normal ElectraAC messages.
-
-TEST(TestDecodeElectraAC, SyntheticDecode) {
- IRsendTest irsend(0);
- IRrecv irrecv(0);
- irsend.begin();
-
- // Synthesised Normal ElectraAC message.
- irsend.reset();
- uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0x87, 0xF6, 0x28, 0x60,
- 0x00, 0x20, 0x00, 0x00, 0x20,
- 0x00, 0x05, 0x0D};
- irsend.sendElectraAC(expectedState);
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decode(&irsend.capture));
- EXPECT_EQ(ELECTRA_AC, irsend.capture.decode_type);
- EXPECT_EQ(kElectraAcBits, irsend.capture.bits);
- EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
-}
-
-// Decode a recorded example
-TEST(TestDecodeElectraAC, RealExampleDecode) {
- IRsendTest irsend(0);
- IRrecv irrecv(0);
- irsend.begin();
-
- // Real ElectraAC message.
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/527
- uint16_t rawData[211] = {
- 9166, 4470, 642, 1632, 642, 1632, 668, 534, 666, 534, 668, 534,
- 614, 536, 640, 1636, 640, 1646, 694, 1662, 612, 1628, 642, 1666,
- 664, 532, 668, 534, 666, 534, 666, 532, 666, 1644, 642, 532,
- 640, 1634, 668, 1632, 642, 538, 666, 1660, 610, 1666, 664, 1632,
- 642, 1672, 610, 536, 666, 534, 694, 532, 666, 1636, 614, 538,
- 666, 1632, 642, 536, 666, 544, 692, 534, 640, 558, 640, 534,
- 640, 540, 666, 534, 638, 1666, 638, 1636, 640, 550, 666, 534,
- 640, 540, 666, 534, 640, 540, 666, 536, 638, 540, 666, 536,
- 638, 550, 664, 536, 638, 540, 664, 536, 638, 540, 666, 534,
- 638, 1640, 664, 536, 692, 546, 664, 536, 664, 536, 664, 536,
- 664, 546, 612, 532, 636, 538, 664, 536, 664, 546, 612, 538,
- 638, 538, 638, 538, 664, 536, 690, 538, 662, 538, 664, 538,
- 662, 548, 664, 536, 662, 538, 662, 562, 638, 564, 636, 564,
- 636, 1668, 582, 556, 652, 572, 612, 568, 636, 564, 610, 570,
- 636, 556, 616, 550, 656, 566, 610, 570, 632, 578, 608, 1640,
- 662, 562, 642, 1686, 582, 570, 634, 566, 604, 576, 636, 566,
- 610, 578, 634, 1664, 584, 590, 660, 1636, 610, 1642, 664, 590,
- 610, 590, 636, 566, 634, 568, 686}; // UNKNOWN 9AD8CDB5
- uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0x87, 0xF6, 0x28, 0x60,
- 0x00, 0x20, 0x00, 0x00, 0x20,
- 0x00, 0x05, 0x0D};
-
- irsend.reset();
- irsend.sendRaw(rawData, 211, 38000);
- irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decode(&irsend.capture));
- ASSERT_EQ(ELECTRA_AC, irsend.capture.decode_type);
- EXPECT_EQ(kElectraAcBits, irsend.capture.bits);
- EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
-}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Fujitsu_test.cpp
deleted file mode 100644
index b895e4d9b..000000000
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Fujitsu_test.cpp
+++ /dev/null
@@ -1,560 +0,0 @@
-// Copyright 2017 Jonny Graham, David Conran
-
-#include "IRrecv_test.h"
-#include "IRsend.h"
-#include "IRsend_test.h"
-#include "ir_Fujitsu.h"
-#include "gtest/gtest.h"
-
-template
-::testing::AssertionResult ArraysMatch(const T (&expected)[size],
- const T* actual) {
- for (size_t i(0); i < size; ++i) {
- if (expected[i] != actual[i]) {
- int e = expected[i];
- int a = actual[i];
- return ::testing::AssertionFailure() << "array[" << i
- << "] (" << std::hex << a << std::dec << ") != expected[" << i
- << "] (" << std::hex << e << std::dec << ")";
- }
- }
- return ::testing::AssertionSuccess();
-}
-// Tests for Fujitsu A/C methods.
-
-// Test sending typical data only.
-TEST(TestIRFujitsuACClass, GetRawDefault) {
- IRFujitsuAC fujitsu = IRFujitsuAC(4); // AR-RAH2E
- fujitsu.setCmd(kFujitsuAcCmdTurnOn);
- fujitsu.setSwing(kFujitsuAcSwingBoth);
- fujitsu.setMode(kFujitsuAcModeCool);
- fujitsu.setFanSpeed(kFujitsuAcFanHigh);
- fujitsu.setTemp(24);
- uint8_t expected_arrah2e[16] = {
- 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
- 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD};
- EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw()));
- EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), "
- "Swing: Vert + Horiz, Command: N/A", fujitsu.toString());
-
- uint8_t expected_ardb1[15] = {
- 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
- 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x1D};
- fujitsu.setModel(ARDB1);
- EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw()));
- EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), "
- "Swing: Vert + Horiz, Command: N/A", fujitsu.toString());
-}
-
-TEST(TestIRFujitsuACClass, GetRawTurnOff) {
- IRFujitsuAC fujitsu = IRFujitsuAC(4);
- fujitsu.setModel(ARRAH2E);
- fujitsu.off();
- uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD};
- EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw()));
- EXPECT_EQ(kFujitsuAcStateLengthShort, fujitsu.getStateLength());
- EXPECT_EQ("Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), "
- "Swing: Vert + Horiz, Command: N/A", fujitsu.toString());
-
- fujitsu.setModel(ARDB1);
- uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02};
- EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw()));
- EXPECT_EQ(kFujitsuAcStateLengthShort - 1, fujitsu.getStateLength());
- EXPECT_EQ("Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), "
- "Swing: Vert + Horiz, Command: N/A", fujitsu.toString());
-}
-
-TEST(TestIRFujitsuACClass, GetRawStepHoriz) {
- IRFujitsuAC fujitsu = IRFujitsuAC(4);
- fujitsu.stepHoriz();
- uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x79, 0x86};
- EXPECT_TRUE(ArraysMatch(expected, fujitsu.getRaw()));
- EXPECT_EQ(kFujitsuAcStateLengthShort, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), "
- "Swing: Vert + Horiz, Command: Step vane horizontally",
- fujitsu.toString());
-}
-
-TEST(TestIRFujitsuACClass, GetRawStepVert) {
- IRFujitsuAC fujitsu = IRFujitsuAC(4);
- fujitsu.setModel(ARRAH2E);
- fujitsu.stepVert();
- uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C, 0x93};
- EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw()));
- EXPECT_EQ(kFujitsuAcStateLengthShort, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), "
- "Swing: Vert + Horiz, Command: Step vane vertically",
- fujitsu.toString());
-
- fujitsu.setModel(ARDB1);
- fujitsu.stepVert();
- uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C};
- EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw()));
- EXPECT_EQ(kFujitsuAcStateLengthShort - 1,
- fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), "
- "Swing: Vert + Horiz, Command: Step vane vertically",
- fujitsu.toString());
-}
-
-TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) {
- IRFujitsuAC fujitsu = IRFujitsuAC(4);
- fujitsu.setCmd(kFujitsuAcCmdStayOn);
- fujitsu.setSwing(kFujitsuAcSwingHoriz);
- fujitsu.setMode(kFujitsuAcModeCool);
- fujitsu.setFanSpeed(kFujitsuAcFanQuiet);
- fujitsu.setTemp(25);
- uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30,
- 0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB};
- EXPECT_TRUE(ArraysMatch(expected, fujitsu.getRaw()));
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 25C, Fan: 4 (QUIET), "
- "Swing: Horiz, Command: N/A",
- fujitsu.toString());
-}
-
-TEST(TestIRFujitsuACClass, GetRawWithFan) {
- IRFujitsuAC fujitsu = IRFujitsuAC(4);
- fujitsu.setCmd(kFujitsuAcCmdStayOn);
- fujitsu.setSwing(kFujitsuAcSwingHoriz);
- fujitsu.setMode(kFujitsuAcModeFan);
- fujitsu.setFanSpeed(kFujitsuAcFanMed);
- fujitsu.setTemp(20); // temp doesn't matter for fan
- // but it is sent by the RC anyway
- fujitsu.setModel(ARRAH2E);
- uint8_t expected_arrah2e[16] = {
- 0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30,
- 0x40, 0x3, 0x22, 0x0, 0x0, 0x0, 0x20, 0x4B};
- EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw()));
- EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 3 (FAN), Temp: 20C, Fan: 2 (MED), Swing: Horiz, "
- "Command: N/A", fujitsu.toString());
-
- fujitsu.setModel(ARDB1);
- uint8_t expected_ardb1[15] = {
- 0x14, 0x63, 0x0, 0x10, 0x10, 0xFC, 0x8, 0x30,
- 0x40, 0x3, 0x22, 0x0, 0x0, 0x0, 0x6B};
- EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw()));
- EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 3 (FAN), Temp: 20C, Fan: 2 (MED), Swing: Horiz, "
- "Command: N/A", fujitsu.toString());
-}
-
-TEST(TestIRFujitsuACClass, SetRaw) {
- IRFujitsuAC fujitsu = IRFujitsuAC(0);
- EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength());
- uint8_t expected_default_arrah2e[kFujitsuAcStateLength] = {
- 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
- 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD};
- EXPECT_TRUE(ArraysMatch(expected_default_arrah2e, fujitsu.getRaw()));
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), "
- "Swing: Vert + Horiz, Command: N/A", fujitsu.toString());
- // Now set a new state via setRaw();
- // This state is a real state from an AR-DB1 remote.
- uint8_t new_state1[kFujitsuAcStateLength - 1] = {
- 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
- 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9F};
- fujitsu.setRaw(new_state1, kFujitsuAcStateLength - 1);
- EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength());
- EXPECT_TRUE(ArraysMatch(new_state1, fujitsu.getRaw()));
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 0 (AUTO), "
- "Swing: Off, Command: N/A", fujitsu.toString());
-}
-
-TEST(TestSendFujitsuAC, GenerateMessage) {
- IRFujitsuAC fujitsu = IRFujitsuAC(4);
- IRsendTest irsend(4);
- fujitsu.begin();
- irsend.begin();
-
- fujitsu.setCmd(kFujitsuAcCmdStayOn);
- fujitsu.setSwing(kFujitsuAcSwingBoth);
- fujitsu.setMode(kFujitsuAcModeCool);
- fujitsu.setFanSpeed(kFujitsuAcFanHigh);
- fujitsu.setTemp(24);
-
- EXPECT_EQ(kFujitsuAcFanHigh, fujitsu.getFanSpeed());
- EXPECT_EQ(kFujitsuAcModeCool, fujitsu.getMode());
- EXPECT_EQ(24, fujitsu.getTemp());
- EXPECT_EQ(kFujitsuAcSwingBoth, fujitsu.getSwing());
- EXPECT_EQ(kFujitsuAcCmdStayOn, fujitsu.getCmd());
-
- irsend.reset();
- irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLength);
- EXPECT_EQ(
- "f38000d50"
- "m3324s1574"
- "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390"
- "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
- "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182"
- "m448s1182m448s390m448s390m448s1182m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s1182"
- "m448s1182m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s390"
- "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182"
- "m448s8100",
- irsend.outputStr());
-}
-
-TEST(TestSendFujitsuAC, GenerateShortMessage) {
- IRFujitsuAC fujitsu = IRFujitsuAC(4);
- IRsendTest irsend(4);
- fujitsu.begin();
- irsend.begin();
-
- fujitsu.off();
-
- EXPECT_EQ(kFujitsuAcCmdTurnOff, fujitsu.getCmd());
-
- irsend.reset();
- irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLengthShort);
- EXPECT_EQ(
- "f38000d50"
- "m3324s1574m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448"
- "s390m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s1182m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s1182m448"
- "s1182m448s1182m448s1182m448s1182m448s1182m448s8100",
- irsend.outputStr());
-}
-
-// Issue #275
-TEST(TestSendFujitsuAC, Issue275) {
- IRFujitsuAC fujitsu = IRFujitsuAC(4);
- IRsendTest irsend(4);
- fujitsu.begin();
- irsend.begin();
- irsend.reset();
-
- fujitsu.setCmd(kFujitsuAcCmdTurnOff);
- irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLengthShort);
- EXPECT_EQ(
- "f38000d50"
- // Header
- "m3324s1574"
- // 0 0 1 0 1 0 0 0 (0x28)
- "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390"
- // 1 1 0 0 0 1 1 0 (0xC6)
- "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390"
- // 0 0 0 0 0 0 0 0 (0x00)
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- // 0 0 0 0 1 0 0 0 (0x08)
- "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
- // 0 0 0 0 1 0 0 0 (0x08)
- "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
- // 0 1 0 0 0 0 0 0 (0x40)
- "m448s390m448s1182m448s390m448s390m448s390m448s390m448s390m448s390"
- // 1 0 1 1 1 1 1 1 (0xBF)
- "m448s1182m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182"
- // Footer
- "m448s8100", irsend.outputStr());
-
- irsend.reset();
- // Per report in Issue #275
- uint16_t off[115] = {
- 3350, 1650,
- 450, 400, 450, 450, 450, 1250, 450, 400, 450, 1250, 450, 400, 450, 400,
- 450, 400, 450, 1250, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 1250,
- 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400,
- 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400,
- 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400,
- 450, 400, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250,
- 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250,
- 450, 400, 450, 1250, 450, 1250, 450, 1250, 450, 1250, 450, 1250,
- 450, 1250, 450};
- irsend.sendRaw(off, 115, 38);
- EXPECT_EQ(
- "f38000d50"
- // Header
- "m3350s1650"
- // 0 0 1 0 1 0 0 0 (0x28)
- "m450s400m450s450m450s1250m450s400m450s1250m450s400m450s400m450s400"
- // 1 1 0 0 0 1 1 0 (0xC6)
- "m450s1250m450s1250m450s400m450s400m450s400m450s1250m450s1250m450s400"
- // 0 0 0 0 0 0 0 0 (0x00)
- "m450s400m450s400m450s400m450s400m450s400m450s400m450s400m450s400"
- // 0 0 0 0 1 0 0 0 (0x08)
- "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400"
- // 0 0 0 0 1 0 0 0 (0x08)
- "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400"
- // 0 1 0 0 0 0 0 0 (0x40)
- "m450s400m450s1250m450s400m450s400m450s400m450s400m450s400m450s400"
- // 1 0 1 1 1 1 1 1 (0xBF)
- "m450s1250m450s400m450s1250m450s1250m450s1250m450s1250m450s1250m450s1250"
- // Footer
- "m450",
- irsend.outputStr());
-}
-
-TEST(TestDecodeFujitsuAC, SyntheticShortMessages) {
- IRsendTest irsend(0);
- IRFujitsuAC fujitsu = IRFujitsuAC(0);
- IRrecv irrecv(0);
-
- irsend.begin();
- irsend.reset();
-
- fujitsu.setModel(ARRAH2E);
- fujitsu.setCmd(kFujitsuAcCmdTurnOff);
- irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength());
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decode(&irsend.capture));
- ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
- ASSERT_EQ(kFujitsuAcMinBits + 8, irsend.capture.bits);
- uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD};
- EXPECT_TRUE(ArraysMatch(expected_arrah2e, irsend.capture.state));
-
- irsend.reset();
-
- fujitsu.setModel(ARDB1);
- fujitsu.setCmd(kFujitsuAcCmdTurnOff);
- irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength());
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decode(&irsend.capture));
- ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
- ASSERT_EQ(kFujitsuAcMinBits, irsend.capture.bits);
- uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02};
- EXPECT_TRUE(ArraysMatch(expected_ardb1, irsend.capture.state));
-}
-
-TEST(TestDecodeFujitsuAC, SyntheticLongMessages) {
- IRsendTest irsend(0);
- IRFujitsuAC fujitsu = IRFujitsuAC(0);
- IRrecv irrecv(0);
- irsend.begin();
-
- irsend.reset();
-
- fujitsu.setModel(ARRAH2E);
- fujitsu.setCmd(kFujitsuAcCmdStayOn);
- fujitsu.setSwing(kFujitsuAcSwingVert);
- fujitsu.setMode(kFujitsuAcModeCool);
- fujitsu.setFanSpeed(kFujitsuAcFanQuiet);
- fujitsu.setTemp(18);
- irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength());
- ASSERT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength());
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decodeFujitsuAC(&irsend.capture));
- ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
- ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits);
- uint8_t expected_arrah2e[kFujitsuAcStateLength] = {
- 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
- 0x20, 0x01, 0x14, 0x00, 0x00, 0x00, 0x20, 0x7B};
- EXPECT_TRUE(ArraysMatch(expected_arrah2e, irsend.capture.state));
- fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8);
- EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 4 (QUIET), "
- "Swing: Vert, Command: N/A", fujitsu.toString());
-
- irsend.reset();
-
- fujitsu.setModel(ARDB1);
- irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength());
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decode(&irsend.capture));
- ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
- ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits);
- uint8_t expected_ardb1[kFujitsuAcStateLength - 1] = {
- 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
- 0x20, 0x01, 0x14, 0x00, 0x00, 0x00, 0x9B};
- EXPECT_TRUE(ArraysMatch(expected_ardb1, irsend.capture.state));
- fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8);
- EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 4 (QUIET), "
- "Swing: Vert, Command: N/A", fujitsu.toString());
-}
-
-TEST(TestDecodeFujitsuAC, RealShortARDB1OffExample) {
- IRsendTest irsend(0);
- IRrecv irrecv(0);
- IRFujitsuAC fujitsu = IRFujitsuAC(0);
-
- irsend.begin();
-
- irsend.reset();
- // "Off" Message recorded from an AR-DB1 remote.
- uint16_t rawData[99] = {
- 3310, 1636, 440, 386, 440, 394, 442, 1210, 442, 390, 414, 1220,
- 444, 390, 446, 380, 446, 380, 436, 1216, 438, 1214, 438, 388,
- 438, 386, 438, 396, 410, 1222, 440, 1220, 442, 384, 442, 384,
- 442, 384, 442, 382, 444, 382, 442, 382, 444, 380, 446, 380,
- 446, 380, 444, 380, 436, 390, 436, 388, 436, 388, 438, 1214,
- 438, 386, 438, 388, 438, 386, 440, 386, 440, 384, 442, 384,
- 442, 384, 442, 1210, 444, 382, 444, 382, 444, 382, 444, 380,
- 446, 1206, 436, 390, 436, 388, 436, 388, 438, 388, 438, 396,
- 420, 388, 436};
- irsend.sendRaw(rawData, 99, 38000);
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decode(&irsend.capture));
- ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
- ASSERT_EQ(kFujitsuAcMinBits, irsend.capture.bits);
- uint8_t expected[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02};
- EXPECT_TRUE(ArraysMatch(expected, irsend.capture.state));
- fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8);
- EXPECT_EQ(kFujitsuAcStateLengthShort - 1, fujitsu.getStateLength());
- EXPECT_EQ("Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), "
- "Swing: Off, Command: N/A", fujitsu.toString());
-}
-
-TEST(TestDecodeFujitsuAC, RealLongARDB1Example) {
- IRsendTest irsend(0);
- IRrecv irrecv(0);
- IRFujitsuAC fujitsu = IRFujitsuAC(0);
-
- irsend.begin();
- irsend.reset();
- uint16_t rawData1[243] = {
- 3316, 1632, 444, 390, 438, 388, 436, 1216, 438, 388, 438, 1214,
- 438, 388, 438, 386, 440, 386, 440, 1212, 440, 1210, 442, 392,
- 412, 396, 442, 392, 444, 1208, 444, 1208, 444, 380, 444, 380,
- 446, 380, 436, 390, 436, 390, 436, 390, 436, 388, 438, 388,
- 438, 388, 438, 388, 438, 386, 438, 386, 440, 384, 440, 1210,
- 442, 384, 442, 382, 442, 384, 442, 384, 442, 382, 442, 382,
- 444, 382, 444, 1208, 444, 382, 444, 380, 446, 380, 436, 390,
- 436, 390, 436, 1214, 438, 1214, 438, 1212, 440, 1212, 440, 1220,
- 412, 1222, 440, 394, 442, 382, 442, 382, 444, 1208, 444, 382,
- 444, 380, 446, 380, 446, 380, 434, 390, 436, 388, 438, 388,
- 438, 388, 438, 1214, 438, 1212, 440, 386, 440, 394, 412, 1222,
- 440, 394, 442, 384, 442, 384, 442, 382, 442, 1208, 444, 390,
- 414, 394, 442, 1216, 446, 380, 436, 390, 436, 390, 436, 388,
- 436, 390, 436, 388, 438, 386, 440, 386, 440, 386, 438, 1212,
- 440, 386, 440, 384, 440, 384, 442, 392, 412, 396, 440, 394,
- 442, 382, 444, 382, 444, 382, 444, 380, 444, 380, 444, 382,
- 444, 380, 446, 380, 436, 388, 436, 390, 436, 388, 438, 388,
- 438, 388, 438, 388, 438, 386, 440, 386, 440, 386, 442, 384,
- 440, 386, 442, 384, 440, 384, 442, 384, 442, 382, 442, 382,
- 444, 1208, 444, 382, 444, 1208, 444, 380, 446, 1206, 436, 390,
- 436, 1216, 436};
- irsend.sendRaw(rawData1, 243, 38000);
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decode(&irsend.capture));
- ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
- ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits);
- uint8_t expected1[kFujitsuAcStateLength - 1] = {
- 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
- 0x21, 0x01, 0x04, 0x00, 0x00, 0x00, 0xAA};
- EXPECT_TRUE(ArraysMatch(expected1, irsend.capture.state));
- fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8);
- EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 4 (QUIET), "
- "Swing: Off, Command: N/A", fujitsu.toString());
-
- irsend.reset();
- uint16_t rawData2[243] = {
- 3316, 1630, 436, 398, 438, 386, 438, 1212, 440, 384, 440, 1212,
- 442, 384, 442, 392, 414, 394, 442, 1218, 446, 1206, 436, 390,
- 436, 388, 438, 388, 438, 1214, 440, 1212, 440, 384, 442, 384,
- 442, 384, 442, 382, 444, 382, 444, 382, 444, 380, 446, 380,
- 444, 380, 436, 390, 436, 388, 438, 396, 418, 388, 438, 1232,
- 410, 396, 440, 394, 442, 384, 442, 384, 442, 382, 442, 392,
- 414, 392, 444, 1216, 446, 380, 436, 390, 436, 396, 418, 390,
- 436, 398, 438, 1214, 440, 1212, 440, 1210, 442, 1208, 444, 1216,
- 416, 1218, 444, 388, 436, 390, 436, 388, 438, 1214, 440, 386,
- 438, 386, 440, 386, 440, 384, 442, 384, 442, 384, 442, 382,
- 444, 382, 444, 1206, 446, 1206, 436, 390, 436, 388, 438, 388,
- 438, 386, 440, 394, 410, 396, 440, 1220, 442, 1210, 442, 392,
- 414, 394, 442, 1218, 446, 406, 410, 388, 436, 390, 436, 390,
- 436, 388, 438, 386, 440, 386, 440, 386, 440, 386, 440, 384,
- 442, 384, 442, 384, 442, 382, 444, 382, 444, 380, 446, 380,
- 446, 380, 436, 390, 436, 390, 436, 388, 438, 386, 438, 388,
- 438, 386, 440, 386, 440, 384, 442, 384, 442, 384, 442, 384,
- 442, 382, 444, 382, 444, 380, 446, 380, 446, 380, 436, 390,
- 436, 388, 436, 388, 438, 386, 438, 386, 440, 386, 440, 1212,
- 440, 1210, 442, 1210, 442, 1208, 444, 1208, 436, 390, 436, 388,
- 436, 1214, 440};
- irsend.sendRaw(rawData2, 243, 38000);
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decode(&irsend.capture));
- ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
- ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits);
- uint8_t expected2[kFujitsuAcStateLength - 1] = {
- 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
- 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9F};
- EXPECT_TRUE(ArraysMatch(expected2, irsend.capture.state));
- fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8);
- EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 0 (AUTO), "
- "Swing: Off, Command: N/A", fujitsu.toString());
-}
-
-TEST(TestDecodeFujitsuAC, Issue414) {
- IRsendTest irsend(0);
- IRrecv irrecv(0);
- IRFujitsuAC fujitsu = IRFujitsuAC(0);
-
- // Capture as supplied by arpmota
- uint16_t rawData[259] = {3352, 1574, 480, 350, 480, 346, 480, 1190, 458, 346,
- 508, 1140, 480, 346, 506, 346, 458, 346, 480, 1168, 480, 1192, 452, 374,
- 458, 346, 480, 346, 508, 1168, 480, 1140, 480, 346, 506, 346, 458, 346,
- 480, 346, 480, 346, 480, 346, 484, 372, 454, 374, 456, 346, 508, 318,
- 480, 374, 458, 374, 480, 318, 480, 1196, 452, 346, 480, 346, 484, 342,
- 484, 346, 480, 374, 458, 346, 506, 318, 508, 1170, 452, 346, 480, 374,
- 458, 346, 506, 318, 480, 1196, 452, 1190, 458, 1162, 480, 1196, 452,
- 1170, 480, 1190, 458, 1164, 480, 1196, 480, 318, 508, 346, 456, 1192,
- 480, 346, 456, 374, 452, 346, 480, 374, 458, 342, 484, 346, 508, 346,
- 456, 342, 512, 1164, 458, 1164, 508, 346, 456, 346, 480, 1190, 456, 342,
- 484, 346, 506, 346, 456, 374, 452, 346, 508, 346, 458, 1164, 508, 346,
- 458, 374, 452, 1168, 480, 374, 480, 318, 480, 374, 456, 346, 508, 318,
- 480, 346, 484, 374, 480, 318, 484, 342, 484, 374, 480, 318, 484, 342,
- 484, 346, 508, 318, 508, 346, 458, 346, 506, 318, 480, 374, 458, 346,
- 506, 318, 480, 346, 484, 374, 480, 318, 482, 372, 456, 346, 508, 318,
- 506, 348, 456, 342, 484, 346, 508, 318, 484, 374, 480, 318, 508, 318,
- 484, 346, 508, 318, 480, 374, 456, 346, 508, 346, 480, 318, 480, 346,
- 484, 374, 480, 320, 484, 1164, 508, 346, 458, 342, 512, 1164, 458, 1190,
- 454, 346, 484, 1164, 508, 346, 458, 1164, 480, 350, 480, 374, 480};
- uint8_t state[16] = {
- 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, 0x81, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x20, 0x2B};
- irsend.begin();
- irsend.reset();
- irsend.sendRaw(rawData, 259, 38000);
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decode(&irsend.capture));
- ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
- ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits);
- EXPECT_TRUE(ArraysMatch(state, irsend.capture.state));
- fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8);
- EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength());
- EXPECT_EQ("Power: On, Mode: 4 (HEAT), Temp: 24C, Fan: 0 (AUTO), "
- "Swing: Off, Command: N/A", fujitsu.toString());
-
- // Resend it using the state this time.
- irsend.reset();
- irsend.sendFujitsuAC(state, 16);
- irsend.makeDecodeResult();
- EXPECT_TRUE(irrecv.decode(&irsend.capture));
- ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
- ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits);
- EXPECT_TRUE(ArraysMatch(state, irsend.capture.state));
- EXPECT_EQ(
- "f38000d50"
- "m3324s1574"
- "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390"
- "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
- "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182"
- "m448s1182m448s390m448s390m448s1182m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390"
- "m448s1182m448s390m448s390m448s390m448s390m448s390m448s390m448s1182"
- "m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
- "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s390"
- "m448s1182m448s1182m448s390m448s1182m448s390m448s1182m448s390m448s390"
- "m448s8100", irsend.outputStr());
-}
diff --git a/lib/IRremoteESP8266-2.6.0/.github/CONTRIBUTING.md b/lib/IRremoteESP8266-2.6.5/.github/CONTRIBUTING.md
similarity index 90%
rename from lib/IRremoteESP8266-2.6.0/.github/CONTRIBUTING.md
rename to lib/IRremoteESP8266-2.6.5/.github/CONTRIBUTING.md
index 9614d90a5..20bb97d94 100644
--- a/lib/IRremoteESP8266-2.6.0/.github/CONTRIBUTING.md
+++ b/lib/IRremoteESP8266-2.6.5/.github/CONTRIBUTING.md
@@ -33,8 +33,8 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r
#### Before Submitting A Bug Report
-* **Check the [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide).** You might be able to find the cause of the problem and fix it yourself. Most importantly, check if you can reproduce the problem in the latest version (a.k.a. 'master') of the library.
-* **Perform a [cursory search](https://github.com/issues?q=+is%3Aissue+repo%3Amarkszabo/IRremoteESP8266)** to see if the problem is already reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one.
+* **Check the [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide).** You might be able to find the cause of the problem and fix it yourself. Most importantly, check if you can reproduce the problem in the latest version (a.k.a. 'master') of the library.
+* **Perform a [cursory search](https://github.com/issues?q=+is%3Aissue+repo%3Acrankyoldgit/IRremoteESP8266)** to see if the problem is already reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Bug Report?
@@ -53,7 +53,7 @@ Provide more context by answering these questions:
* **Can you reproduce the problem in one of the code examples?**
* **Did the problem start happening recently** (e.g. after updating to a new version of Arduino or the library) or was this always a problem?
-* If the problem started happening recently, **can you reproduce the problem in an older version of the library?** What's the most recent version in which the problem doesn't happen? You can download older versions of the library from [the releases page](https://github.com/markszabo/IRremoteESP8266/releases).
+* If the problem started happening recently, **can you reproduce the problem in an older version of the library?** What's the most recent version in which the problem doesn't happen? You can download older versions of the library from [the releases page](https://github.com/crankyoldgit/IRremoteESP8266/releases).
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
Include details about your configuration, circuit and environment:
diff --git a/lib/IRremoteESP8266-2.6.0/.github/Contributors.md b/lib/IRremoteESP8266-2.6.5/.github/Contributors.md
similarity index 86%
rename from lib/IRremoteESP8266-2.6.0/.github/Contributors.md
rename to lib/IRremoteESP8266-2.6.5/.github/Contributors.md
index af9734d69..a4958fe70 100644
--- a/lib/IRremoteESP8266-2.6.0/.github/Contributors.md
+++ b/lib/IRremoteESP8266-2.6.5/.github/Contributors.md
@@ -2,7 +2,7 @@
### Main contributors & maintainers
- [Mark Szabo](https://github.com/markszabo/) : Initial IR sending on ESP8266
- [SƩbastien Warin](https://github.com/sebastienwarin/) (http://sebastien.warin.fr) : Initial IR receiving on ESP8266
-- [David Conran](https://github.com/crankyoldgit/)
+- [David Conran](https://github.com/crankyoldgit/) : ESP32 support and pretty much everything else.
- [Roi Dayan](https://github.com/roidayan/)
- [Marcos de Alcântara Marinho](https://github.com/marcosamarinho/)
- [Massimiliano Pinto](https://github.com/pintomax/)
@@ -15,6 +15,6 @@
- [Fabien Valthier](https://github.com/hcoohb)
- [Ajay Pala](https://github.com/ajaypala/)
-All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors).
+All contributors can be found on the [contributors site](https://github.com/crankyoldgit/IRremoteESP8266/graphs/contributors).
### Contributors of the [original project](https://github.com/z3t0/Arduino-IRremote) can be found on the [original project's contributors page](https://github.com/z3t0/Arduino-IRremote/blob/master/Contributors.md)
diff --git a/lib/IRremoteESP8266-2.6.0/.github/issue_template.md b/lib/IRremoteESP8266-2.6.5/.github/issue_template.md
similarity index 77%
rename from lib/IRremoteESP8266-2.6.0/.github/issue_template.md
rename to lib/IRremoteESP8266-2.6.5/.github/issue_template.md
index 024a0398c..d9b80dab6 100644
--- a/lib/IRremoteESP8266-2.6.0/.github/issue_template.md
+++ b/lib/IRremoteESP8266-2.6.5/.github/issue_template.md
@@ -1,6 +1,6 @@
-_(Please use this template for reporting issues. You can delete what ever is not relevant. Giving us this information will help us help you faster. Please also read the [FAQ](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions) & [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide). Your problem may already have an answer there.)_
+_(Please use this template for reporting issues. You can delete what ever is not relevant. Giving us this information will help us help you faster. Please also read the [FAQ](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions) & [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide). Your problem may already have an answer there.)_
-### Version/revison of the library used
+### Version/revision of the library used
_Typically located in the `library.json` & `src/IRremoteESP8266.h` files in the root directory of the library.
e.g. v2.0.0, or 'master' as at 1st of June, 2017. etc._
@@ -30,9 +30,9 @@ _What can we do to (pref. reliably) repeat what is happening?_
_Include all relevant code snippets or links to the actual code files. Tip: [How to quote your code so it is still readable](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code)._
#### Circuit diagram and hardware used (if applicable)
-_Link to an image of the circuit diagram used. Part number of the IR receiver module etc._
+_Link to an image of the circuit diagram used. Part number of the IR receiver module etc. ESP8266 or ESP32 board type._
-### I have followed the steps in the [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide) & read the [FAQ](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions)
+### I have followed the steps in the [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide) & read the [FAQ](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions)
_Yes/No._
### Has this library/code previously worked as expected for you?
diff --git a/lib/IRremoteESP8266-2.6.0/.gitignore b/lib/IRremoteESP8266-2.6.5/.gitignore
similarity index 91%
rename from lib/IRremoteESP8266-2.6.0/.gitignore
rename to lib/IRremoteESP8266-2.6.5/.gitignore
index 23e21ca3e..c02171953 100644
--- a/lib/IRremoteESP8266-2.6.0/.gitignore
+++ b/lib/IRremoteESP8266-2.6.5/.gitignore
@@ -8,8 +8,12 @@
# vi/vim
**/*.swp
+# vscode
+.vscode
+
## Build environments
# Platformio
+**/.pio/
**/.pioenvs/
**/.piolibdeps/
**/.clang_complete
@@ -44,3 +48,6 @@ tools/mode2_decode
#Cygwin builds
*.exe
+
+# Mac extended attributes
+.DS_Store
diff --git a/lib/IRremoteESP8266-2.6.0/.gitmodules b/lib/IRremoteESP8266-2.6.5/.gitmodules
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/.gitmodules
rename to lib/IRremoteESP8266-2.6.5/.gitmodules
diff --git a/lib/IRremoteESP8266-2.6.0/.style.yapf b/lib/IRremoteESP8266-2.6.5/.style.yapf
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/.style.yapf
rename to lib/IRremoteESP8266-2.6.5/.style.yapf
diff --git a/lib/IRremoteESP8266-2.6.5/.travis.yml b/lib/IRremoteESP8266-2.6.5/.travis.yml
new file mode 100644
index 000000000..e8bf3d832
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/.travis.yml
@@ -0,0 +1,74 @@
+language: c
+env:
+ - BD=esp8266:esp8266:nodemcuv2:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled
+ # - BD=esp8266:esp8266:d1_mini:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled
+before_install:
+ - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
+ - sleep 3
+ - export DISPLAY=:1.0
+ - wget http://downloads.arduino.cc/arduino-1.8.8-linux64.tar.xz
+ - tar xf arduino-1.8.8-linux64.tar.xz
+ - sudo mv arduino-1.8.8 /usr/local/share/arduino
+ - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
+ - wget https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py
+install:
+ - ln -s $PWD /usr/local/share/arduino/libraries/
+ - git clone https://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WiFiManager
+ - git clone https://github.com/knolleary/pubsubclient.git /usr/local/share/arduino/libraries/PubSubClient
+ - git clone https://github.com/bblanchon/ArduinoJson.git --branch 5.x /usr/local/share/arduino/libraries/ArduinoJson
+ - arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs
+ - arduino --install-boards esp8266:esp8266
+ - arduino --board $BD --save-prefs
+ - arduino --pref "compiler.warning_level=all" --save-prefs
+ - sudo apt-get install jq
+ - sudo apt-get purge python-enum34
+ - sudo apt-get install pylint3
+script: echo Running checks
+notifications:
+ email:
+ on_success: change
+ on_failure: change
+jobs:
+ include:
+ - script:
+ # Check that everything compiles. (Part 1)
+ - arduino --verify --board $BD $PWD/examples/IRrecvDemo/IRrecvDemo.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/IRGCSendDemo/IRGCSendDemo.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/IRGCTCPServer/IRGCTCPServer.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/IRServer/IRServer.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/IRrecvDumpV2/IRrecvDumpV2.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/IRsendDemo/IRsendDemo.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino 2> /dev/null
+ - script:
+ # Check that everything compiles. (Part 2)
+ - arduino --verify --board $BD $PWD/examples/IRsendProntoDemo/IRsendProntoDemo.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/LGACSend/LGACSend.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/IRMQTTServer/IRMQTTServer.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/ControlSamsungAC/ControlSamsungAC.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/DumbIRRepeater/DumbIRRepeater.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/SmartIRRepeater/SmartIRRepeater.ino 2> /dev/null
+ - arduino --verify --board $BD $PWD/examples/CommonAcControl/CommonAcControl.ino 2> /dev/null
+ - script:
+ # Check the version numbers match.
+ - LIB_VERSION=$(egrep "^#define\s+_IRREMOTEESP8266_VERSION_\s+" src/IRremoteESP8266.h | cut -d\" -f2)
+ - test ${LIB_VERSION} == "$(jq -r .version library.json)"
+ - grep -q "^version=${LIB_VERSION}$" library.properties
+ # Check the tools programs compile.
+ - (cd tools; make all)
+ # Check for lint issues.
+ - shopt -s nullglob
+ - python cpplint.py --extensions=c,cc,cpp,ino --headers=h,hpp {src,test,tools}/*.{h,c,cc,cpp,hpp,ino} examples/*/*.{h,c,cc,cpp,hpp,ino}
+ - pylint3 -d F0001 {src,test,tools}/*.py
+ - shopt -u nullglob
+ # Build and run the unit tests.
+ - (cd test; make run)
+ - (cd tools; make run_tests)
diff --git a/lib/IRremoteESP8266-2.6.0/CPPLINT.cfg b/lib/IRremoteESP8266-2.6.5/CPPLINT.cfg
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/CPPLINT.cfg
rename to lib/IRremoteESP8266-2.6.5/CPPLINT.cfg
diff --git a/lib/IRremoteESP8266-2.6.0/LICENSE.txt b/lib/IRremoteESP8266-2.6.5/LICENSE.txt
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/LICENSE.txt
rename to lib/IRremoteESP8266-2.6.5/LICENSE.txt
diff --git a/lib/IRremoteESP8266-2.6.0/README.md b/lib/IRremoteESP8266-2.6.5/README.md
similarity index 62%
rename from lib/IRremoteESP8266-2.6.0/README.md
rename to lib/IRremoteESP8266-2.6.5/README.md
index 1eaaa21b4..c4cb31515 100644
--- a/lib/IRremoteESP8266-2.6.0/README.md
+++ b/lib/IRremoteESP8266-2.6.5/README.md
@@ -1,18 +1,19 @@
# IRremote ESP8266 Library
-[](https://travis-ci.org/markszabo/IRremoteESP8266)
+[](https://travis-ci.org/crankyoldgit/IRremoteESP8266)
[](https://www.ardu-badge.com/IRremoteESP8266)
-[](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Average time to resolve an issue")
-[](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Percentage of issues still open")
-[](https://gitlicense.com/license/markszabo/IRremoteESP8266)
+[](http://isitmaintained.com/project/crankyoldgit/IRremoteESP8266 "Average time to resolve an issue")
+[](http://isitmaintained.com/project/crankyoldgit/IRremoteESP8266 "Percentage of issues still open")
+[](https://gitlicense.com/license/crankyoldgit/IRremoteESP8266)
-This library enables you to **send _and_ receive** infra-red signals on an [ESP8266 using the Arduino framework](https://github.com/esp8266/Arduino) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* etc.
+This library enables you to **send _and_ receive** infra-red signals on an [ESP8266](https://github.com/esp8266/Arduino) or an
+[ESP32](https://github.com/espressif/arduino-esp32) using the [Arduino framework](https://www.arduino.cc/) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* demodulators etc.
-## v2.6.0 Now Available
-Version 2.6.0 of the library is now [available](https://github.com/markszabo/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
+## v2.6.5 Now Available
+Version 2.6.4 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
#### Upgrading from pre-v2.0
-Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/markszabo/IRremoteESP8266/wiki/Upgrading-to-v2.0) page.
+Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page.
#### Upgrading from pre-v2.5
The library has changed from using constants declared as `#define` to
@@ -29,11 +30,15 @@ something you likely should not have. You should be able to quickly determine
the new name from the old. e.g. `CONSTANT_NAME` to `kConstantName`.
Use common sense or examining the library's code if this does affect code.
+## Supported protocols
+You can find the details of which protocols & devices are supported
+[here](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md).
+
## Troubleshooting
-Before reporting an issue or asking for help, please try to follow our [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide) first.
+Before reporting an issue or asking for help, please try to follow our [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide) first.
## Frequently Asked Questions
-Some common answers to common questions and problems are on our [F.A.Q. wiki page](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions).
+Some common answers to common questions and problems are on our [F.A.Q. wiki page](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions).
## Installation
##### Official releases via the Arduino IDE v1.8+ (Windows & Linux)
@@ -43,7 +48,7 @@ Some common answers to common questions and problems are on our [F.A.Q. wiki pag
1. Select the version you wish to install and click _"Install"_.
##### Manual Installation for Windows
-1. Click on _"Clone or Download"_ button, then _"[Download ZIP](https://github.com/markszabo/IRremoteESP8266/archive->master.zip)"_ on the page.
+1. Click on _"Clone or Download"_ button, then _"[Download ZIP](https://github.com/crankyoldgit/IRremoteESP8266/archive->master.zip)"_ on the page.
1. Extract the contents of the downloaded zip file.
1. Rename the extracted folder to _"IRremoteESP8266"_.
1. Move this folder to your libraries directory. (under windows: `C:\Users\YOURNAME\Documents\Arduino\libraries\`)
@@ -53,7 +58,7 @@ Some common answers to common questions and problems are on our [F.A.Q. wiki pag
##### Using Git to install library ( Linux )
```
cd ~/Arduino/libraries
-git clone https://github.com/markszabo/IRremoteESP8266.git
+git clone https://github.com/crankyoldgit/IRremoteESP8266.git
```
###### To Update to the latest version of the library
```
@@ -74,6 +79,6 @@ Available [here](.github/Contributors.md)
## Library History
This library was originally based on Ken Shirriff's work (https://github.com/shirriff/Arduino-IRremote/)
-[Mark Szabo](https://github.com/markszabo/IRremoteESP8266) has updated the IRsend class to work on ESP8266 and [Sebastien Warin](https://github.com/sebastienwarin/IRremoteESP8266) the receiving & decoding part (IRrecv class).
+[Mark Szabo](https://github.com/crankyoldgit/IRremoteESP8266) has updated the IRsend class to work on ESP8266 and [Sebastien Warin](https://github.com/sebastienwarin/IRremoteESP8266) the receiving & decoding part (IRrecv class).
As of v2.0, the library was almost entirely re-written with the ESP8266's resources in mind.
diff --git a/lib/IRremoteESP8266-2.6.0/ReleaseNotes.md b/lib/IRremoteESP8266-2.6.5/ReleaseNotes.md
similarity index 69%
rename from lib/IRremoteESP8266-2.6.0/ReleaseNotes.md
rename to lib/IRremoteESP8266-2.6.5/ReleaseNotes.md
index 98416a12a..5672d2483 100644
--- a/lib/IRremoteESP8266-2.6.0/ReleaseNotes.md
+++ b/lib/IRremoteESP8266-2.6.5/ReleaseNotes.md
@@ -1,5 +1,146 @@
# Release Notes
+## _v2.6.5 (20190828)_
+
+**[Bug Fixes]**
+- IRMQTTServer: Remove duplicate MQTT_CLIMATE from HA discovery (#869)
+- Fujitsu: Ensure `on()` is called in common a/c framework. (#862)
+- Update `strToModel()` (#861)
+- IRMQTTServer: Add missing header file. (#858)
+- IRMQTTServer: Fix a compile error when HTML_PASSWORD_ENABLE is enabled. (#856)
+
+**[Features]**
+- IRrecv: Allow tolerance percentage to be set at run-time. (#865)
+- Basic support for Daikin152 A/C protocol. (#874)
+- Teco: Add light, humid, & save support. (#871)
+- Detailed support for Amcor A/C protocol. (#836, #854)
+- IRMQTTServer: Add ability to report Vcc at the ESP chip. (#845)
+- Gree: Add timer support. (#849)
+- IRac/Mitsubishi A/C: Support wide `swingh_t` mode (#844)
+- IRMQTTServer: Generate protocol and bit size html selects (#838)
+
+**[Misc]**
+- New example code to show how to use the `IRac` class to control A/Cs (#839)
+- Improve/fix `swingh_t::kWide` support (#846)
+- Kelvinator: Optimise code a little to save space. (#843)
+
+
+## _v2.6.4 (20190726)_
+
+**[Bug Fixes]**
+- Fix some swing problems with the Mitsubishi HAVC protocol (#831)
+- Fix parameter ordering for Gree in common a/c code. (#815)
+- Fix parameters for Coolix in IRac::sendAc() (#829)
+- IRMQTTServer: Fix sending >64 bit codes. (#811)
+
+**[Features]**
+- Daikin128: Full detailed support & common a/c support. (#832)
+- Midea: Support native temp units of Celsius & SwingV. (#823)
+- Gree: Support `YBOFB` models and bug fix. (#815)
+- Pioneer: Fix sendPioneer with Pioneer specific timings (#830)
+- Daikin128: Initial support for Daikin 17 Series/BRC52B63 (#828)
+- Coolix: Better `toCommon()` support. (#825)
+- Experimental detailed support for Daikin 176 bits (#816)
+- Add setting of output options to A/C classes. (#808)
+- Add invert flag support to Samsung AC (#807)
+
+**[Misc]**
+- Daikin176: making some change on Daikin176 to work with IRMQTTServer (#826)
+- Reduce duplicate code to save (3K+) space. (#813)
+- Daikin176: Experiment Daikin176bits with IRMQTTServer (#824)
+- Update platformio.ini files for PlatformIO v4.0.0 (#812)
+- Change repo URLs to new location. (#806)
+- Move `htmlEscape()` to the IRutils namespace (#801)
+
+
+## _v2.6.3 (20190704)_
+
+**[Bug Fixes]**
+- IRMQTTServer: REPLAY_DECODED_AC_MESSAGE not working. (#784, #797)
+- ESP32: Ensure `IRrecv`'s GPIO is set to input mode. (#774)
+
+**[Features]**
+- IRMQTTServer: Show available sketch space for OTA uploads. (#795)
+- Experimental detailed support for Electra/AUX protocol (#788)
+- IRMQTTServer: Ability to resend existing climate state via MQTT & HTTP (#784)
+- Daikin160: Add detailed & common a/c support. (#777)
+- Experimental detailed support for Neoclima protocol. (#767)
+- Gree: add WiFi and IFeel bits (#770)
+- Handle A/Cs with toggles better. (#758)
+- IRMQTTServer: Allow sending/receiving climate via JSON over MQTT. (#763)
+
+**[Misc]**
+- Move converting of IR A/C messages out of example code. (#798)
+- Reduce example code size and complexity (#790)
+- Change `ControlSamsungAC` example to not use `sendExtended()` (#792)
+- IRMQTTServer: Add MQTT_CLIMATE_IR_SEND_ON_RESTART compile-time flag. (#784)
+- Refactor A/C's toString()'s to reduce code size. Saves ~3.5k (#782)
+- Add sanity tests for unexpected conditions in IRrecv. (#773)
+- IRMQTTServer: Fixed the HA config documentation (missing '-') (#776)
+- Improve `mkkeywords` tool. (#766)
+- Refactor with generic decode routines in `IRrecv` class. Saves ~7k. (#765)
+
+
+## _v2.6.2 (20190616)_
+
+**[Features]**
+- Initial support for the ESP32 architecture & boards. (#742)
+- Add changable GPIO settings to IRMQTTServer. (#730)
+- IRMQTTServer: Enforce a repeat for all Coolix calls (#752)
+- Basic DAIKIN 160bit send and decode. (#754)
+- Add example code for a Smart(er) IR Repeater. (#740)
+- Enforce Samsung A/C Quiet & Powerful mutual exclusivity.
+
+**[Misc]**
+- IRMQTTServer: Add some memory alloc safety checks. (#749)
+- Move some ToString() functions to IRac.cpp (#748)
+- Increase tolerance value for TCL112AC protocol. (#745)
+- Fix compiler warning in IRutils_test.cpp (#756)
+- Scrape Supported Protocols and generate SupportedProtocols.md (#755)
+- Make supported device info more organised. (#753)
+
+
+## _v2.6.1 (20190609)_
+
+**[Breaking Changes]**
+- Major rework/breaking changes to Argo A/C support. (#705)
+
+**[Bug Fixes]**
+- Correct `set/getQuiet` for Samsung A/C (#736)
+- Add missing `on/off()` to IRCoolixAC class. (#725)
+- Daikin `set/getEye()` uses wrong bit. (#711)
+- IRMQTTServer: Continue to use same Temperature units. (#710)
+- Fixed a bug with `setMode()`/`getMode()` for HAIER_AC. (#705)
+
+**[Features]**
+- Add set/getPowerful for Samsung A/C (#736)
+- Add `calibrate()` to all the A/C classes. (#735)
+- IRMQTTServer: Add sequencing for sending MQTT IR commands. (#723)
+- Add support for Fujitsu AR-REB1E & AR-JW2 remotes. (#718)
+- Add Beta `decodeTrotec()` support. (#719)
+- Add experimental `decodeArgo()` support. (#717)
+- Support for Goodweather A/Cs. (#715)
+- Add `DISABLE_CAPTURE_WHILE_TRANSMITTING` feature to IRMQTTServer. (#713)
+- Support for Lixil Inax Toilet protocol. (#712)
+- Add `set/getWeeklyTimerEnable()` to Daikin (#711)
+- IRMQTTServer: Update Common A/C settings based on received IR messages. (#705)
+- Add day of week to DAIKIN protocol (#699)
+- Add limited support for Sharp A/C (#696)
+- SAMSUNG_AC: Make sure special power mode messages are sent. (#695)
+- Add `set/getPowerful()` (turbo) to DAIKIN216 (#693)
+
+**[Misc]**
+- Add kPeriodOffset for CPU Freq of 160MHz. (#729)
+- Example code for a Dumb IR repeater. (#737)
+- Update swing handling for Fujitsu A/Cs. (#724)
+- Add function to convert `decode_results` to `sendRaw()` array. (#721)
+- Attempt to reduce heap fragmentation from strings. (#707)
+- Update Fujitsu A/C example code to safer settings (#716)
+- Enforce better `const` usage in IRUtils. (#708)
+- Attempt to reduce heap fragmentation by A/C `toString()`s. (#694)
+- Minor changes to DAIKIN216 timings and features. (#693)
+
+
## _v2.6.0 (20190430)_
**[Bug Fixes]**
diff --git a/lib/IRremoteESP8266-2.6.5/SupportedProtocols.md b/lib/IRremoteESP8266-2.6.5/SupportedProtocols.md
new file mode 100644
index 000000000..c9d286973
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/SupportedProtocols.md
@@ -0,0 +1,141 @@
+
+# IR Protocols supported by this library
+
+| Protocol | Brand | Model | A/C Model | Detailed A/C Support |
+| --- | --- | --- | --- | --- |
+| [Aiwa](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Aiwa.cpp) | **Aiwa** | RC-T501 RCU | | - |
+| [Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.cpp) | **[Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.h)** | ADR-853H A/C ADR-853H A/C TAC-444 remote TAC-444 remote TAC-495 remote TAC-495 remote | | Yes |
+| [Argo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Argo.cpp) | **[Argo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Argo.h)** | Ulisse 13 DCI Mobile Split A/C | | Yes |
+| [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **Carrier/Surrey** | 42QG5A55970 remote 53NGK009/012 Inverter 619EGX0090E0 A/C 619EGX0120E0 A/C 619EGX0180E0 A/C 619EGX0220E0 A/C | | - |
+| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Beko](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | BINR 070/071 split-type A/C BINR 070/071 split-type A/C RG57K7(B)/BGEF Remote RG57K7(B)/BGEF Remote | | Yes |
+| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | MS12FU-10HRDN1-QRD0GW(B) A/C MS12FU-10HRDN1-QRD0GW(B) A/C MSABAU-07HRFN1-QRD0GW A/C (circa 2016) MSABAU-07HRFN1-QRD0GW A/C (circa 2016) RG52D/BGE Remote RG52D/BGE Remote | | Yes |
+| [Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.cpp) | **[Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.h)** | 17 Series A/C (DAIKIN128) ARC423A5 remote ARC433** remote ARC433B69 remote ARC477A1 remote ARC480A5 remote (DAIKIN152) BRC4C153 remote BRC52B63 remote (DAIKIN128) FTE12HV2S A/C FTXB09AXVJU A/C (DAIKIN128) FTXB12AXVJU A/C (DAIKIN128) FTXZ25NV1B A/C FTXZ35NV1B A/C FTXZ50NV1B A/C | | Yes |
+| [Denon](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Denon.cpp) | **Unknown** | | | - |
+| [Dish](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Dish.cpp) | **DISH NETWORK** | echostar 301 | | - |
+| [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[AUX](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | KFR-35GW/BpNFW=3 A/C YKR-T/011 remote | | Yes |
+| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-DB1 remote AR-RAE1E remote AR-RAH2E remote AR-REB1E remote AST9RSGCW A/C ASYG30LFCA A/C ASYG7LMCA A/C | ARDB1 ARJW2 ARRAH2E ARREB1E | Yes |
+| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-JW2 remote | ARDB1 ARJW2 ARRAH2E ARREB1E | Yes |
+| [GICable](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **Unknown** | | | - |
+| [GlobalCache](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GlobalCache.cpp) | **Unknown** | | | - |
+| [Goodweather](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Goodweather.cpp) | **[Goodweather](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Goodweather.h)** | ZH/JT-03 remote | | Yes |
+| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[EKOKAI](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | A/C | YAW1F YBOFB | Yes |
+| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | YBOFB remote YBOFB2 remote | YAW1F YBOFB | Yes |
+| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[RusClimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | EACS/I-09HAR_X/N3 A/C YAW1F remote | YAW1F YBOFB | Yes |
+| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Ultimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | Heat Pump | YAW1F YBOFB | Yes |
+| [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | HSU-09HMC203 A/C HSU07-HEA03 remote YR-W02 remote | | Yes |
+| [Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | LT0541-HTA remote RAS-35THA6 remote Series VI A/C (Circa 2007) | | Yes |
+| [Inax](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Inax.cpp) | **Lixil** | Inax DT-BA283 Toilet | | - |
+| [JVC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_JVC.cpp) | **Unknown** | | | - |
+| [Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.h)** | YAPOF3 remote | | Yes |
+| [Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.cpp) | **[Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.h)** | KSV26CRC A/C KSV26HRC A/C KSV35CRC A/C KSV35HRC A/C KSV53HRC A/C KSV62HRC A/C KSV70CRC A/C KSV70HRC A/C KSV80HRC A/C YALIF Remote | | Yes |
+| [LG](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.cpp) | **[LG](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.h)** | 6711A20083V remote 6711A20083V remote AKB74395308 remote AKB74395308 remote | | Yes |
+| [Lasertag](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Lasertag.cpp) | **Unknown** | | | - |
+| [Lego](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Lego.cpp) | **LEGO Power Functions** | IR Receiver | | - |
+| [Lutron](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Lutron.cpp) | **Unknown** | | | - |
+| [MWM](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MWM.cpp) | **Unknown** | | | - |
+| [Magiquest](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Magiquest.cpp) | **[Unknown](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Magiquest.h)** | | | Yes |
+| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Comfee](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | MPD1-12CRN7 A/C | | Yes |
+| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Keystone](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57H4(B)BGEF remote | | Yes |
+| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Pioneer System](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RUBO18GMFILCAD A/C (18K BTU) RYBO12GMFILCAD A/C (12K BTU) | | Yes |
+| [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | HC3000 Projector TV | | Yes |
+| [MitsubishiHeavy](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.cpp) | **[Mitsubishi Heavy Industries](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.h)** | RKX502A001C remote RLA502A700B remote SRKxxZJ-S A/C SRKxxZM-S A/C SRKxxZMXA-S A/C | | Yes |
+| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Yamaha](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | RAV561 remote RXV585B A/V Receiver | | Yes |
+| [Neoclima](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Neoclima.cpp) | **[Neoclima](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Neoclima.h)** | NS-09AHTI A/C NS-09AHTI A/C ZH/TY-01 remote ZH/TY-01 remote | | Yes |
+| [Nikai](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Nikai.cpp) | **Unknown** | | | - |
+| [Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.cpp) | **[Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.h)** | A75C2311 remote (CKP) A75C3704 remote A75C3747 remote A75C3747 remote A75C3747 remote A75C3747 remote CKP series A/C CS-ME10CKPG A/C CS-ME12CKPG A/C CS-ME14CKPG A/C CS-YW9MKD A/C CS-Z9RKR A/C DKE series A/C JKE series A/C NKE series A/C RKR series A/C TV | CKP DKE JKE LKE NKE RKR | Yes |
+| [Pioneer](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Pioneer.cpp) | **Unknown** | | | - |
+| [Pronto](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Pronto.cpp) | **Unknown** | | | - |
+| [RC5_RC6](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp) | **Unknown** | | | - |
+| [RCMM](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RCMM.cpp) | **Microsoft** | XBOX 360 | | - |
+| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AR12HSSDBWKNEU A/C AR12KSFPEWQNET A/C IEC-R03 remote UA55H6300 TV | | Yes |
+| [Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **Unknown** | | | - |
+| [Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AY-ZP40KR A/C LC-52D62U TV | | Yes |
+| [Sherwood](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sherwood.cpp) | **Sherwood** | RC-138 remote RD6505(B) Receiver | | - |
+| [Sony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sony.cpp) | **Unknown** | | | - |
+| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Leberg](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | LBS-TOR07 A/C | | Yes |
+| [Teco](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.cpp) | **[Alaska](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.h)** | SAC9010QC A/C SAC9010QC remote | | Yes |
+| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II RAS 18SKP-ES RAS-B13N3KV2 RAS-B13N3KVP-E WC-L03SE WH-TA04NE | | Yes |
+| [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Unknown](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | | | Yes |
+| [Vestel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Vestel.cpp) | **[Vestel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Vestel.h)** | BIOX CXP-9 A/C (9K BTU) | | Yes |
+| [Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.cpp) | **[Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.h)** | DG11J1-04 remote DG11J1-3A remote DG11J1-91 remote SPIS409L A/C SPIS412L A/C SPIW409L A/C SPIW412L A/C SPIW418L A/C | DG11J13A DG11J191 | Yes |
+| [Whynter](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whynter.cpp) | **Whynter** | ARC-110WD A/C | | - |
+
+
+## Send only protocols:
+
+- GLOBALCACHE
+- PRONTO
+- RAW
+- SHERWOOD
+
+
+## Send & decodable protocols:
+
+- AIWA_RC_T501
+- AMCOR
+- ARGO
+- CARRIER_AC
+- COOLIX
+- DAIKIN
+- DAIKIN128
+- DAIKIN152
+- DAIKIN160
+- DAIKIN176
+- DAIKIN2
+- DAIKIN216
+- DENON
+- DISH
+- ELECTRA_AC
+- FUJITSU_AC
+- GICABLE
+- GOODWEATHER
+- GREE
+- HAIER_AC
+- HAIER_AC_YRW02
+- HITACHI_AC
+- HITACHI_AC1
+- HITACHI_AC2
+- INAX
+- JVC
+- KELVINATOR
+- LASERTAG
+- LEGOPF
+- LG
+- LG2
+- LUTRON
+- MAGIQUEST
+- MIDEA
+- MITSUBISHI
+- MITSUBISHI2
+- MITSUBISHI_AC
+- MITSUBISHI_HEAVY_152
+- MITSUBISHI_HEAVY_88
+- MWM
+- NEC
+- NEC_LIKE
+- NEOCLIMA
+- NIKAI
+- PANASONIC
+- PANASONIC_AC
+- PIONEER
+- RC5
+- RC5X
+- RC6
+- RCMM
+- SAMSUNG
+- SAMSUNG36
+- SAMSUNG_AC
+- SANYO
+- SANYO_LC7461
+- SHARP
+- SHARP_AC
+- SONY
+- TCL112AC
+- TECO
+- TOSHIBA_AC
+- TROTEC
+- VESTEL_AC
+- WHIRLPOOL_AC
+- WHYNTER
diff --git a/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/CommonAcControl.ino b/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/CommonAcControl.ino
new file mode 100644
index 000000000..6f0416b51
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/CommonAcControl.ino
@@ -0,0 +1,81 @@
+/* Copyright 2019 David Conran
+*
+* This example code demonstrates how to use the "Common" IRac class to control
+* various air conditions. The IRac class does not support all the features
+* for every protocol. Some have more detailed support that what the "Common"
+* interface offers, and some only have a limited subset of the "Common" options.
+*
+* This example code will:
+* o Try to turn on, then off every fully supported A/C protocol we know of.
+* o It will try to put the A/C unit into Cooling mode at 25C, with a medium
+* fan speed, and no fan swinging.
+* Note: Some protocols support multiple models, only the first model is tried.
+*
+*/
+#include
+#include
+#include
+#include
+
+const uint16_t kIrLed = 4; // The ESP GPIO pin to use that controls the IR LED.
+IRac ac(kIrLed); // Create a A/C object using GPIO to sending messages with.
+stdAc::state_t state; // Where we will store the desired state of the A/C.
+stdAc::state_t prev; // Where we will store the previous state of the A/C.
+
+void setup() {
+ Serial.begin(115200);
+ delay(200);
+
+ // Set up what we want to send.
+ // See state_t, opmode_t, fanspeed_t, swingv_t, & swingh_t in IRsend.h for
+ // all the various options.
+ state.protocol = decode_type_t::DAIKIN; // Set a protocol to use.
+ state.model = 1; // Some A/C's have different models. Let's try using just 1.
+ state.mode = stdAc::opmode_t::kCool; // Run in cool mode initially.
+ state.celsius = true; // Use Celsius for units of temp. False = Fahrenheit
+ state.degrees = 25; // 25 degrees.
+ state.fanspeed = stdAc::fanspeed_t::kMedium; // Start with the fan at medium.
+ state.swingv = stdAc::swingv_t::kOff; // Don't swing the fan up or down.
+ state.swingh = stdAc::swingh_t::kOff; // Don't swing the fan left or right.
+ state.light = false; // Turn off any LED/Lights/Display that we can.
+ state.beep = false; // Turn off any beep from the A/C if we can.
+ state.econo = false; // Turn off any economy modes if we can.
+ state.filter = false; // Turn off any Ion/Mold/Health filters if we can.
+ state.turbo = false; // Don't use any turbo/powerful/etc modes.
+ state.quiet = false; // Don't use any quiet/silent/etc modes.
+ state.sleep = -1; // Don't set any sleep time or modes.
+ state.clean = false; // Turn off any Cleaning options if we can.
+ state.clock = -1; // Don't set any current time if we can avoid it.
+ state.power = false; // Initially start with the unit off.
+
+ prev = state; // Make sure we have a valid previous state.
+}
+
+void loop() {
+ // For every protocol the library has ...
+ for (int i = 1; i < kLastDecodeType; i++) {
+ decode_type_t protocol = (decode_type_t)i;
+ // If the protocol is supported by the IRac class ...
+ if (ac.isProtocolSupported(protocol)) {
+ state.protocol = protocol; // Change the protocol used.
+
+ Serial.println("Protocol " + String(protocol) + " / " +
+ typeToString(protocol));
+ state.power = true; // We want to turn on the A/C unit.
+ // Have the IRac class create and send a message.
+ // We need a `prev` state as some A/Cs use toggle messages.
+ // e.g. On & Off are the same message. When given the previous state,
+ // it will try to do the correct thing for you.
+ ac.sendAc(state, &prev); // Construct and send the message.
+ Serial.println("Sent a message to turn ON the A/C unit.");
+ prev = state; // Copy new state over the previous one.
+ delay(5000); // Wait 5 seconds.
+ state.power = false; // Now we want to turn the A/C off.
+ ac.sendAc(state, &prev); // Construct and send the message.
+ Serial.println("Sent a message to turn OFF the A/C unit.");
+ prev = state; // Copy new state over the previous one.
+ delay(1000); // Wait 1 second.
+ }
+ }
+ Serial.println("Starting from the begining again ...");
+}
diff --git a/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/ControlSamsungAC.ino b/lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/ControlSamsungAC.ino
similarity index 79%
rename from lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/ControlSamsungAC.ino
rename to lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/ControlSamsungAC.ino
index df910fe87..4463013c1 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/ControlSamsungAC.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/ControlSamsungAC.ino
@@ -6,7 +6,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
-* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -23,9 +23,7 @@
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
@@ -57,31 +55,29 @@ void setup() {
}
void loop() {
- // Turn the A/C unit on and set to cooling mode.
- // Power changes require we send an extended message.
- Serial.println("Sending an extended IR command to A/C ...");
+ // Turn the A/C unit on
+ Serial.println("Turn on the A/C ...");
ac.on();
+ ac.send();
+ printState();
+ delay(15000); // wait 15 seconds
+ // and set to cooling mode.
+ Serial.println("Set the A/C mode to cooling ...");
ac.setMode(kSamsungAcCool);
- ac.sendExtended();
+ ac.send();
printState();
delay(15000); // wait 15 seconds
// Increase the fan speed.
- Serial.println("Sending a normal IR command to A/C ...");
+ Serial.println("Set the fan to high and the swing on ...");
ac.setFan(kSamsungAcFanHigh);
- ac.send();
- printState();
- delay(15000);
-
- // Change to swing the fan.
- Serial.println("Sending a normal IR command to A/C ...");
ac.setSwing(true);
ac.send();
printState();
delay(15000);
// Change to Fan mode, lower the speed, and stop the swing.
- Serial.println("Sending a normal IR command to A/C ...");
+ Serial.println("Set the A/C to fan only with a low speed, & no swing ...");
ac.setSwing(false);
ac.setMode(kSamsungAcFan);
ac.setFan(kSamsungAcFanLow);
@@ -90,10 +86,9 @@ void loop() {
delay(15000);
// Turn the A/C unit off.
- // Power changes require we send an extended message.
- Serial.println("Sending an extended IR command to A/C ...");
+ Serial.println("Turn off the A/C ...");
ac.off();
- ac.sendExtended();
+ ac.send();
printState();
delay(15000); // wait 15 seconds
}
diff --git a/lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/DumbIRRepeater.ino b/lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/DumbIRRepeater.ino
new file mode 100644
index 000000000..80f5ce64a
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/DumbIRRepeater.ino
@@ -0,0 +1,130 @@
+/*
+ * IRremoteESP8266: DumbIRRepeater.ino - Record and playback IR codes.
+ * Copyright 2019 David Conran (crankyoldgit)
+ *
+ * This program will try to capture incoming IR messages and replay them back.
+ * It doesn't use any of the advanced detection features, thus it will just
+ * replay the messages at fixed modulated frequency (kFrequency) and a 50% duty
+ * cycle.
+ *
+ * Note:
+ * This might NOT be the frequency of the incoming message, so some replayed
+ * messages may not work. The frequency of incoming messages & duty cycle is
+ * lost at the point of the Hardware IR demodulator. The ESP can't see it.
+ *
+ * W A R N I N G
+ * This code is just for educational/example use only. No help will be given
+ * to you to make it do something else, or to make it work with some
+ * weird device or circuit, or to make it more usable or practical.
+ * If it works for you. Great. If not, Congratulations on changing/fixing it.
+ *
+ * An IR detector/demodulator must be connected to the input, kRecvPin.
+ * An IR LED circuit must be connected to the output, kIrLedPin.
+ *
+ * Example circuit diagrams (both are needed):
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-receiving
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
+ *
+ * Common mistakes & tips:
+ * * Don't just connect the IR LED directly to the pin, it won't
+ * have enough current to drive the IR LED effectively.
+ * * Make sure you have the IR LED polarity correct.
+ * See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity
+ * * Some digital camera/phones can be used to see if the IR LED is flashed.
+ * Replace the IR LED with a normal LED if you don't have a digital camera
+ * when debugging.
+ * * Avoid using the following pins unless you really know what you are doing:
+ * * Pin 0/D3: Can interfere with the boot/program mode & support circuits.
+ * * Pin 1/TX/TXD0: Any serial transmissions from the ESP will interfere.
+ * * Pin 3/RX/RXD0: Any serial transmissions to the ESP will interfere.
+ * * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
+ * for your first time. e.g. ESP-12 etc.
+ *
+ * Changes:
+ * Version 1.0: June, 2019
+ * - Initial version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+// ==================== start of TUNEABLE PARAMETERS ====================
+
+// The GPIO an IR detector/demodulator is connected to. Recommended: 14 (D5)
+const uint16_t kRecvPin = 14;
+
+// GPIO to use to control the IR LED circuit. Recommended: 4 (D2).
+const uint16_t kIrLedPin = 4;
+
+// The Serial connection baud rate.
+// NOTE: Make sure you set your Serial Monitor to the same speed.
+const uint32_t kBaudRate = 115200;
+
+// As this program is a special purpose capture/resender, let's use a larger
+// than expected buffer so we can handle very large IR messages.
+// i.e. Up to 512 bits.
+const uint16_t kCaptureBufferSize = 1024;
+
+// kTimeout is the Nr. of milli-Seconds of no-more-data before we consider a
+// message ended.
+const uint8_t kTimeout = 50; // Milli-Seconds
+
+// kFrequency is the modulation frequency all messages will be replayed at.
+const uint16_t kFrequency = 38000; // in Hz. e.g. 38kHz.
+
+// ==================== end of TUNEABLE PARAMETERS ====================
+
+// The IR transmitter.
+IRsend irsend(kIrLedPin);
+// The IR receiver.
+IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, false);
+// Somewhere to store the captured message.
+decode_results results;
+
+// This section of code runs only once at start-up.
+void setup() {
+ irrecv.enableIRIn(); // Start up the IR receiver.
+ irsend.begin(); // Start up the IR sender.
+
+ Serial.begin(kBaudRate, SERIAL_8N1);
+ while (!Serial) // Wait for the serial connection to be establised.
+ delay(50);
+ Serial.println();
+
+ Serial.print("DumbIRRepeater is now running and waiting for IR input "
+ "on Pin ");
+ Serial.println(kRecvPin);
+ Serial.print("and will retransmit it on Pin ");
+ Serial.println(kIrLedPin);
+}
+
+// The repeating section of the code
+void loop() {
+ // Check if an IR message has been received.
+ if (irrecv.decode(&results)) { // We have captured something.
+ // The capture has stopped at this point.
+
+ // Convert the results into an array suitable for sendRaw().
+ // resultToRawArray() allocates the memory we need for the array.
+ uint16_t *raw_array = resultToRawArray(&results);
+ // Find out how many elements are in the array.
+ uint16_t length = getCorrectedRawLength(&results);
+ // Send it out via the IR LED circuit.
+ irsend.sendRaw(raw_array, length, kFrequency);
+ // Resume capturing IR messages. It was not restarted until after we sent
+ // the message so we didn't capture our own message.
+ irrecv.resume();
+ // Deallocate the memory allocated by resultToRawArray().
+ delete [] raw_array;
+
+ // Display a crude timestamp & notification.
+ uint32_t now = millis();
+ Serial.printf(
+ "%06u.%03u: A message that was %d entries long was retransmitted.\n",
+ now / 1000, now % 1000, length);
+ }
+ yield(); // Or delay(milliseconds); This ensures the ESP doesn't WDT reset.
+}
diff --git a/lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/IRGCSendDemo.ino
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/IRGCSendDemo.ino
rename to lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/IRGCSendDemo.ino
index 03c80e18b..0b6ea5e84 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/IRGCSendDemo.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/IRGCSendDemo.ino
@@ -17,7 +17,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
- * https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -36,9 +36,7 @@
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/IRGCTCPServer.ino
similarity index 97%
rename from lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/IRGCTCPServer.ino
rename to lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/IRGCTCPServer.ino
index 69f7299fb..b69373d34 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/IRGCTCPServer.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/IRGCTCPServer.ino
@@ -37,10 +37,13 @@
* can check your wifi router for it's address.
*/
-#ifndef UNIT_TEST
#include
-#endif
+#if defined(ESP8266)
#include
+#endif // ESP8266
+#if defined(ESP32)
+#include
+#endif // ESP32
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.h b/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.h
similarity index 50%
rename from lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.h
rename to lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.h
index 9494dbe2b..73821dc05 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.h
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.h
@@ -5,6 +5,9 @@
#ifndef EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_
#define EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_
+#if defined(ESP8266)
+#include
+#endif // ESP8266
#include
#include
#include
@@ -18,17 +21,38 @@
#define MQTT_ENABLE true // Whether or not MQTT is used at all.
#endif // MQTT_ENABLE
+#ifndef EXAMPLES_ENABLE
+// Whether or not examples are included. `false` saves ~2.5K of program space.
+#define EXAMPLES_ENABLE true
+#endif // EXAMPLES_ENABLE
+
// ---------------------- Board Related Settings -------------------------------
// NOTE: Make sure you set your Serial Monitor to the same speed.
#define BAUD_RATE 115200 // Serial port Baud rate.
-// GPIO the IR LED is connected to/controlled by. GPIO 4 = D2.
-#define IR_LED 4 // <=- CHANGE_ME (optional)
-// define IR_LED 3 // For an ESP-01 we suggest you use RX/GPIO3/Pin 7.
+// Change if you need multiple independent send gpios & topics. (MQTT only)
+const uint8_t kNrOfIrTxGpios = 1;
+// Default GPIO the IR LED is connected to/controlled by. GPIO 4 = D2.
+// For an ESP-01 we suggest you use RX/GPIO3/Pin 7. i.e. kDefaultIrLed = 3
+// Note: A value of -1 means unused.
+const int8_t kDefaultIrLed = 4; // <=- CHANGE_ME (optional)
-// GPIO the IR RX module is connected to/controlled by. e.g. GPIO 14 = D5.
-// Comment this out to disable receiving/decoding IR messages entirely.
-#define IR_RX 14 // <=- CHANGE_ME (optional)
+// **DANGER** Optional flag to invert the output. (default = false)
+// `false`: The LED is illuminated when the GPIO is HIGH.
+// `true`: The LED is illuminated when GPIO is LOW rather than HIGH.
+// Setting this to something other than the default could
+// easily destroy your IR LED if you are overdriving it.
+// Unless you *REALLY* know what you are doing, don't change this.
+const bool kInvertTxOutput = false;
+
+// Default GPIO the IR demodulator is connected to/controlled by. GPIO 14 = D5.
+const int8_t kDefaultIrRx = 14; // <=- CHANGE_ME (optional)
+
+// Enable/disable receiving/decoding IR messages entirely.
+// Note: IR_RX costs about 40k+ of program memory.
+#define IR_RX true
+
+// Should we use PULLUP on the IR Rx gpio?
#define IR_RX_PULLUP false
// --------------------- Network Related Settings ------------------------------
@@ -49,6 +73,8 @@ const IPAddress kSubnetMask = IPAddress(255, 255, 255, 0);
// before we will connect.
// The unset default is 8%.
// (Uncomment to enable)
+// Do you want/need mdns enabled? (https://en.wikipedia.org/wiki/Multicast_DNS)
+#define MDNS_ENABLE true // `false` to disable and save ~21k of program space.
// ----------------------- HTTP Related Settings -------------------------------
#define FIRMWARE_OTA true // Allow remote update of the firmware via http.
@@ -56,8 +82,9 @@ const IPAddress kSubnetMask = IPAddress(255, 255, 255, 0);
// Note: Firmware OTA is also disabled until
// a password is set.
#define HTML_PASSWORD_ENABLE false // Protect access to the HTML interface.
- // Note: OTA update is always passworded.
-// If you do not set a password, Firmware OTA updates will be blocked.
+ // Note: OTA & GPIO updates are always
+ // passworded.
+// If you do not set a password, Firmware OTA & GPIO updates will be blocked.
// ----------------------- MQTT Related Settings -------------------------------
#if MQTT_ENABLE
@@ -71,13 +98,29 @@ const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries.
#define MQTT_CLIMATE "ac" // Sub-topic for the climate topics.
#define MQTT_CLIMATE_CMND "cmnd" // Sub-topic for the climate command topics.
#define MQTT_CLIMATE_STAT "stat" // Sub-topic for the climate stat topics.
-#define MQTTbroadcastInterval 10 * 60 // Seconds between rebroadcasts
+// Enable sending/receiving climate via JSON. `true` cost ~5k of program space.
+#define MQTT_CLIMATE_JSON false
+// Do we send an IR message when we reboot and recover the existing A/C state?
+// If set to `false` you may miss requested state changes while the ESP was
+// down. If set to `true`, it will resend the previous desired state sent to the
+// A/C. Depending on your circumstances, you may need to change this.
+#define MQTT_CLIMATE_IR_SEND_ON_RESTART false
+#define MQTTbroadcastInterval 10 * 60 // Seconds between rebroadcasts.
#define QOS 1 // MQTT broker should queue up any unreceived messages for us
// #define QOS 0 // MQTT broker WON'T queue up messages for us. Fire & Forget.
+// Enable(true)/Disable(false) the option to send a MQTT Discovery message for
+// the AirCon/Climate system to Home Assistant. `false` saves ~1.5k.
+#define MQTT_DISCOVERY_ENABLE true
#endif // MQTT_ENABLE
// ------------------------ IR Capture Settings --------------------------------
+// Should we stop listening for IR messages when we send a message via IR?
+// Set this to `true` if your IR demodulator is picking up self transmissions.
+// Use `false` if it isn't or can't see the self-sent transmissions
+// Using `true` may mean some incoming IR messages are lost or garbled.
+// i.e. `false` is better if you can get away with it.
+#define DISABLE_CAPTURE_WHILE_TRANSMITTING true
// Let's use a larger than normal buffer so we can handle AirCon remote codes.
const uint16_t kCaptureBufferSize = 1024;
#if DECODE_AC
@@ -94,17 +137,38 @@ const uint16_t kMinUnknownSize = 2 * 10;
#define REPORT_RAW_UNKNOWNS false // Report the whole buffer, recommended:
// MQTT_MAX_PACKET_SIZE of 1024 or more
-// ------------------------ Advanced Usage Only --------------------------------
-// Change if you need multiple independent send gpio/topics.
-const uint8_t gpioTable[] = {
- IR_LED, // Default GPIO. e.g. ir_server/send or ir_server/send_0
- // Uncomment the following as needed.
- // NOTE: Remember to disable DEBUG if you are using one of the serial pins.
- // 5, // GPIO 5 / D1 e.g. ir_server/send_1
- // 14, // GPIO 14 / D5 e.g. ir_server/send_2
- // 16, // GPIO 16 / D0 e.g. ir_server/send_3
-};
+// Should we use and report individual A/C settings we capture via IR if we
+// can understand the individual settings of the remote.
+// e.g. Aquire the A/C settings from an actual A/C IR remote and override
+// any local settings set via MQTT/HTTP etc.
+#define USE_DECODED_AC_SETTINGS true // `false` to disable. `true` to enable.
+// Should we allow or ignore an A/C IR remote to override the A/C protocol/model
+// as set via MQTT or HTTP?
+// e.g. If `true`, you can use any fully supported A/C remote to control
+// another brand's or model's A/C unit. `false` means change to the new
+// protocol/model if we support it via `USE_DECODED_AC_SETTINGS`.
+#define IGNORE_DECODED_AC_PROTOCOL true
+// Do we (re-)send the captured & decoded A/C message via the IR_LED?
+// `false` if you don't want to repeat the captured message.
+// e.g. Useful if the IR demodulator is located in the path between the remote
+// and the A/C unit so the command isn't sent twice.
+// `true` if you want it sent anyway.
+// e.g. The IR demodulator is in a completely different location than than the
+// actual a/c unit.
+#define REPLAY_DECODED_AC_MESSAGE false
+// ------------------------ Advanced Usage Only --------------------------------
+
+// Reports the input voltage to the ESP chip. **NOT** the input voltage
+// to the development board (e.g. NodeMCU, D1 Mini etc) which are typically
+// powered by USB (5V) which is then lowered to 3V via a Low Drop Out (LDO)
+// Voltage regulator. Hence, this feature is turned off by default as it
+// make little sense for most users as it really isn't the actual input voltage.
+// E.g. For purposes of monitoring a battery etc.
+// Note: Turning on the feature costs ~250 bytes of prog space.
+#define REPORT_VCC false // Do we report Vcc via html info page & MQTT?
+
+// Keywords for MQTT topics, html arguments, or config file.
#define KEY_PROTOCOL "protocol"
#define KEY_MODEL "model"
#define KEY_POWER "power"
@@ -119,10 +183,12 @@ const uint8_t gpioTable[] = {
#define KEY_BEEP "beep"
#define KEY_ECONO "econo"
#define KEY_SLEEP "sleep"
-#define KEY_CLOCK "clock"
#define KEY_FILTER "filter"
#define KEY_CLEAN "clean"
#define KEY_CELSIUS "use_celsius"
+#define KEY_JSON "json"
+#define KEY_RESEND "resend"
+#define KEY_VCC "vcc"
// HTML arguments we will parse for IR code information.
#define KEY_TYPE "type" // KEY_PROTOCOL is also checked too.
@@ -130,6 +196,10 @@ const uint8_t gpioTable[] = {
#define KEY_BITS "bits"
#define KEY_REPEAT "repeats"
+// GPIO html/config keys
+#define KEY_TX_GPIO "tx"
+#define KEY_RX_GPIO "rx"
+
// Text for Last Will & Testament status messages.
const char* kLwtOnline = "Online";
const char* kLwtOffline = "Offline";
@@ -140,24 +210,39 @@ const uint8_t kUsernameLength = 15;
const uint8_t kPasswordLength = 20;
// -------------------------- Debug Settings -----------------------------------
-// Disable debug output if any of the IR pins are on the TX (D1) pin.
-// Note: This is a crude method to catch the common use cases.
-// See `isSerialGpioUsedByIr()` for the better method.
-#if (IR_LED != 1 && IR_RX != 1)
+// Debug output is disabled if any of the IR pins are on the TX (D1) pin.
+// See `isSerialGpioUsedByIr()`.
+// Note: Debug costs ~6k of program space.
#ifndef DEBUG
-#define DEBUG true // Change to 'false' to disable all serial output.
+#define DEBUG false // Change to 'true' for serial debug output.
#endif // DEBUG
-#else // (IR_LED != 1 && IR_RX != 1)
-#undef DEBUG
-#define DEBUG false
-#endif
// ----------------- End of User Configuration Section -------------------------
// Constants
-#define _MY_VERSION_ "v1.0.0"
+#define _MY_VERSION_ "v1.3.4"
+
+const uint8_t kRebootTime = 15; // Seconds
+const uint8_t kQuickDisplayTime = 2; // Seconds
+
+// Common bit sizes for the simple protocols.
+const uint8_t kCommonBitSizes[] = {
+ 12, 13, 15, 16, 20, 24, 28, 32, 35, 36, 42, 48, 56, 64};
+// Gpio related
+#if defined(ESP8266)
+const int8_t kTxGpios[] = {-1, 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16};
+const int8_t kRxGpios[] = {-1, 0, 1, 2, 3, 4, 5, 12, 13, 14, 15};
+#endif // ESP8266
+#if defined(ESP32)
+// Ref: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
+const int8_t kTxGpios[] = {
+ -1, 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23,
+ 25, 26, 27, 32, 33};
+const int8_t kRxGpios[] = {
+ -1, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23,
+ 25, 26, 27, 32, 33, 34, 35, 36, 39};
+#endif // ESP32
-const uint8_t kSendTableSize = sizeof(gpioTable);
// JSON stuff
// Name of the json config file in SPIFFS.
const char* kConfigFile = "/config.json";
@@ -169,47 +254,94 @@ const char* kMqttPrefixKey = "mqtt_prefix";
const char* kHostnameKey = "hostname";
const char* kHttpUserKey = "http_user";
const char* kHttpPassKey = "http_pass";
+const char* kCommandDelimiter = ",";
+
+// URLs
+const char* kUrlRoot = "/";
+const char* kUrlAdmin = "/admin";
+const char* kUrlAircon = "/aircon";
+const char* kUrlSendDiscovery = "/send_discovery";
+const char* kUrlExamples = "/examples";
+const char* kUrlGpio = "/gpio";
+const char* kUrlGpioSet = "/gpio/set";
+const char* kUrlInfo = "/info";
+const char* kUrlReboot = "/quitquitquit";
+const char* kUrlWipe = "/reset";
#if MQTT_ENABLE
const uint32_t kBroadcastPeriodMs = MQTTbroadcastInterval * 1000; // mSeconds.
const uint32_t kStatListenPeriodMs = 5 * 1000; // mSeconds
+const int32_t kMaxPauseMs = 10000; // 10 Seconds.
+const char* kSequenceDelimiter = ";";
+const char kPauseChar = 'P';
+#if defined(ESP8266)
+const uint32_t kChipId = ESP.getChipId();
+#endif // ESP8266
+#if defined(ESP32)
+const uint32_t kChipId = ESP.getEfuseMac(); // Discard the top 16 bits.
+#endif // ESP32
+
+const char* kClimateTopics =
+ "(" KEY_PROTOCOL "|" KEY_MODEL "|" KEY_POWER "|" KEY_MODE "|" KEY_TEMP "|"
+ KEY_FANSPEED "|" KEY_SWINGV "|" KEY_SWINGH "|" KEY_QUIET "|"
+ KEY_TURBO "|" KEY_LIGHT "|" KEY_BEEP "|" KEY_ECONO "|" KEY_SLEEP "|"
+ KEY_FILTER "|" KEY_CLEAN "|" KEY_CELSIUS "|" KEY_RESEND
+#if MQTT_CLIMATE_JSON
+ "|" KEY_JSON
+#endif // MQTT_CLIMATE_JSON
+ ") ";
void mqttCallback(char* topic, byte* payload, unsigned int length);
String listOfCommandTopics(void);
void handleSendMqttDiscovery(void);
void subscribing(const String topic_name);
void unsubscribing(const String topic_name);
-void mqttLog(const String mesg);
+void mqttLog(const char* str);
+bool mountSpiffs(void);
bool reconnect(void);
void receivingMQTT(String const topic_name, String const callback_str);
void callback(char* topic, byte* payload, unsigned int length);
void sendMQTTDiscovery(const char *topic);
void doBroadcast(TimerMs *timer, const uint32_t interval,
- const commonAcState_t state, const bool retain,
+ const stdAc::state_t state, const bool retain,
const bool force);
+#if MQTT_CLIMATE_JSON
+stdAc::state_t jsonToState(const stdAc::state_t current, const String str);
+void sendJsonState(const stdAc::state_t state, const String topic,
+ const bool retain = false, const bool ha_mode = true);
+#endif // MQTT_CLIMATE_JSON
#endif // MQTT_ENABLE
+#if REPORT_VCC
+String vccToString(void);
+#endif // REPORT_VCC
bool isSerialGpioUsedByIr(void);
void debug(const char *str);
void saveWifiConfigCallback(void);
void saveWifiConfig(void);
void loadWifiConfigFile(void);
+void doRestart(const char* str, const bool serial_only = false);
String msToHumanString(uint32_t const msecs);
String timeElapsed(uint32_t const msec);
String timeSince(uint32_t const start);
-String listOfSendGpios(void);
+String gpioToString(const int16_t gpio);
+uint8_t getDefaultIrSendIdx(void);
+IRsend* getDefaultIrSendPtr(void);
+int8_t getDefaultTxGpio(void);
+String listOfTxGpios(void);
bool hasUnsafeHTMLChars(String input);
+String htmlHeader(const String title, const String h1_text = "");
+String htmlEnd(void);
+String htmlButton(const String url, const String button,
+ const String text = "");
String htmlMenu(void);
void handleRoot(void);
String addJsReloadUrl(const String url, const uint16_t timeout_s,
const bool notify);
void handleExamples(void);
-String boolToString(const bool value);
-String opmodeToString(const stdAc::opmode_t mode);
-String fanspeedToString(const stdAc::fanspeed_t speed);
-String swingvToString(const stdAc::swingv_t swingv);
-String swinghToString(const stdAc::swingh_t swingh);
String htmlSelectBool(const String name, const bool def);
-String htmlSelectProtocol(const String name, const decode_type_t def);
+String htmlSelectClimateProtocol(const String name, const decode_type_t def);
+String htmlSelectAcStateProtocol(const String name, const decode_type_t def,
+ const bool simple);
String htmlSelectModel(const String name, const int16_t def);
String htmlSelectMode(const String name, const stdAc::opmode_t def);
String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def);
@@ -221,7 +353,7 @@ void handleAdmin(void);
void handleInfo(void);
void handleReset(void);
void handleReboot(void);
-bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType,
+bool parseStringAndSendAirCon(IRsend *irsend, const decode_type_t irType,
const String str);
uint16_t countValuesInStr(const String str, char sep);
uint16_t * newCodeArray(const uint16_t size);
@@ -241,18 +373,21 @@ void setup_wifi(void);
void init_vars(void);
void setup(void);
void loop(void);
+uint32_t maxSketchSpace(void);
uint64_t getUInt64fromHex(char const *str);
-bool sendIRCode(IRsend *irsend, int const ir_type,
+bool sendIRCode(IRsend *irsend, decode_type_t const ir_type,
uint64_t const code, char const * code_str, uint16_t bits,
uint16_t repeat);
bool sendInt(const String topic, const int32_t num, const bool retain);
bool sendBool(const String topic, const bool on, const bool retain);
bool sendString(const String topic, const String str, const bool retain);
bool sendFloat(const String topic, const float_t temp, const bool retain);
-commonAcState_t updateClimate(commonAcState_t current, const String str,
+stdAc::state_t updateClimate(stdAc::state_t current, const String str,
const String prefix, const String payload);
-bool cmpClimate(const commonAcState_t a, const commonAcState_t b);
-bool sendClimate(const commonAcState_t prev, const commonAcState_t next,
+bool cmpClimate(const stdAc::state_t a, const stdAc::state_t b);
+bool sendClimate(const stdAc::state_t prev, const stdAc::state_t next,
const String topic_prefix, const bool retain,
- const bool forceMQTT, const bool forceIR);
+ const bool forceMQTT, const bool forceIR,
+ const bool enableIR = true);
+bool decodeCommonAc(const decode_results *decode);
#endif // EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.ino b/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.ino
similarity index 66%
rename from lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.ino
rename to lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.ino
index 31e40432d..730a8965f 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.ino
@@ -7,11 +7,13 @@
* resources. I'm *NOT* claiming complete Copyright ownership of all the code.
* Likewise, feel free to borrow from this as much as you want.
*
- * NOTE: An IR LED circuit SHOULD be connected to ESP8266 GPIO4 (D2) if
- * you want to send IR messages.
- * A compatible IR RX modules SHOULD be connected to ESP8266 GPIO14 (D5)
- * if you want to capture & decode IR nessages.
- * See 'IR_LED' & 'IR_RX' in IRMQTTServer.h.
+ * NOTE: An IR LED circuit SHOULD be connected to the ESP if
+ * you want to send IR messages. e.g. GPIO4 (D2)
+ * A compatible IR RX modules SHOULD be connected to ESP
+ * if you want to capture & decode IR nessages. e.g. GPIO14 (D5)
+ * See 'IR_RX' in IRMQTTServer.h.
+ * GPIOs are configurable from the http:///gpio
+ * page.
*
* WARN: This is *very* advanced & complicated example code. Not for beginners.
* You are strongly suggested to try & look at other example code first
@@ -29,21 +31,25 @@
*
* - Arduino IDE:
* o Install the following libraries via Library Manager
- * - ArduinoJson (https://arduinojson.org/) (Version >= 5.x and < 6)
+ * - ArduinoJson (https://arduinojson.org/) (Version >= 5.0 and < 6.0)
* - PubSubClient (https://pubsubclient.knolleary.net/)
- * - WiFiManager (https://github.com/tzapu/WiFiManager) (Version >= 0.14)
+ * - WiFiManager (https://github.com/tzapu/WiFiManager)
+ * (ESP8266: Version >= 0.14, ESP32: 'development' branch.)
* o You MUST change to have the following (or larger) value:
* (with REPORT_RAW_UNKNOWNS 1024 or more is recommended)
* #define MQTT_MAX_PACKET_SIZE 768
+ * o Use the smallest non-zero SPIFFS size you can for your board.
+ * (See the Tools -> Flash Size menu)
+ *
* - PlatformIO IDE:
* If you are using PlatformIO, this should already been done for you in
* the accompanying platformio.ini file.
*
* ## First Boot (Initial setup)
- * The ESP8266 board will boot into the WiFiManager's AP mode.
+ * The ESP board will boot into the WiFiManager's AP mode.
* i.e. It will create a WiFi Access Point with a SSID like: "ESP123456" etc.
* Connect to that SSID. Then point your browser to http://192.168.4.1/ and
- * configure the ESP8266 to connect to your desired WiFi network and associated
+ * configure the ESP to connect to your desired WiFi network and associated
* required settings. It will remember these details on next boot if the device
* connects successfully.
* More information can be found here:
@@ -55,6 +61,9 @@
* ## Normal Use (After initial setup)
* Enter 'http:///gpio page to configure the GPIOs
+ * for the IR LED(s) and/or IR RX demodulator.
+ *
* You can send URLs like the following, with similar data type limitations as
* the MQTT formating in the next section. e.g:
* http:///ir?type=7&code=E0E09966
@@ -102,6 +111,19 @@
* bit/byte size you want to send as some A/C units have units
* have different sized messages. e.g. Fujitsu A/C units.
*
+ * Sequences.
+ * You can send a sequence of IR messages via MQTT using the above methods
+ * if you separate them with a ';' character. In addition you can add a
+ * pause/gap between sequenced messages by using 'P' followed immediately by
+ * the number of milliseconds you wish to wait (up to a max of kMaxPauseMs).
+ * e.g. 7,E0E09966;4,f50,12
+ * Send a Samsung(7) TV Power on code, followed immediately by a Sony(4)
+ * TV power off message.
+ * or: 19,C1A28877;P500;19,C1A25AA5;P500;19,C1A2E21D,0,30
+ * Turn on a Sherwood(19) Amplifier, Wait 1/2 a second, Switch the
+ * Amplifier to Video input 2, wait 1/2 a second, then send the Sherwood
+ * Amp the "Volume Up" message 30 times.
+ *
* In short:
* No spaces after/before commas.
* Values are comma separated.
@@ -163,6 +185,13 @@
* acknowledge this via the relevant state topic for that command.
* e.g. If the aircon/climate changes from power off to power on, it will
* send an "on" payload to "ir_server/ac/stat/power"
+ *
+ * There is a special command available to force the ESP to resend the current
+ * A/C state in an IR message. To do so use the `resend` command MQTT topic,
+ * e.g. `ir_server/ac/cmnd/resend` with a payload message of `resend`.
+ * There is no corresponding "stat" message update for this particular topic,
+ * but a log message is produced indicating it was received.
+ *
* NOTE: These "stat" messages have the MQTT retain flag set to on. Thus the
* MQTT broker will remember them until reset/restarted etc.
*
@@ -195,43 +224,43 @@
* In HA's configuration.yaml, add:
*
* climate:
- * platform: mqtt
- * name: Living Room Aircon
- * modes:
- * - "off"
- * - "auto"
- * - "cool"
- * - "heat"
- * - "dry"
- * - "fan_only"
- * fan_modes:
- * - "auto"
- * - "min"
- * - "low"
- * - "medium"
- * - "high"
- * - "max"
- * swing_modes:
- * - "off"
- * - "auto"
- * - "highest"
- * - "high"
- * - "middle"
- * - "low"
- * - "lowest"
- * power_command_topic: "ir_server/ac/cmnd/power"
- * mode_command_topic: "ir_server/ac/cmnd/mode"
- * mode_state_topic: "ir_server/ac/stat/mode"
- * temperature_command_topic: "ir_server/ac/cmnd/temp"
- * temperature_state_topic: "ir_server/ac/stat/temp"
- * fan_mode_command_topic: "ir_server/ac/cmnd/fanspeed"
- * fan_mode_state_topic: "ir_server/ac/stat/fanspeed"
- * swing_mode_command_topic: "ir_server/ac/cmnd/swingv"
- * swing_mode_state_topic: "ir_server/ac/stat/swingv"
- * min_temp: 16
- * max_temp: 32
- * temp_step: 1
- * retain: false
+ * - platform: mqtt
+ * name: Living Room Aircon
+ * modes:
+ * - "off"
+ * - "auto"
+ * - "cool"
+ * - "heat"
+ * - "dry"
+ * - "fan_only"
+ * fan_modes:
+ * - "auto"
+ * - "min"
+ * - "low"
+ * - "medium"
+ * - "high"
+ * - "max"
+ * swing_modes:
+ * - "off"
+ * - "auto"
+ * - "highest"
+ * - "high"
+ * - "middle"
+ * - "low"
+ * - "lowest"
+ * power_command_topic: "ir_server/ac/cmnd/power"
+ * mode_command_topic: "ir_server/ac/cmnd/mode"
+ * mode_state_topic: "ir_server/ac/stat/mode"
+ * temperature_command_topic: "ir_server/ac/cmnd/temp"
+ * temperature_state_topic: "ir_server/ac/stat/temp"
+ * fan_mode_command_topic: "ir_server/ac/cmnd/fanspeed"
+ * fan_mode_state_topic: "ir_server/ac/stat/fanspeed"
+ * swing_mode_command_topic: "ir_server/ac/cmnd/swingv"
+ * swing_mode_state_topic: "ir_server/ac/stat/swingv"
+ * min_temp: 16
+ * max_temp: 32
+ * temp_step: 1
+ * retain: false
*
* ### via HTTP:
* Use the "http:///aircon/set" URL and pass on
@@ -250,9 +279,13 @@
* `ir_server/log`
*
* ## Updates
- * You can upload new firmware over the air (OTA) via the form on the device's
- * main page. No need to connect to the device again via USB. \o/
- * Your WiFi settings should be remembered between updates. \o/ \o/
+ * You can upload new firmware Over The Air (OTA) via the form on the device's
+ * "Admin" page. No need to connect to the device again via USB. \o/
+ * Your settings should be remembered between updates. \o/ \o/
+ *
+ * On boards with 1 Meg of flash should use an SPIFFS size of 64k if you want a
+ * hope of being able to load a firmware via OTA.
+ * Boards with only 512k flash have no chance of OTA with this firmware.
*
* ## Security
*
@@ -279,12 +312,21 @@
#include
#include
#include
+#if defined(ESP8266)
#include
+#include
+#include
+#endif // ESP8266
+#if defined(ESP32)
+#include
+#include
+#include
+#include
+#include
+#endif // ESP32
#include
#include
-#include
#include
-#include
#include
#include
#include
@@ -303,13 +345,22 @@
#include
#include
+using irutils::msToString;
+
+#if REPORT_VCC
+ ADC_MODE(ADC_VCC);
+#endif // REPORT_VCC
+
// Globals
+#if defined(ESP8266)
ESP8266WebServer server(kHttpPort);
-#ifdef IR_RX
-IRrecv irrecv(IR_RX, kCaptureBufferSize, kCaptureTimeout, true);
-decode_results capture; // Somewhere to store inbound IR messages.
-#endif // IR_RX
+#endif // ESP8266
+#if defined(ESP32)
+WebServer server(kHttpPort);
+#endif // ESP32
+#if MDNS_ENABLE
MDNSResponder mdns;
+#endif // MDNS_ENABLE
WiFiClient espClient;
WiFiManager wifiManager;
bool flagSaveWifiConfig = false;
@@ -319,23 +370,28 @@ char Hostname[kHostnameLength + 1] = "ir_server"; // Default hostname.
uint16_t *codeArray;
uint32_t lastReconnectAttempt = 0; // MQTT last attempt reconnection number
bool boot = true;
-bool lockIr = false; // Primitive locking for gating the IR LED.
+volatile bool lockIr = false; // Primitive locking for gating the IR LED.
uint32_t sendReqCounter = 0;
bool lastSendSucceeded = false; // Store the success status of the last send.
uint32_t lastSendTime = 0;
int8_t offset; // The calculated period offset for this chip and library.
-IRsend *IrSendTable[kSendTableSize];
-
-#ifdef IR_RX
+IRsend *IrSendTable[kNrOfIrTxGpios];
+int8_t txGpioTable[kNrOfIrTxGpios] = {kDefaultIrLed};
+String lastClimateSource;
+#if IR_RX
+IRrecv *irrecv = NULL;
+decode_results capture; // Somewhere to store inbound IR messages.
+int8_t rx_gpio = kDefaultIrRx;
String lastIrReceived = "None";
uint32_t lastIrReceivedTime = 0;
uint32_t irRecvCounter = 0;
#endif // IR_RX
// Climate stuff
-commonAcState_t climate;
-commonAcState_t climate_prev;
-IRac commonAc(gpioTable[0]);
+stdAc::state_t climate;
+stdAc::state_t climate_prev;
+IRac *commonAc = NULL;
+
TimerMs lastClimateIr = TimerMs(); // When we last sent the IR Climate mesg.
uint32_t irClimateCounter = 0; // How many have we sent?
// Store the success status of the last climate send.
@@ -368,7 +424,9 @@ String MqttLwt; // Topic for the Last Will & Testament.
String MqttClimate; // Sub-topic for the climate topics.
String MqttClimateCmnd; // Sub-topic for the climate command topics.
String MqttClimateStat; // Sub-topic for the climate stat topics.
+#if MQTT_DISCOVERY_ENABLE
String MqttDiscovery;
+#endif // MQTT_DISCOVERY_ENABLE
String MqttHAName;
String MqttClientId;
@@ -382,16 +440,29 @@ TimerMs statListenTime = TimerMs(); // How long we've been listening for.
#endif // MQTT_ENABLE
bool isSerialGpioUsedByIr(void) {
- const uint8_t kSerialTxGpio = 1; // The GPIO serial output is sent too.
- // Note: *DOES NOT* control Serial output.
+ const int8_t kSerialTxGpio = 1; // The GPIO serial output is sent to.
+ // Note: *DOES NOT* control Serial output.
+#if defined(ESP32)
+ const int8_t kSerialRxGpio = 3; // The GPIO serial input is received on.
+#endif // ESP32
// Ensure we are not trodding on anything IR related.
-#ifdef IR_RX
- if (IR_RX == kSerialTxGpio)
- return true; // Serial port is in use by IR capture. Abort.
+#if IR_RX
+ switch (rx_gpio) {
+#if defined(ESP32)
+ case kSerialRxGpio:
+#endif // ESP32
+ case kSerialTxGpio:
+ return true; // Serial port is in use by IR capture. Abort.
+ }
#endif // IR_RX
- for (uint8_t i = 0; i < kSendTableSize; i++)
- if (gpioTable[i] == kSerialTxGpio)
- return true; // Serial port is in use for IR sending. Abort.
+ for (uint8_t i = 0; i < kNrOfIrTxGpios; i++)
+ switch (txGpioTable[i]) {
+#if defined(ESP32)
+ case kSerialRxGpio:
+#endif // ESP32
+ case kSerialTxGpio:
+ return true; // Serial port is in use for IR sending. Abort.
+ }
return false; // Not in use as far as we can tell.
}
@@ -410,8 +481,27 @@ void saveWifiConfigCallback(void) {
flagSaveWifiConfig = true;
}
-void saveWifiConfig(void) {
- debug("Saving the wifi config.");
+// Forcibly mount the SPIFFS. Formatting the SPIFFS if needed.
+//
+// Returns:
+// A boolean indicating success or failure.
+bool mountSpiffs(void) {
+ debug("Mounting SPIFFS...");
+ if (SPIFFS.begin()) return true; // We mounted it okay.
+ // We failed the first time.
+ debug("Failed to mount SPIFFS!\nFormatting SPIFFS and trying again...");
+ SPIFFS.format();
+ if (!SPIFFS.begin()) { // Did we fail?
+ debug("DANGER: Failed to mount SPIFFS even after formatting!");
+ delay(10000); // Make sure the debug message doesn't just float by.
+ return false;
+ }
+ return true; // Success!
+}
+
+bool saveConfig(void) {
+ debug("Saving the config.");
+ bool success = false;
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
#if MQTT_ENABLE
@@ -424,8 +514,15 @@ void saveWifiConfig(void) {
json[kHostnameKey] = Hostname;
json[kHttpUserKey] = HttpUsername;
json[kHttpPassKey] = HttpPassword;
+#if IR_RX
+ json[KEY_RX_GPIO] = static_cast(rx_gpio);
+#endif // IR_RX
+ for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) {
+ const String key = KEY_TX_GPIO + String(i);
+ json[key] = static_cast(txGpioTable[i]);
+ }
- if (SPIFFS.begin()) {
+ if (mountSpiffs()) {
File configFile = SPIFFS.open(kConfigFile, "w");
if (!configFile) {
debug("Failed to open config file for writing.");
@@ -434,15 +531,17 @@ void saveWifiConfig(void) {
json.printTo(configFile);
configFile.close();
debug("Finished writing config file.");
+ success = true;
}
SPIFFS.end();
}
+ return success;
}
-void loadWifiConfigFile(void) {
- debug("Trying to mount SPIFFS");
- if (SPIFFS.begin()) {
- debug("mounted file system");
+bool loadConfigFile(void) {
+ bool success = false;
+ if (mountSpiffs()) {
+ debug("mounted the file system");
if (SPIFFS.exists(kConfigFile)) {
debug("config file exists");
@@ -468,7 +567,17 @@ void loadWifiConfigFile(void) {
strncpy(Hostname, json[kHostnameKey] | "", kHostnameLength);
strncpy(HttpUsername, json[kHttpUserKey] | "", kUsernameLength);
strncpy(HttpPassword, json[kHttpPassKey] | "", kPasswordLength);
+ // Read in the GPIO settings.
+#if IR_RX
+ // Single RX gpio
+ rx_gpio = json[KEY_RX_GPIO] | kDefaultIrRx;
+#endif // IR_RX
+ // Potentially multiple TX gpios
+ for (uint16_t i = 0; i < kNrOfIrTxGpios; i++)
+ txGpioTable[i] = json[String(KEY_TX_GPIO + String(i)).c_str()] |
+ kDefaultIrLed;
debug("Recovered Json fields.");
+ success = true;
} else {
debug("Failed to load json config");
}
@@ -480,89 +589,89 @@ void loadWifiConfigFile(void) {
}
debug("Unmounting SPIFFS.");
SPIFFS.end();
- } else {
- debug("Failed to mount SPIFFS");
}
-}
-
-String msToHumanString(uint32_t const msecs) {
- uint32_t totalseconds = msecs / 1000;
- if (totalseconds == 0) return "Now";
-
- // Note: millis() can only count up to 45 days, so uint8_t is safe.
- uint8_t days = totalseconds / (60 * 60 * 24);
- uint8_t hours = (totalseconds / (60 * 60)) % 24;
- uint8_t minutes = (totalseconds / 60) % 60;
- uint8_t seconds = totalseconds % 60;
-
- String result = "";
- if (days) result += String(days) + " day";
- if (days > 1) result += 's';
- if (hours) result += ' ' + String(hours) + " hour";
- if (hours > 1) result += 's';
- if (minutes) result += ' ' + String(minutes) + " minute";
- if (minutes > 1) result += 's';
- if (seconds) result += ' ' + String(seconds) + " second";
- if (seconds > 1) result += 's';
- result.trim();
- return result;
+ return success;
}
String timeElapsed(uint32_t const msec) {
- String result = msToHumanString(msec);
+ String result = msToString(msec);
if (result.equalsIgnoreCase("Now"))
return result;
else
- return result + " ago";
+ return result + F(" ago");
}
String timeSince(uint32_t const start) {
if (start == 0)
- return "Never";
+ return F("Never");
uint32_t diff = 0;
uint32_t now = millis();
if (start < now)
diff = now - start;
else
diff = UINT32_MAX - start + now;
- return msToHumanString(diff) + " ago";
+ return msToString(diff) + F(" ago");
+}
+
+String gpioToString(const int16_t gpio) {
+ if (gpio == kGpioUnused)
+ return F("Unused");
+ else
+ return String(gpio);
+}
+
+int8_t getDefaultTxGpio(void) {
+ for (int8_t i = 0; i < kNrOfIrTxGpios; i++)
+ if (txGpioTable[i] != kGpioUnused) return txGpioTable[i];
+ return kGpioUnused;
}
// Return a string containing the comma separated list of sending gpios.
-String listOfSendGpios(void) {
- String result = String(gpioTable[0]);
- if (kSendTableSize > 1) result += " (default)";
- for (uint8_t i = 1; i < kSendTableSize; i++) {
- result += ", " + String(gpioTable[i]);
+String listOfTxGpios(void) {
+ bool found = false;
+ String result = "";
+ for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) {
+ if (i) result += ", ";
+ result += gpioToString(txGpioTable[i]);
+ if (!found && txGpioTable[i] == getDefaultTxGpio()) {
+ result += " (default)";
+ found = true;
+ }
}
return result;
}
String htmlMenu(void) {
- return F(
- ""
- ""
- "Home"
- " "
- ""
- "Aircon"
- " "
- ""
- "Examples"
- " "
- ""
- "System Info"
- " "
- ""
- "Admin"
- " "
- " "
- " ");
+ String html = F("");
+ html += htmlButton(kUrlRoot, F("Home"));
+ html += htmlButton(kUrlAircon, F("Aircon"));
+#if EXAMPLES_ENABLE
+ html += htmlButton(kUrlExamples, F("Examples"));
+#endif // EXAMPLES_ENABLE
+ html += htmlButton(kUrlInfo, F("System Info"));
+ html += htmlButton(kUrlAdmin, F("Admin"));
+ html += F(" ");
+ return html;
+}
+
+String htmlSelectAcStateProtocol(const String name, const decode_type_t def,
+ const bool simple) {
+ String html = "";
+ for (uint8_t i = 1; i <= decode_type_t::kLastDecodeType; i++) {
+ if (simple ^ hasACState((decode_type_t)i)) {
+ switch (i) {
+ case decode_type_t::RAW:
+ case decode_type_t::PRONTO:
+ case decode_type_t::GLOBALCACHE:
+ break;
+ default:
+ html += htmlOptionItem(String(i), typeToString((decode_type_t)i),
+ i == def);
+ }
+ }
+ }
+ html += F(" ");
+ return html;
}
// Root web page with example usage etc.
@@ -573,72 +682,29 @@ void handleRoot(void) {
return server.requestAuthentication();
}
#endif
- String html = F(
- "IR MQTT server "
- ""
- "ESP8266 IR MQTT Server "
- "" _MY_VERSION_ " ");
+ String html = htmlHeader(F("ESP IR MQTT Server"));
+ html += F("" _MY_VERSION_ " ");
html += htmlMenu();
html += F(
"Send a simple IR message "
"
"
" "
@@ -686,11 +734,15 @@ void handleRoot(void) {
""
" "
@@ -699,10 +751,14 @@ void handleRoot(void) {
""
" "
@@ -711,15 +767,20 @@ void handleRoot(void) {
""
- " ");
+ " ");
+ html += htmlEnd();
server.send(200, "text/html", html);
}
@@ -747,6 +808,7 @@ String addJsReloadUrl(const String url, const uint16_t timeout_s,
return html;
}
+#if EXAMPLES_ENABLE
// Web page with hardcoded example usage etc.
void handleExamples(void) {
#if HTML_PASSWORD_ENABLE
@@ -755,11 +817,7 @@ void handleExamples(void) {
return server.requestAuthentication();
}
#endif
- String html = F(
- "IR MQTT examples "
- ""
- "ESP8266 IR MQTT Server "
- "" _MY_VERSION_ " ");
+ String html = htmlHeader(F("IR MQTT examples"));
html += htmlMenu();
html += F(
"Hardcoded examples "
@@ -792,121 +850,35 @@ void handleExamples(void) {
"Change just the temp to 27C (via HTTP aircon interface)
"
""
"Turn OFF the current A/C (via HTTP aircon interface)
"
- " ");
+ " ");
+ html += htmlEnd();
server.send(200, "text/html", html);
}
+#endif // EXAMPLES_ENABLE
-String boolToString(const bool value) {
- return value ? F("on") : F("off");
-}
-
-
-String opmodeToString(const stdAc::opmode_t mode) {
- switch (mode) {
- case stdAc::opmode_t::kOff:
- return F("off");
- case stdAc::opmode_t::kAuto:
- return F("auto");
- case stdAc::opmode_t::kCool:
- return F("cool");
- case stdAc::opmode_t::kHeat:
- return F("heat");
- case stdAc::opmode_t::kDry:
- return F("dry");
- case stdAc::opmode_t::kFan:
- return F("fan_only");
- default:
- return F("unknown");
- }
-}
-
-String fanspeedToString(const stdAc::fanspeed_t speed) {
- switch (speed) {
- case stdAc::fanspeed_t::kAuto:
- return F("auto");
- case stdAc::fanspeed_t::kMax:
- return F("max");
- case stdAc::fanspeed_t::kHigh:
- return F("high");
- case stdAc::fanspeed_t::kMedium:
- return F("medium");
- case stdAc::fanspeed_t::kLow:
- return F("low");
- case stdAc::fanspeed_t::kMin:
- return F("min");
- default:
- return F("unknown");
- }
-}
-
-String swingvToString(const stdAc::swingv_t swingv) {
- switch (swingv) {
- case stdAc::swingv_t::kOff:
- return F("off");
- case stdAc::swingv_t::kAuto:
- return F("auto");
- case stdAc::swingv_t::kHighest:
- return F("highest");
- case stdAc::swingv_t::kHigh:
- return F("high");
- case stdAc::swingv_t::kMiddle:
- return F("middle");
- case stdAc::swingv_t::kLow:
- return F("low");
- case stdAc::swingv_t::kLowest:
- return F("lowest");
- default:
- return F("unknown");
- }
-}
-
-String swinghToString(const stdAc::swingh_t swingh) {
- switch (swingh) {
- case stdAc::swingh_t::kOff:
- return F("off");
- case stdAc::swingh_t::kAuto:
- return F("auto");
- case stdAc::swingh_t::kLeftMax:
- return F("leftmax");
- case stdAc::swingh_t::kLeft:
- return F("left");
- case stdAc::swingh_t::kMiddle:
- return F("middle");
- case stdAc::swingh_t::kRight:
- return F("right");
- case stdAc::swingh_t::kRightMax:
- return F("rightmax");
- default:
- return F("unknown");
- }
+String htmlOptionItem(const String value, const String text, bool selected) {
+ String html = F("' + text + F(" ");
+ return html;
}
String htmlSelectBool(const String name, const bool def) {
String html = "";
- for (uint16_t i = 0; i < 2; i++) {
- html += F("';
- html += boolToString(i);
- html += F(" ");
- }
+ for (uint16_t i = 0; i < 2; i++)
+ html += htmlOptionItem(IRac::boolToString(i), IRac::boolToString(i),
+ i == def);
html += F(" ");
return html;
}
-String htmlSelectProtocol(const String name, const decode_type_t def) {
+String htmlSelectClimateProtocol(const String name, const decode_type_t def) {
String html = "";
for (uint8_t i = 1; i <= decode_type_t::kLastDecodeType; i++) {
if (IRac::isProtocolSupported((decode_type_t)i)) {
- html += F("';
- html += typeToString((decode_type_t)i);
- html += F(" ");
+ html += htmlOptionItem(String(i), typeToString((decode_type_t)i),
+ i == def);
}
}
html += F(" ");
@@ -917,17 +889,26 @@ String htmlSelectModel(const String name, const int16_t def) {
String html = "";
for (int16_t i = -1; i <= 6; i++) {
String num = String(i);
- html += F("';
+ String text;
if (i == -1)
- html += F("Default");
+ text = F("Default");
else if (i == 0)
- html += F("Unknown");
+ text = F("Unknown");
else
- html += num;
+ text = num;
+ html += htmlOptionItem(num, text, i == def);
+ }
+ html += F(" ");
+ return html;
+}
+
+String htmlSelectGpio(const String name, const int16_t def,
+ const int8_t list[], const int16_t length) {
+ String html = ": ";
+ for (int16_t i = 0; i < length; i++) {
+ String num = String(list[i]);
+ html += htmlOptionItem(num, list[i] == kGpioUnused ? F("Unused") : num,
+ list[i] == def);
html += F("");
}
html += F(" ");
@@ -936,15 +917,9 @@ String htmlSelectModel(const String name, const int16_t def) {
String htmlSelectMode(const String name, const stdAc::opmode_t def) {
String html = "";
- for (int8_t i = -1; i <= 4; i++) {
- String mode = opmodeToString((stdAc::opmode_t)i);
- html += F("';
- html += mode;
- html += F(" ");
+ for (int8_t i = -1; i <= (int8_t)stdAc::opmode_t::kLastOpmodeEnum; i++) {
+ String mode = IRac::opmodeToString((stdAc::opmode_t)i);
+ html += htmlOptionItem(mode, mode, (stdAc::opmode_t)i == def);
}
html += F(" ");
return html;
@@ -952,15 +927,9 @@ String htmlSelectMode(const String name, const stdAc::opmode_t def) {
String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def) {
String html = "";
- for (int8_t i = 0; i <= 5; i++) {
- String speed = fanspeedToString((stdAc::fanspeed_t)i);
- html += F("';
- html += speed;
- html += F(" ");
+ for (int8_t i = 0; i <= (int8_t)stdAc::fanspeed_t::kLastFanspeedEnum; i++) {
+ String speed = IRac::fanspeedToString((stdAc::fanspeed_t)i);
+ html += htmlOptionItem(speed, speed, (stdAc::fanspeed_t)i == def);
}
html += F(" ");
return html;
@@ -968,15 +937,9 @@ String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def) {
String htmlSelectSwingv(const String name, const stdAc::swingv_t def) {
String html = "";
- for (int8_t i = -1; i <= 5; i++) {
- String swing = swingvToString((stdAc::swingv_t)i);
- html += F("';
- html += swing;
- html += F(" ");
+ for (int8_t i = -1; i <= (int8_t)stdAc::swingv_t::kLastSwingvEnum; i++) {
+ String swing = IRac::swingvToString((stdAc::swingv_t)i);
+ html += htmlOptionItem(swing, swing, (stdAc::swingv_t)i == def);
}
html += F(" ");
return html;
@@ -984,32 +947,50 @@ String htmlSelectSwingv(const String name, const stdAc::swingv_t def) {
String htmlSelectSwingh(const String name, const stdAc::swingh_t def) {
String html = "";
- for (int8_t i = -1; i <= 5; i++) {
- String swing = swinghToString((stdAc::swingh_t)i);
- html += F("';
- html += swing;
- html += F(" ");
+ for (int8_t i = -1; i <= (int8_t)stdAc::swingh_t::kLastSwinghEnum; i++) {
+ String swing = IRac::swinghToString((stdAc::swingh_t)i);
+ html += htmlOptionItem(swing, swing, (stdAc::swingh_t)i == def);
}
html += F(" ");
return html;
}
+String htmlHeader(const String title, const String h1_text) {
+ String html = F("");
+ html += title;
+ html += F(" ");
+ if (h1_text.length())
+ html += h1_text;
+ else
+ html += title;
+ html += F(" ");
+ return html;
+}
+
+String htmlEnd(void) {
+ return F("");
+}
+
+String htmlButton(const String url, const String button, const String text) {
+ String html = F("");
+ html += button;
+ html += F(" ");
+ html += text;
+ return html;
+}
+
// Admin web page
void handleAirCon(void) {
- String html = F(
- "AirCon control "
- ""
- "Air Conditioner Control ");
+ String html = htmlHeader(F("Air Conditioner Control"));
html += htmlMenu();
html += "Current Settings "
"";
- // Display the current settings.
- html += F("");
+ html += htmlEnd();
server.send(200, "text/html", html);
}
@@ -1061,63 +1043,66 @@ void handleAirConSet(void) {
return server.requestAuthentication();
}
#endif
- commonAcState_t result = climate;
+ stdAc::state_t result = climate;
debug("New common a/c received via HTTP");
- for (uint16_t i = 0; i < server.args(); i++)
- result = updateClimate(result, server.argName(i), "", server.arg(i));
+ bool force_resend = false;
+ for (uint16_t i = 0; i < server.args(); i++) {
+ if (server.argName(i).equals(KEY_RESEND))
+ force_resend = IRac::strToBool(server.arg(i).c_str());
+ else
+ result = updateClimate(result, server.argName(i), "", server.arg(i));
+ }
#if MQTT_ENABLE
- sendClimate(climate, result, MqttClimateStat,
- true, false, false);
+ sendClimate(climate, result, MqttClimateStat, true, false, force_resend);
#else // MQTT_ENABLE
- sendClimate(climate, result, "", false, false, false);
+ sendClimate(climate, result, "", false, false, force_resend);
#endif // MQTT_ENABLE
+ lastClimateSource = F("HTTP");
// Update the old climate state with the new one.
climate = result;
// Redirect back to the aircon page.
- String html = F(
- "Update Aircon "
- ""
- "Aircon updated! ");
- html += addJsReloadUrl("/aircon", 2, false);
- html += F("");
+ String html = htmlHeader(F("Aircon updated!"));
+ html += addJsReloadUrl(kUrlAircon, kQuickDisplayTime, false);
+ html += htmlEnd();
server.send(200, "text/html", html);
}
+String htmlDisabled(void) {
+ String html = F(
+ "Updates disabled until you set a password. "
+ "You will need to wipe & reset to set one. ");
+ return html;
+}
+
// Admin web page
void handleAdmin(void) {
- String html = F(
- "IR MQTT server admin "
- ""
- "Administration ");
+ String html = htmlHeader(F("Administration"));
html += htmlMenu();
- html += F(
- "Special commands "
+ html += F("Special commands ");
#if MQTT_ENABLE
- ""
- "Send MQTT Discovery"
- " "
- "Send a Climate MQTT discovery message to Home Assistant. "
+#if MQTT_DISCOVERY_ENABLE
+ html += htmlButton(
+ kUrlSendDiscovery, F("Send MQTT Discovery"),
+ F("Send a Climate MQTT discovery message to Home Assistant. "));
+#endif // MQTT_DISCOVERY_ENABLE
#endif // MQTT_ENABLE
- ""
- "Reboot"
- " A simple reboot of the ESP8266. "
- "ie. No changes "
- ""
- "Wipe Settings"
- " Warning: "
- "Resets the device back to original settings. "
- "ie. Goes back to AP/Setup mode. ");
+ html += htmlButton(
+ kUrlReboot, F("Reboot"),
+ F("A simple reboot of the ESP8266. ie. No changes "
+ " "));
+ html += htmlButton(
+ kUrlWipe, F("Wipe Settings"),
+ F("Warning: Resets the device back to original settings. "
+ "ie. Goes back to AP/Setup mode. "));
+ html += htmlButton(kUrlGpio, F("GPIOs"), F("Change the IR GPIOs. "));
#if FIRMWARE_OTA
html += F("Update firmware "
- "Warning: ");
+ "Warning: ");
if (!strlen(HttpPassword)) // Deny if password not set
- html += F("OTA firmware is disabled until you set a password. "
- "You will need to wipe & reset to set one."
- " ");
+ html += htmlDisabled();
else // default password has been changed, so allow it.
html += F(
"Updating your firmware may screw up your access to the device. "
@@ -1128,16 +1113,25 @@ void handleAdmin(void) {
" "
"");
#endif // FIRMWARE_OTA
- html += F("");
+ html += htmlEnd();
server.send(200, "text/html", html);
}
+uint32_t maxSketchSpace(void) {
+#if defined(ESP8266)
+ return (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
+#else // defined(ESP8266)
+ return UPDATE_SIZE_UNKNOWN;
+#endif // defined(ESP8266)
+}
+
+#if REPORT_VCC
+String vccToString(void) { return String(ESP.getVcc() / 1000.0); }
+#endif // REPORT_VCC
+
// Info web page
void handleInfo(void) {
- String html =
- "IR MQTT server info "
- ""
- "
Information ";
+ String html = htmlHeader(F("IR MQTT server info"));
html += htmlMenu();
html +=
"General "
@@ -1149,13 +1143,22 @@ void handleInfo(void) {
" " __TIME__ " "
"Period Offset: " + String(offset) + "us "
"IR Lib Version: " _IRREMOTEESP8266_VERSION_ " "
+#if defined(ESP8266)
"ESP8266 Core Version: " + ESP.getCoreVersion() + " "
- "IR Send GPIO(s): " + listOfSendGpios() + " "
+ "Free Sketch Space: " + String(maxSketchSpace() >> 10) + "k "
+#endif // ESP8266
+#if defined(ESP32)
+ "ESP32 SDK Version: " + ESP.getSdkVersion() + " "
+#endif // ESP32
+ "Cpu Freq: " + String(ESP.getCpuFreqMHz()) + "MHz "
+ "IR Send GPIO(s): " + listOfTxGpios() + " "
+ + irutils::addBoolToString(kInvertTxOutput,
+ "Inverting GPIO output", false) + " "
"Total send requests: " + String(sendReqCounter) + " "
"Last message sent: " + String(lastSendSucceeded ? "Ok" : "FAILED") +
" (" + timeSince(lastSendTime) + ") "
-#ifdef IR_RX
- "IR Recv GPIO: " + String(IR_RX) +
+#if IR_RX
+ "IR Recv GPIO: " + gpioToString(rx_gpio) +
#if IR_RX_PULLUP
" (pullup)"
#endif // IR_RX_PULLUP
@@ -1180,6 +1183,11 @@ void handleInfo(void) {
"Off"
#endif // DEBUG
" "
+#if REPORT_VCC
+ "Vcc: ";
+ html += vccToString();
+ html += "V "
+#endif // REPORT_VCC
""
#if MQTT_ENABLE
"MQTT Information "
@@ -1191,7 +1199,7 @@ void handleInfo(void) {
"Client id: " + MqttClientId + " "
"Command topic(s): " + listOfCommandTopics() + " "
"Acknowledgements topic: " + MqttAck + " "
-#ifdef IR_RX
+#if IR_RX
"IR Received topic: " + MqttRecv + " "
#endif // IR_RX
"Log topic: " + MqttLog + " "
@@ -1199,8 +1207,9 @@ void handleInfo(void) {
"QoS: " + String(QOS) + " "
// lastMqttCmd* is unescaped untrusted input.
// Avoid any possible HTML/XSS when displaying it.
- "Last MQTT command seen: (topic) '" + htmlEscape(lastMqttCmdTopic) +
- "' (payload) '" + htmlEscape(lastMqttCmd) + "' (" +
+ "Last MQTT command seen: (topic) '" +
+ irutils::htmlEscape(lastMqttCmdTopic) +
+ "' (payload) '" + irutils::htmlEscape(lastMqttCmd) + "' (" +
timeSince(lastMqttCmdTime) + ") "
"Total published: " + String(mqttSentCounter) + " "
"Total received: " + String(mqttRecvCounter) + " "
@@ -1208,15 +1217,16 @@ void handleInfo(void) {
#endif // MQTT_ENABLE
"Climate Information "
" "
- "IR Send GPIO: " + String(gpioTable[0]) + " "
+ "IR Send GPIO: " + String(txGpioTable[0]) + " "
+ "Last update source: " + lastClimateSource + " "
"Total sent: " + String(irClimateCounter) + " "
"Last send: " + String(hasClimateBeenSent ?
(String(lastClimateSucceeded ? "Ok" : "FAILED") +
" (" + timeElapsed(lastClimateIr.elapsed()) + ") ") :
"Never ") + " "
#if MQTT_ENABLE
- "State listen period: " + msToHumanString(kStatListenPeriodMs) + " "
- "State broadcast period: " + msToHumanString(kBroadcastPeriodMs) + " "
+ "State listen period: " + msToString(kStatListenPeriodMs) + " "
+ "State broadcast period: " + msToString(kBroadcastPeriodMs) + " "
"Last state broadcast: " + (hasBroadcastBeenSent ?
timeElapsed(lastBroadcast.elapsed()) :
String("Never ")) + " "
@@ -1226,47 +1236,51 @@ void handleInfo(void) {
timeElapsed(lastDiscovery.elapsed()) :
String("Never "))) +
" "
- "Command topics: " + MqttClimateCmnd +
- "(" KEY_PROTOCOL "|" KEY_MODEL "|" KEY_POWER "|" KEY_MODE "|" KEY_TEMP "|"
- KEY_FANSPEED "|" KEY_SWINGV "|" KEY_SWINGH "|" KEY_QUIET "|"
- KEY_TURBO "|" KEY_LIGHT "|" KEY_BEEP "|" KEY_ECONO "|" KEY_SLEEP "|"
- KEY_CLOCK "|" KEY_FILTER "|" KEY_CLEAN "|" KEY_CELSIUS ") "
- "State topics: " + MqttClimateStat +
- "(" KEY_PROTOCOL "|" KEY_MODEL "|" KEY_POWER "|" KEY_MODE "|" KEY_TEMP "|"
- KEY_FANSPEED "|" KEY_SWINGV "|" KEY_SWINGH "|" KEY_QUIET "|"
- KEY_TURBO "|" KEY_LIGHT "|" KEY_BEEP "|" KEY_ECONO "|" KEY_SLEEP "|"
- KEY_CLOCK "|" KEY_FILTER "|" KEY_CLEAN "|" KEY_CELSIUS ") "
+ "Command topics: " + MqttClimateCmnd + kClimateTopics +
+ "State topics: " + MqttClimateStat + kClimateTopics +
#endif // MQTT_ENABLE
"
"
// Page footer
""
"(Note: Page will refresh every 60 seconds.) "
"
";
- html += addJsReloadUrl("/info", 60, false);
- html += "";
+ html += addJsReloadUrl(kUrlInfo, 60, false);
+ html += htmlEnd();
server.send(200, "text/html", html);
}
+
+void doRestart(const char* str, const bool serial_only) {
+#if MQTT_ENABLE
+ if (!serial_only)
+ mqttLog(str);
+ else
+#endif // MQTT_ENABLE
+ debug(str);
+ delay(2000); // Enough time for messages to be sent.
+ ESP.restart();
+ delay(5000); // Enough time to ensure we don't return.
+}
+
// Reset web page
void handleReset(void) {
#if HTML_PASSWORD_ENABLE
if (!server.authenticate(HttpUsername, HttpPassword)) {
- debug("Basic HTTP authentication failure for /reset.");
+ debug(("Basic HTTP authentication failure for " +
+ String(kUrlWipe)).c_str());
return server.requestAuthentication();
}
#endif
server.send(200, "text/html",
- "Reset WiFi Config "
- ""
- "Resetting the WiFiManager config back to defaults. "
+ htmlHeader(F("Reset WiFi Config"),
+ F("Resetting the WiFiManager config back to defaults.")) +
"Device restarting. Try connecting in a few seconds.
" +
- addJsReloadUrl("/", 10, true) +
- "");
+ addJsReloadUrl(kUrlRoot, 10, true) +
+ htmlEnd());
// Do the reset.
#if MQTT_ENABLE
mqttLog("Wiping all saved config settings.");
#endif // MQTT_ENABLE
- debug("Trying to mount SPIFFS");
- if (SPIFFS.begin()) {
+ if (mountSpiffs()) {
debug("Removing JSON config file");
SPIFFS.remove(kConfigFile);
SPIFFS.end();
@@ -1274,34 +1288,24 @@ void handleReset(void) {
delay(1000);
debug("Reseting wifiManager's settings.");
wifiManager.resetSettings();
- delay(1000);
- debug("rebooting...");
- ESP.restart();
- delay(1000);
+ doRestart("Rebooting...");
}
// Reboot web page
void handleReboot() {
#if HTML_PASSWORD_ENABLE
if (!server.authenticate(HttpUsername, HttpPassword)) {
- debug("Basic HTTP authentication failure for /quitquitquit.");
+ debug(("Basic HTTP authentication failure for " +
+ String(kUrlReboot)).c_str());
return server.requestAuthentication();
}
#endif
server.send(200, "text/html",
- "Rebooting "
- ""
- "Device restarting. "
+ htmlHeader(F("Device restarting.")) +
"Try connecting in a few seconds.
" +
- addJsReloadUrl("/", 15, true) +
- "");
-#if MQTT_ENABLE
- mqttLog("Reboot requested");
-#endif // MQTT_ENABLE
- // Do the reset.
- delay(1000);
- ESP.restart();
- delay(1000);
+ addJsReloadUrl(kUrlRoot, kRebootTime, true) +
+ htmlEnd());
+ doRestart("Reboot requested");
}
// Parse an Air Conditioner A/C Hex String/code and send it.
@@ -1311,7 +1315,7 @@ void handleReboot() {
// str: A hexadecimal string containing the state to be sent.
// Returns:
// bool: Successfully sent or not.
-bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType,
+bool parseStringAndSendAirCon(IRsend *irsend, const decode_type_t irType,
const String str) {
uint8_t strOffset = 0;
uint8_t state[kStateSizeMax] = {0}; // All array elements are set to 0.
@@ -1327,12 +1331,6 @@ bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType,
}
switch (irType) { // Get the correct state size for the protocol.
- case KELVINATOR:
- stateSize = kKelvinatorStateLength;
- break;
- case TOSHIBA_AC:
- stateSize = kToshibaACStateLength;
- break;
case DAIKIN:
// Daikin has 2 different possible size states.
// (The correct size, and a legacy shorter size.)
@@ -1350,36 +1348,6 @@ bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType,
// Lastly, it should never exceed the "normal" size.
stateSize = std::min(stateSize, kDaikinStateLength);
break;
- case DAIKIN2:
- stateSize = kDaikin2StateLength;
- break;
- case DAIKIN216:
- stateSize = kDaikin216StateLength;
- break;
- case ELECTRA_AC:
- stateSize = kElectraAcStateLength;
- break;
- case MITSUBISHI_AC:
- stateSize = kMitsubishiACStateLength;
- break;
- case MITSUBISHI_HEAVY_88:
- stateSize = kMitsubishiHeavy88StateLength;
- break;
- case MITSUBISHI_HEAVY_152:
- stateSize = kMitsubishiHeavy152StateLength;
- break;
- case PANASONIC_AC:
- stateSize = kPanasonicAcStateLength;
- break;
- case TROTEC:
- stateSize = kTrotecStateLength;
- break;
- case ARGO:
- stateSize = kArgoStateLength;
- break;
- case GREE:
- stateSize = kGreeStateLength;
- break;
case FUJITSU_AC:
// Fujitsu has four distinct & different size states, so make a best guess
// which one we are being presented with based on the number of
@@ -1396,23 +1364,16 @@ bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType,
// Lastly, it should never exceed the maximum "normal" size.
stateSize = std::min(stateSize, kFujitsuAcStateLength);
break;
- case HAIER_AC:
- stateSize = kHaierACStateLength;
- break;
- case HAIER_AC_YRW02:
- stateSize = kHaierACYRW02StateLength;
- break;
- case HITACHI_AC:
- stateSize = kHitachiAcStateLength;
- break;
- case HITACHI_AC1:
- stateSize = kHitachiAc1StateLength;
- break;
- case HITACHI_AC2:
- stateSize = kHitachiAc2StateLength;
- break;
- case WHIRLPOOL_AC:
- stateSize = kWhirlpoolAcStateLength;
+ case MWM:
+ // MWM has variable size states, so make a best guess
+ // which one we are being presented with based on the number of
+ // hexadecimal digits provided. i.e. Zero-pad if you need to to get
+ // the correct length/byte size.
+ stateSize = inputLength / 2; // Every two hex chars is a byte.
+ // Use at least the minimum size.
+ stateSize = std::max(stateSize, (uint16_t) 3);
+ // Cap the maximum size.
+ stateSize = std::min(stateSize, kStateSizeMax);
break;
case SAMSUNG_AC:
// Samsung has two distinct & different size states, so make a best guess
@@ -1430,23 +1391,13 @@ bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType,
// Lastly, it should never exceed the maximum "extended" size.
stateSize = std::min(stateSize, kSamsungAcExtendedStateLength);
break;
- case MWM:
- // MWM has variable size states, so make a best guess
- // which one we are being presented with based on the number of
- // hexadecimal digits provided. i.e. Zero-pad if you need to to get
- // the correct length/byte size.
- stateSize = inputLength / 2; // Every two hex chars is a byte.
- // Use at least the minimum size.
- stateSize = std::max(stateSize, (uint16_t) 3);
- // Cap the maximum size.
- stateSize = std::min(stateSize, kStateSizeMax);
- break;
- case TCL112AC:
- stateSize = kTcl112AcStateLength;
- break;
- default: // Not a protocol we expected. Abort.
- debug("Unexpected AirCon protocol detected. Ignoring.");
- return false;
+ default: // Everything else.
+ stateSize = IRsend::defaultBits(irType) / 8;
+ if (!stateSize || !hasACState(irType)) {
+ // Not a protocol we expected. Abort.
+ debug("Unexpected AirCon protocol detected. Ignoring.");
+ return false;
+ }
}
if (inputLength > stateSize * 2) {
debug("AirCon code to large for the given protocol.");
@@ -1477,125 +1428,9 @@ bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType,
*statePtr = c;
}
}
-
- // Make the appropriate call for the protocol type.
- switch (irType) {
-#if SEND_KELVINATOR
- case KELVINATOR:
- irsend->sendKelvinator(reinterpret_cast(state));
- break;
-#endif
-#if SEND_TOSHIBA_AC
- case TOSHIBA_AC:
- irsend->sendToshibaAC(reinterpret_cast(state));
- break;
-#endif
-#if SEND_DAIKIN
- case DAIKIN:
- irsend->sendDaikin(reinterpret_cast(state));
- break;
-#endif
-#if SEND_DAIKIN2
- case DAIKIN2:
- irsend->sendDaikin2(reinterpret_cast(state));
- break;
-#endif
-#if SEND_DAIKIN216
- case DAIKIN216:
- irsend->sendDaikin216(reinterpret_cast(state));
- break;
-#endif // SEND_DAIKIN216
-#if SEND_MITSUBISHI_AC
- case MITSUBISHI_AC:
- irsend->sendMitsubishiAC(reinterpret_cast(state));
- break;
-#endif
-#if SEND_MITSUBISHIHEAVY
- case MITSUBISHI_HEAVY_88: // 59
- irsend->sendMitsubishiHeavy88(reinterpret_cast(state));
- break;
- case MITSUBISHI_HEAVY_152: // 60
- irsend->sendMitsubishiHeavy152(reinterpret_cast(state));
- break;
-#endif // SEND_MITSUBISHIHEAVY
-#if SEND_TROTEC
- case TROTEC:
- irsend->sendTrotec(reinterpret_cast(state));
- break;
-#endif
-#if SEND_ARGO
- case ARGO:
- irsend->sendArgo(reinterpret_cast(state));
- break;
-#endif
-#if SEND_GREE
- case GREE:
- irsend->sendGree(reinterpret_cast(state));
- break;
-#endif
-#if SEND_FUJITSU_AC
- case FUJITSU_AC:
- irsend->sendFujitsuAC(reinterpret_cast(state), stateSize);
- break;
-#endif
-#if SEND_HAIER_AC
- case HAIER_AC:
- irsend->sendHaierAC(reinterpret_cast(state));
- break;
-#endif
-#if SEND_HAIER_AC_YRW02
- case HAIER_AC_YRW02:
- irsend->sendHaierACYRW02(reinterpret_cast(state));
- break;
-#endif
-#if SEND_HITACHI_AC
- case HITACHI_AC:
- irsend->sendHitachiAC(reinterpret_cast(state));
- break;
-#endif
-#if SEND_HITACHI_AC1
- case HITACHI_AC1:
- irsend->sendHitachiAC1(reinterpret_cast(state));
- break;
-#endif
-#if SEND_HITACHI_AC2
- case HITACHI_AC2:
- irsend->sendHitachiAC2(reinterpret_cast(state));
- break;
-#endif
-#if SEND_WHIRLPOOL_AC
- case WHIRLPOOL_AC:
- irsend->sendWhirlpoolAC(reinterpret_cast(state));
- break;
-#endif
-#if SEND_SAMSUNG_AC
- case SAMSUNG_AC:
- irsend->sendSamsungAC(reinterpret_cast(state), stateSize);
- break;
-#endif
-#if SEND_ELECTRA_AC
- case ELECTRA_AC:
- irsend->sendElectraAC(reinterpret_cast(state));
- break;
-#endif
-#if SEND_PANASONIC_AC
- case PANASONIC_AC:
- irsend->sendPanasonicAC(reinterpret_cast(state));
- break;
-#endif
-#if SEND_MWM
- case MWM:
- irsend->sendMWM(reinterpret_cast(state), stateSize);
- break;
-#endif
-#if SEND_TCL112AC
- case TCL112AC:
- irsend->sendTcl112Ac(reinterpret_cast(state));
- break;
-#endif
- default:
- debug("Unexpected AirCon type in send request. Not sent.");
- return false;
+ if (!irsend->send(irType, state, stateSize)) {
+ debug("Unexpected AirCon type in send request. Not sent.");
+ return false;
}
return true; // We were successful as far as we can tell.
}
@@ -1620,20 +1455,16 @@ uint16_t countValuesInStr(const String str, char sep) {
// Args:
// size: Nr. of uint16_t's need to be in the new array.
// Returns:
-// A Ptr to the new array. Restarts the ESP8266 if it fails.
+// A Ptr to the new array. Restarts the ESP if it fails.
uint16_t * newCodeArray(const uint16_t size) {
uint16_t *result;
result = reinterpret_cast(malloc(size * sizeof(uint16_t)));
// Check we malloc'ed successfully.
- if (result == NULL) { // malloc failed, so give up.
- Serial.printf("\nCan't allocate %d bytes. (%d bytes free)\n",
- size * sizeof(uint16_t), ESP.getFreeHeap());
- Serial.println("Giving up & forcing a reboot.");
- ESP.restart(); // Reboot.
- delay(500); // Wait for the restart to happen.
- return result; // Should never get here, but just in case.
- }
+ if (result == NULL) // malloc failed, so give up.
+ doRestart(
+ "FATAL: Can't allocate memory for an array for a new message! "
+ "Forcing a reboot!", true); // Send to serial only as we are in low mem
return result;
}
@@ -1676,7 +1507,6 @@ bool parseStringAndSendGC(IRsend *irsend, const String str) {
start_from = index + 1;
count++;
} while (index != -1);
-
irsend->sendGC(code_array, count); // All done. Send it.
free(code_array); // Free up the memory allocated.
if (count > 0)
@@ -1795,6 +1625,16 @@ bool parseStringAndSendRaw(IRsend *irsend, const String str) {
}
#endif // SEND_RAW
+uint8_t getDefaultIrSendIdx(void) {
+ for (uint16_t i = 0; i < kNrOfIrTxGpios; i++)
+ if (IrSendTable[i] != NULL) return i;
+ return 0;
+}
+
+IRsend* getDefaultIrSendPtr(void) {
+ return IrSendTable[getDefaultIrSendIdx()];
+}
+
// Parse the URL args to find the IR code.
void handleIr(void) {
#if HTML_PASSWORD_ENABLE
@@ -1805,7 +1645,7 @@ void handleIr(void) {
#endif
uint64_t data = 0;
String data_str = "";
- int16_t ir_type = decode_type_t::NEC; // Default to NEC codes.
+ decode_type_t ir_type = decode_type_t::NEC; // Default to NEC codes.
uint16_t nbits = 0;
uint16_t repeat = 0;
@@ -1823,17 +1663,104 @@ void handleIr(void) {
}
}
debug("New code received via HTTP");
- lastSendSucceeded = sendIRCode(IrSendTable[0], ir_type, data,
+ lastSendSucceeded = sendIRCode(getDefaultIrSendPtr(), ir_type, data,
data_str.c_str(), nbits, repeat);
- String html = F(
- "Send IR command "
- ""
- "IR command sent! ");
- html += addJsReloadUrl("/", 2, true);
- html += F("");
+ String html = htmlHeader(F("IR command sent!"));
+ html += addJsReloadUrl(kUrlRoot, kQuickDisplayTime, true);
+ html += htmlEnd();
server.send(200, "text/html", html);
}
+// GPIO menu page
+void handleGpio(void) {
+#if HTML_PASSWORD_ENABLE
+ if (!server.authenticate(HttpUsername, HttpPassword)) {
+ debug("Basic HTTP authentication failure for /gpios.");
+ return server.requestAuthentication();
+ }
+#endif
+ String html = htmlHeader(F("GPIO config"));
+ html += F(
+ "");
+ html += htmlEnd();
+ server.send(200, "text/html", html);
+}
+
+// GPIO setting page
+void handleGpioSetting(void) {
+ bool changed = false;
+ if (!server.authenticate(HttpUsername, HttpPassword)) {
+ debug("Basic HTTP authentication failure for /gpios.");
+ return server.requestAuthentication();
+ }
+ String html = htmlHeader(F("Update GPIOs"));
+ if (!strlen(HttpPassword)) { // Don't allow if password not set
+ html += htmlDisabled();
+ } else {
+ debug("Attempt to change GPIOs");
+ for (uint16_t arg = 0; arg < server.args(); arg++) {
+ int8_t num = std::max(static_cast(server.arg(arg).toInt()),
+ kGpioUnused);
+#if IR_RX
+ if (server.argName(arg).equals(KEY_RX_GPIO)) {
+ if (rx_gpio != num) {
+ rx_gpio = num;
+ changed = true;
+ }
+ } else {
+#endif // IR_RX
+ for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) {
+ if (server.argName(arg).equals(KEY_TX_GPIO + String(i))) {
+ if (txGpioTable[i] != num) {
+ txGpioTable[i] = num;
+ changed = true;
+ }
+ }
+ }
+#if IR_RX
+ }
+#endif // IR_RX
+ }
+ if (!changed) {
+ html += F("No changes detected! ");
+ } else if (saveConfig()) {
+ html += F("Saved changes & rebooting. ");
+ } else {
+ html += F("ERROR: Changes didn't save correctly! "
+ "Rebooting. ");
+ }
+ }
+ html += addJsReloadUrl(changed ? kUrlRoot : kUrlGpio,
+ changed ? kRebootTime : kQuickDisplayTime,
+ true);
+ html += htmlEnd();
+ server.send(200, "text/html", html);
+ if (changed) doRestart("GPIOs were changed. Rebooting!");
+}
+
void handleNotFound(void) {
String message = "File Not Found\n\n";
message += "URI: ";
@@ -1850,7 +1777,7 @@ void handleNotFound(void) {
void setup_wifi(void) {
delay(10);
- loadWifiConfigFile();
+ loadConfigFile();
// We start by connecting to a WiFi network
wifiManager.setTimeout(300); // Time out after 5 mins.
// Set up additional parameters for WiFiManager config menu page.
@@ -1896,7 +1823,7 @@ void setup_wifi(void) {
kMqttPrefixKey, "Leave empty to use Hostname", MqttPrefix,
kHostnameLength);
wifiManager.addParameter(&custom_mqtt_prefix);
- #endif // MQTT_ENABLE
+#endif // MQTT_ENABLE
#if USE_STATIC_IP
// Use a static IP config rather than the one supplied via DHCP.
wifiManager.setSTAStaticIPConfig(kIPAddress, kGateway, kSubnetMask);
@@ -1906,13 +1833,9 @@ void setup_wifi(void) {
#endif // MIN_SIGNAL_STRENGTH
wifiManager.setRemoveDuplicateAPs(HIDE_DUPLIATE_NETWORKS);
- if (!wifiManager.autoConnect()) {
- debug("Wifi failed to connect and hit timeout. Rebooting...");
- delay(3000);
+ if (!wifiManager.autoConnect())
// Reboot. A.k.a. "Have you tried turning it Off and On again?"
- ESP.reset();
- delay(5000);
- }
+ doRestart("Wifi failed to connect and hit timeout. Rebooting...", true);
#if MQTT_ENABLE
strncpy(MqttServer, custom_mqtt_server.getValue(), kHostnameLength);
@@ -1925,7 +1848,7 @@ void setup_wifi(void) {
strncpy(HttpUsername, custom_http_username.getValue(), kUsernameLength);
strncpy(HttpPassword, custom_http_password.getValue(), kPasswordLength);
if (flagSaveWifiConfig) {
- saveWifiConfig();
+ saveConfig();
}
debug("WiFi connected. IP address:");
debug(WiFi.localIP().toString().c_str());
@@ -1951,10 +1874,12 @@ void init_vars(void) {
MqttClimateCmnd = MqttClimate + '/' + MQTT_CLIMATE_CMND + '/';
// Sub-topic for the climate stat topics.
MqttClimateStat = MqttClimate + '/' + MQTT_CLIMATE_STAT + '/';
+#if MQTT_DISCOVERY_ENABLE
MqttDiscovery = "homeassistant/climate/" + String(Hostname) + "/config";
+#endif // MQTT_DISCOVERY_ENABLE
MqttHAName = String(Hostname) + "_aircon";
// Create a unique MQTT client id.
- MqttClientId = String(Hostname) + String(ESP.getChipId(), HEX);
+ MqttClientId = String(Hostname) + String(kChipId, HEX);
#endif // MQTT_ENABLE
}
@@ -1979,67 +1904,98 @@ void setup(void) {
climate.sleep = -1; // Off
climate.clock = -1; // Don't set.
climate_prev = climate;
-
- // Initialise all the IR transmitters.
- for (uint8_t i = 0; i < kSendTableSize; i++) {
- IrSendTable[i] = new IRsend(gpioTable[i]);
- IrSendTable[i]->begin();
- offset = IrSendTable[i]->calibrate();
- }
-#ifdef IR_RX
-#if IR_RX_PULLUP
- pinMode(IR_RX, INPUT_PULLUP);
-#endif // IR_RX_PULLUP
-#if DECODE_HASH
- // Ignore messages with less than minimum on or off pulses.
- irrecv.setUnknownThreshold(kMinUnknownSize);
-#endif // DECODE_HASH
- irrecv.enableIRIn(); // Start the receiver
-#endif // IR_RX
+ lastClimateSource = F("None");
#if DEBUG
if (!isSerialGpioUsedByIr()) {
+#if defined(ESP8266)
// Use SERIAL_TX_ONLY so that the RX pin can be freed up for GPIO/IR use.
Serial.begin(BAUD_RATE, SERIAL_8N1, SERIAL_TX_ONLY);
+#else // ESP8266
+ Serial.begin(BAUD_RATE, SERIAL_8N1);
+#endif // ESP8266
while (!Serial) // Wait for the serial connection to be establised.
delay(50);
Serial.println();
- debug("IRMQTTServer " _MY_VERSION_" has booted.");
+ debug("IRMQTTServer " _MY_VERSION_ " has booted.");
}
#endif // DEBUG
setup_wifi();
+#if DEBUG
+ // After the config has been loaded, check again if we are using a Serial GPIO
+ if (isSerialGpioUsedByIr()) Serial.end();
+#endif // DEBUG
+
+ // Initialise all the IR transmitters.
+ for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) {
+ if (txGpioTable[i] == kGpioUnused) {
+ IrSendTable[i] = NULL;
+ } else {
+ IrSendTable[i] = new IRsend(txGpioTable[i], kInvertTxOutput);
+ if (IrSendTable[i] == NULL) break;
+ IrSendTable[i]->begin();
+ offset = IrSendTable[i]->calibrate();
+ }
+ }
+#if IR_RX
+ if (rx_gpio != kGpioUnused)
+ irrecv = new IRrecv(rx_gpio, kCaptureBufferSize, kCaptureTimeout, true);
+ if (irrecv != NULL) {
+#if DECODE_HASH
+ // Ignore messages with less than minimum on or off pulses.
+ irrecv->setUnknownThreshold(kMinUnknownSize);
+#endif // DECODE_HASH
+ irrecv->enableIRIn(IR_RX_PULLUP); // Start the receiver
+ }
+#endif // IR_RX
+ commonAc = new IRac(txGpioTable[0], kInvertTxOutput);
+
// Wait a bit for things to settle.
delay(500);
lastReconnectAttempt = 0;
+#if MDNS_ENABLE
+#if defined(ESP8266)
if (mdns.begin(Hostname, WiFi.localIP())) {
+#else // ESP8266
+ if (mdns.begin(Hostname)) {
+#endif // ESP8266
debug("MDNS responder started");
}
+#endif // MDNS_ENABLE
// Setup the root web page.
- server.on("/", handleRoot);
+ server.on(kUrlRoot, handleRoot);
+#if EXAMPLES_ENABLE
// Setup the examples web page.
- server.on("/examples", handleExamples);
+ server.on(kUrlExamples, handleExamples);
+#endif // EXAMPLES_ENABLE
// Setup the page to handle web-based IR codes.
server.on("/ir", handleIr);
// Setup the aircon page.
- server.on("/aircon", handleAirCon);
+ server.on(kUrlAircon, handleAirCon);
// Setup the aircon update page.
server.on("/aircon/set", handleAirConSet);
// Setup the info page.
- server.on("/info", handleInfo);
+ server.on(kUrlInfo, handleInfo);
// Setup the admin page.
- server.on("/admin", handleAdmin);
+ server.on(kUrlAdmin, handleAdmin);
// Setup a reset page to cause WiFiManager information to be reset.
- server.on("/reset", handleReset);
+ server.on(kUrlWipe, handleReset);
// Reboot url
- server.on("/quitquitquit", handleReboot);
+ server.on(kUrlReboot, handleReboot);
+ // Show & pick which gpios are used for what etc.
+ server.on(kUrlGpio, handleGpio);
+ // Parse and update the new gpios.
+ server.on(kUrlGpioSet, handleGpioSetting);
#if MQTT_ENABLE
+#if MQTT_DISCOVERY_ENABLE
// MQTT Discovery url
- server.on("/send_discovery", handleSendMqttDiscovery);
+ server.on(kUrlSendDiscovery, handleSendMqttDiscovery);
+#endif // MQTT_DISCOVERY_ENABLE
// Finish setup of the mqtt clent object.
mqtt_client.setServer(MqttServer, atoi(MqttPort));
mqtt_client.setCallback(mqttCallback);
@@ -2056,9 +2012,7 @@ void setup(void) {
delay(1000);
#endif // MQTT_ENABLE
server.send(200, "text/html",
- "Updating firmware. "
- ""
- "Updating firmware "
+ htmlHeader(F("Updating firmware")) +
" "
"Warning! Don't power off the device for 60 seconds! "
"The firmware is uploading and will try to flash itself. "
@@ -2066,11 +2020,9 @@ void setup(void) {
"
The firmware upload seems to have " +
String(Update.hasError() ? "FAILED!" : "SUCCEEDED!") +
" Rebooting!
" +
- addJsReloadUrl("/", 20, true) +
- "");
- delay(1000);
- ESP.restart();
- delay(1000);
+ addJsReloadUrl(kUrlRoot, 20, true) +
+ htmlEnd());
+ doRestart("Post firmware reboot.");
}, [](){
if (!server.authenticate(HttpUsername, HttpPassword)) {
debug("Basic HTTP authentication failure for /update.");
@@ -2078,12 +2030,12 @@ void setup(void) {
}
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
- WiFiUDP::stopAll();
debug("Update:");
debug(upload.filename.c_str());
- uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) &
- 0xFFFFF000;
- if (!Update.begin(maxSketchSpace)) { // start with max available size
+#if defined(ESP8266)
+ WiFiUDP::stopAll();
+#endif // defined(ESP8266)
+ if (!Update.begin(maxSketchSpace())) { // start with max available
#if DEBUG
if (!isSerialGpioUsedByIr())
Update.printError(Serial);
@@ -2138,9 +2090,9 @@ void unsubscribing(const String topic_name) {
debug(topic_name.c_str());
}
-void mqttLog(const String mesg) {
- debug(mesg.c_str());
- mqtt_client.publish(MqttLog.c_str(), mesg.c_str());
+void mqttLog(const char* str) {
+ debug(str);
+ mqtt_client.publish(MqttLog.c_str(), str);
mqttSentCounter++;
}
@@ -2174,7 +2126,7 @@ bool reconnect(void) {
// Subscribing to topic(s)
subscribing(MqttSend);
- for (uint8_t i = 0; i < kSendTableSize; i++) {
+ for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) {
subscribing(MqttSend + '_' + String(static_cast(i)));
}
// Climate command topics.
@@ -2193,12 +2145,13 @@ bool reconnect(void) {
// Return a string containing the comma separated list of MQTT command topics.
String listOfCommandTopics(void) {
String result = MqttSend;
- for (uint16_t i = 0; i < kSendTableSize; i++) {
+ for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) {
result += ", " + MqttSend + '_' + String(i);
}
return result;
}
+#if MQTT_DISCOVERY_ENABLE
// MQTT Discovery web page
void handleSendMqttDiscovery(void) {
#if HTML_PASSWORD_ENABLE
@@ -2208,9 +2161,7 @@ void handleSendMqttDiscovery(void) {
}
#endif // HTML_PASSWORD_ENABLE
server.send(200, "text/html",
- "Sending MQTT Discovery message "
- ""
- "Sending MQTT Discovery message. " +
+ htmlHeader(F("Sending MQTT Discovery message")) +
htmlMenu() +
"The Home Assistant MQTT Discovery message is being sent to topic: " +
MqttDiscovery + ". It will show up in Home Assistant in a few seconds."
@@ -2218,29 +2169,35 @@ void handleSendMqttDiscovery(void) {
"
Warning! "
"Home Assistant's config for this device is reset each time this is "
" is sent.
" +
- addJsReloadUrl("/", 15, true) +
- "");
+ addJsReloadUrl(kUrlRoot, kRebootTime, true) +
+ htmlEnd());
sendMQTTDiscovery(MqttDiscovery.c_str());
}
+#endif // MQTT_DISCOVERY_ENABLE
void doBroadcast(TimerMs *timer, const uint32_t interval,
- const commonAcState_t state, const bool retain,
+ const stdAc::state_t state, const bool retain,
const bool force) {
if (force || (!lockMqttBroadcast && timer->elapsed() > interval)) {
debug("Sending MQTT stat update broadcast.");
sendClimate(state, state, MqttClimateStat,
retain, true, false);
+#if REPORT_VCC
+ sendString(MqttClimateStat + KEY_VCC, vccToString(), false);
+#endif // REPORT_VCC
+#if MQTT_CLIMATE_JSON
+ sendJsonState(state, MqttClimateStat + KEY_JSON);
+#endif // MQTT_CLIMATE_JSON
timer->reset(); // It's been sent, so reset the timer.
hasBroadcastBeenSent = true;
}
}
void receivingMQTT(String const topic_name, String const callback_str) {
- char* tok_ptr;
uint64_t code = 0;
uint16_t nbits = 0;
uint16_t repeat = 0;
- uint8_t channel = 0; // Default to the first channel. e.g. "*_0"
+ uint8_t channel = getDefaultIrSendIdx(); // Default to first usable channel.
debug("Receiving data by MQTT topic:");
debug(topic_name.c_str());
@@ -2255,10 +2212,18 @@ void receivingMQTT(String const topic_name, String const callback_str) {
if (topic_name.startsWith(MqttClimate)) {
if (topic_name.startsWith(MqttClimateCmnd)) {
debug("It's a climate command topic");
- commonAcState_t updated = updateClimate(
+ stdAc::state_t updated = updateClimate(
climate, topic_name, MqttClimateCmnd, callback_str);
- sendClimate(climate, updated, MqttClimateStat,
- true, false, false);
+ // Handle the special command for forcing a resend of the state via IR.
+ bool force_resend = false;
+ if (topic_name.equals(MqttClimateCmnd + KEY_RESEND) &&
+ callback_str.equalsIgnoreCase(KEY_RESEND)) {
+ force_resend = true;
+ mqttLog("Climate resend requested.");
+ }
+ if (sendClimate(climate, updated, MqttClimateStat,
+ true, false, force_resend) && !force_resend)
+ lastClimateSource = F("MQTT");
climate = updated;
} else if (topic_name.startsWith(MqttClimateStat)) {
debug("It's a climate state topic. Update internal state and DON'T send");
@@ -2268,7 +2233,7 @@ void receivingMQTT(String const topic_name, String const callback_str) {
return; // We are done for now.
}
// Check if a specific channel was requested by looking for a "*_[0-9]" suffix
- for (uint8_t i = 0; i < kSendTableSize; i++) {
+ for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) {
debug(("Checking if " + topic_name + " ends with _" + String(i)).c_str());
if (topic_name.endsWith("_" + String(i))) {
channel = i;
@@ -2278,39 +2243,67 @@ void receivingMQTT(String const topic_name, String const callback_str) {
}
debug(("Using transmit channel " + String(static_cast(channel)) +
- " / GPIO " + String(static_cast(gpioTable[channel]))).c_str());
+ " / GPIO " + String(static_cast(txGpioTable[channel]))).c_str());
// Make a copy of the callback string as strtok destroys it.
char* callback_c_str = strdup(callback_str.c_str());
debug("MQTT Payload (raw):");
debug(callback_c_str);
- // Get the numeric protocol type.
- int ir_type = strtoul(strtok_r(callback_c_str, ",", &tok_ptr), NULL, 10);
- char* next = strtok_r(NULL, ",", &tok_ptr);
- // If there is unparsed string left, try to convert it assuming it's hex.
- if (next != NULL) {
- code = getUInt64fromHex(next);
- next = strtok_r(NULL, ",", &tok_ptr);
- } else {
- // We require at least two value in the string. Give up.
- return;
+ // Chop up the str into command chunks.
+ // i.e. commands in a sequence are delimitered by ';'.
+ char* sequence_tok_ptr;
+ for (char* sequence_item = strtok_r(callback_c_str, kSequenceDelimiter,
+ &sequence_tok_ptr);
+ sequence_item != NULL;
+ sequence_item = strtok_r(NULL, kSequenceDelimiter, &sequence_tok_ptr)) {
+ // Now, process each command individually.
+ char* tok_ptr;
+ // Make a copy of the sequence_item str as strtok_r stomps on it.
+ char* ircommand = strdup(sequence_item);
+ // Check if it is a pause command.
+ switch (ircommand[0]) {
+ case kPauseChar:
+ { // It's a pause. Everything after the 'P' should be a number.
+ int32_t msecs = std::min((int32_t) strtoul(ircommand + 1, NULL, 10),
+ kMaxPauseMs);
+ delay(msecs);
+ mqtt_client.publish(MqttAck.c_str(),
+ String(kPauseChar + String(msecs)).c_str());
+ mqttSentCounter++;
+ break;
+ }
+ default: // It's an IR command.
+ {
+ // Get the numeric protocol type.
+ decode_type_t ir_type = (decode_type_t)atoi(strtok_r(
+ ircommand, kCommandDelimiter, &tok_ptr));
+ char* next = strtok_r(NULL, kCommandDelimiter, &tok_ptr);
+ // If there is unparsed string left, try to convert it assuming it's
+ // hex.
+ if (next != NULL) {
+ code = getUInt64fromHex(next);
+ next = strtok_r(NULL, kCommandDelimiter, &tok_ptr);
+ } else {
+ // We require at least two value in the string. Give up.
+ break;
+ }
+ // If there is still string left, assume it is the bit size.
+ if (next != NULL) {
+ nbits = atoi(next);
+ next = strtok_r(NULL, kCommandDelimiter, &tok_ptr);
+ }
+ // If there is still string left, assume it is the repeat count.
+ if (next != NULL)
+ repeat = atoi(next);
+ // send received MQTT value by IR signal
+ lastSendSucceeded = sendIRCode(
+ IrSendTable[channel], ir_type, code,
+ strchr(sequence_item, kCommandDelimiter[0]) + 1, nbits, repeat);
+ }
+ }
+ free(ircommand);
}
- // If there is still string left, assume it is the bit size.
- if (next != NULL) {
- nbits = atoi(next);
- next = strtok_r(NULL, ",", &tok_ptr);
- }
- // If there is still string left, assume it is the repeat count.
- if (next != NULL)
- repeat = atoi(next);
-
free(callback_c_str);
-
- // send received MQTT value by IR signal
- lastSendSucceeded = sendIRCode(
- IrSendTable[channel], ir_type, code,
- callback_str.substring(callback_str.indexOf(",") + 1).c_str(),
- nbits, repeat);
}
// Callback function, when we receive an MQTT value on the topics
@@ -2321,6 +2314,10 @@ void mqttCallback(char* topic, byte* payload, unsigned int length) {
// constructing the PUBLISH packet.
// Allocate the correct amount of memory for the payload copy
byte* payload_copy = reinterpret_cast(malloc(length + 1));
+ if (payload_copy == NULL) {
+ debug("Can't allocate memory for `payload_copy`. Skipping callback!");
+ return;
+ }
// Copy the payload to the new buffer
memcpy(payload_copy, payload, length);
@@ -2336,35 +2333,29 @@ void mqttCallback(char* topic, byte* payload, unsigned int length) {
free(payload_copy);
}
+#if MQTT_DISCOVERY_ENABLE
void sendMQTTDiscovery(const char *topic) {
if (mqtt_client.publish(
topic, String(
"{"
"\"~\":\"" + MqttClimate + "\","
"\"name\":\"" + MqttHAName + "\","
- "\"pow_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" KEY_POWER "\","
- "\"mode_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" KEY_MODE "\","
- "\"mode_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/" KEY_MODE
- "\","
+ "\"pow_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_POWER "\","
+ "\"mode_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_MODE "\","
+ "\"mode_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_MODE "\","
"\"modes\":[\"off\",\"auto\",\"cool\",\"heat\",\"dry\",\"fan_only\"],"
- "\"temp_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" KEY_TEMP "\","
- "\"temp_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/" KEY_TEMP
- "\","
+ "\"temp_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_TEMP "\","
+ "\"temp_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_TEMP "\","
"\"min_temp\":\"16\","
"\"max_temp\":\"30\","
"\"temp_step\":\"1\","
- "\"fan_mode_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/"
- KEY_FANSPEED "\","
- "\"fan_mode_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/"
- KEY_FANSPEED "\","
+ "\"fan_mode_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_FANSPEED "\","
+ "\"fan_mode_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_FANSPEED "\","
"\"fan_modes\":[\"auto\",\"min\",\"low\",\"medium\",\"high\",\"max\"],"
- "\"swing_mode_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/"
- KEY_SWINGV "\","
- "\"swing_mode_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/"
- KEY_SWINGV "\","
+ "\"swing_mode_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_SWINGV "\","
+ "\"swing_mode_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_SWINGV "\","
"\"swing_modes\":["
- "\"off\",\"auto\",\"highest\",\"high\",\"middle\",\"low\",\"lowest\""
- "]"
+ "\"off\",\"auto\",\"highest\",\"high\",\"middle\",\"low\",\"lowest\"]"
"}").c_str())) {
mqttLog("MQTT climate discovery successful sent.");
hasDiscoveryBeenSent = true;
@@ -2374,6 +2365,7 @@ void sendMQTTDiscovery(const char *topic) {
mqttLog("MQTT climate discovery FAILED to send.");
}
}
+#endif // MQTT_DISCOVERY_ENABLE
#endif // MQTT_ENABLE
void loop(void) {
@@ -2397,11 +2389,12 @@ void loop(void) {
lastReconnectAttempt = 0;
wasConnected = true;
if (boot) {
- mqttLog("IR Server just booted");
+ mqttLog("IRMQTTServer " _MY_VERSION_ " just booted");
boot = false;
} else {
- mqttLog("IR Server just (re)connected to MQTT. "
- "Lost connection about " + timeSince(lastConnectedTime));
+ mqttLog(String(
+ "IRMQTTServer just (re)connected to MQTT. Lost connection about "
+ + timeSince(lastConnectedTime)).c_str());
}
lastConnectedTime = now;
debug("successful client mqtt connection");
@@ -2422,10 +2415,11 @@ void loop(void) {
if (lockMqttBroadcast && statListenTime.elapsed() > kStatListenPeriodMs) {
unsubscribing(MqttClimateStat + '+');
mqttLog("Finished listening for previous state.");
- if (cmpClimate(climate, climate_prev)) { // Something changed.
+ if (IRac::cmpStates(climate, climate_prev)) { // Something changed.
mqttLog("The state was recovered from MQTT broker. Updating.");
sendClimate(climate_prev, climate, MqttClimateStat,
- true, false, false);
+ true, false, false, MQTT_CLIMATE_IR_SEND_ON_RESTART);
+ lastClimateSource = F("MQTT (via retain)");
}
lockMqttBroadcast = false; // Release the lock so we can broadcast again.
}
@@ -2433,15 +2427,16 @@ void loop(void) {
doBroadcast(&lastBroadcast, kBroadcastPeriodMs, climate, false, false);
}
#endif // MQTT_ENABLE
-#ifdef IR_RX
+#if IR_RX
// Check if an IR code has been received via the IR RX module.
#if REPORT_UNKNOWNS
- if (irrecv.decode(&capture)) {
+ if (irrecv != NULL && irrecv->decode(&capture)) {
#else // REPORT_UNKNOWNS
- if (irrecv.decode(&capture) && capture.decode_type != UNKNOWN) {
+ if (irrecv != NULL && irrecv->decode(&capture) &&
+ capture.decode_type != UNKNOWN) {
#endif // REPORT_UNKNOWNS
lastIrReceivedTime = millis();
- lastIrReceived = String(capture.decode_type) + "," +
+ lastIrReceived = String(capture.decode_type) + kCommandDelimiter[0] +
resultToHexidecimal(&capture);
#if REPORT_RAW_UNKNOWNS
if (capture.decode_type == UNKNOWN) {
@@ -2461,14 +2456,17 @@ void loop(void) {
#endif // REPORT_RAW_UNKNOWNS
// If it isn't an AC code, add the bits.
if (!hasACState(capture.decode_type))
- lastIrReceived += "," + String(capture.bits);
+ lastIrReceived += kCommandDelimiter[0] + String(capture.bits);
#if MQTT_ENABLE
mqtt_client.publish(MqttRecv.c_str(), lastIrReceived.c_str());
mqttSentCounter++;
-#endif // MQTT_ENABLE
- irRecvCounter++;
debug("Incoming IR message sent to MQTT:");
debug(lastIrReceived.c_str());
+#endif // MQTT_ENABLE
+ irRecvCounter++;
+#if USE_DECODED_AC_SETTINGS
+ if (decodeCommonAc(&capture)) lastClimateSource = F("IR");
+#endif // USE_DECODED_AC_SETTINGS
}
#endif // IR_RX
delay(100);
@@ -2505,297 +2503,51 @@ uint64_t getUInt64fromHex(char const *str) {
// repeat: Nr. of times the message is to be repeated. (Not all protcols.)
// Returns:
// bool: Successfully sent or not.
-bool sendIRCode(IRsend *irsend, int const ir_type,
+bool sendIRCode(IRsend *irsend, decode_type_t const ir_type,
uint64_t const code, char const * code_str, uint16_t bits,
uint16_t repeat) {
+ if (irsend == NULL) return false;
+ bool success = true; // Assume success.
+ // Ensure we have enough repeats.
+ repeat = std::max(IRsend::minRepeats(ir_type), repeat);
+ if (bits == 0) bits = IRsend::defaultBits(ir_type);
// Create a pseudo-lock so we don't try to send two codes at the same time.
while (lockIr)
delay(20);
lockIr = true;
- bool success = true; // Assume success.
+ // Turn off IR capture if we need to.
+#if IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING
+ if (irrecv != NULL) irrecv->disableIRIn(); // Stop the IR receiver
+#endif // IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING
// send the IR message.
switch (ir_type) {
-#if SEND_RC5
- case RC5: // 1
- if (bits == 0)
- bits = kRC5Bits;
- irsend->sendRC5(code, bits, repeat);
- break;
-#endif
-#if SEND_RC6
- case RC6: // 2
- if (bits == 0)
- bits = kRC6Mode0Bits;
- irsend->sendRC6(code, bits, repeat);
- break;
-#endif
-#if SEND_NEC
- case NEC: // 3
- if (bits == 0)
- bits = kNECBits;
- irsend->sendNEC(code, bits, repeat);
- break;
-#endif
-#if SEND_SONY
- case SONY: // 4
- if (bits == 0)
- bits = kSony12Bits;
- repeat = std::max(repeat, kSonyMinRepeat);
- irsend->sendSony(code, bits, repeat);
- break;
-#endif
-#if SEND_PANASONIC
- case PANASONIC: // 5
- if (bits == 0)
- bits = kPanasonicBits;
- irsend->sendPanasonic64(code, bits, repeat);
- break;
-#endif
-#if SEND_JVC
- case JVC: // 6
- if (bits == 0)
- bits = kJvcBits;
- irsend->sendJVC(code, bits, repeat);
- break;
-#endif
-#if SEND_SAMSUNG
- case SAMSUNG: // 7
- if (bits == 0)
- bits = kSamsungBits;
- irsend->sendSAMSUNG(code, bits, repeat);
- break;
-#endif
-#if SEND_SAMSUNG36
- case SAMSUNG36: // 56
- if (bits == 0)
- bits = kSamsung36Bits;
- irsend->sendSamsung36(code, bits, repeat);
- break;
-#endif
-#if SEND_WHYNTER
- case WHYNTER: // 8
- if (bits == 0)
- bits = kWhynterBits;
- irsend->sendWhynter(code, bits, repeat);
- break;
-#endif
-#if SEND_AIWA_RC_T501
- case AIWA_RC_T501: // 9
- if (bits == 0)
- bits = kAiwaRcT501Bits;
- repeat = std::max(repeat, kAiwaRcT501MinRepeats);
- irsend->sendAiwaRCT501(code, bits, repeat);
- break;
-#endif
-#if SEND_LG
- case LG: // 10
- if (bits == 0)
- bits = kLgBits;
- irsend->sendLG(code, bits, repeat);
- break;
-#endif
-#if SEND_MITSUBISHI
- case MITSUBISHI: // 12
- if (bits == 0)
- bits = kMitsubishiBits;
- repeat = std::max(repeat, kMitsubishiMinRepeat);
- irsend->sendMitsubishi(code, bits, repeat);
- break;
-#endif
-#if SEND_DISH
- case DISH: // 13
- if (bits == 0)
- bits = kDishBits;
- repeat = std::max(repeat, kDishMinRepeat);
- irsend->sendDISH(code, bits, repeat);
- break;
-#endif
-#if SEND_SHARP
- case SHARP: // 14
- if (bits == 0)
- bits = kSharpBits;
- irsend->sendSharpRaw(code, bits, repeat);
- break;
-#endif
-#if SEND_COOLIX
- case COOLIX: // 15
- if (bits == 0)
- bits = kCoolixBits;
- irsend->sendCOOLIX(code, bits, repeat);
- break;
-#endif
- case DAIKIN: // 16
- case DAIKIN2: // 53
- case DAIKIN216: // 61
- case KELVINATOR: // 18
- case MITSUBISHI_AC: // 20
- case GREE: // 24
- case ARGO: // 27
- case TROTEC: // 28
- case TOSHIBA_AC: // 32
- case FUJITSU_AC: // 33
- case HAIER_AC: // 38
- case HAIER_AC_YRW02: // 44
- case HITACHI_AC: // 40
- case HITACHI_AC1: // 41
- case HITACHI_AC2: // 42
- case WHIRLPOOL_AC: // 45
- case SAMSUNG_AC: // 46
- case ELECTRA_AC: // 48
- case PANASONIC_AC: // 49
- case MWM: // 52
- success = parseStringAndSendAirCon(irsend, ir_type, code_str);
- break;
-#if SEND_DENON
- case DENON: // 17
- if (bits == 0)
- bits = DENON_BITS;
- irsend->sendDenon(code, bits, repeat);
- break;
-#endif
-#if SEND_SHERWOOD
- case SHERWOOD: // 19
- if (bits == 0)
- bits = kSherwoodBits;
- repeat = std::max(repeat, kSherwoodMinRepeat);
- irsend->sendSherwood(code, bits, repeat);
- break;
-#endif
-#if SEND_RCMM
- case RCMM: // 21
- if (bits == 0)
- bits = kRCMMBits;
- irsend->sendRCMM(code, bits, repeat);
- break;
-#endif
-#if SEND_SANYO
- case SANYO_LC7461: // 22
- if (bits == 0)
- bits = kSanyoLC7461Bits;
- irsend->sendSanyoLC7461(code, bits, repeat);
- break;
-#endif
-#if SEND_RC5
- case RC5X: // 23
- if (bits == 0)
- bits = kRC5XBits;
- irsend->sendRC5(code, bits, repeat);
- break;
-#endif
#if SEND_PRONTO
- case PRONTO: // 25
+ case decode_type_t::PRONTO: // 25
success = parseStringAndSendPronto(irsend, code_str, repeat);
break;
-#endif
-#if SEND_NIKAI
- case NIKAI: // 29
- if (bits == 0)
- bits = kNikaiBits;
- irsend->sendNikai(code, bits, repeat);
- break;
-#endif
+#endif // SEND_PRONTO
+ case decode_type_t::RAW: // 30
#if SEND_RAW
- case RAW: // 30
success = parseStringAndSendRaw(irsend, code_str);
break;
#endif
#if SEND_GLOBALCACHE
- case GLOBALCACHE: // 31
+ case decode_type_t::GLOBALCACHE: // 31
success = parseStringAndSendGC(irsend, code_str);
break;
#endif
-#if SEND_MIDEA
- case MIDEA: // 34
- if (bits == 0)
- bits = kMideaBits;
- irsend->sendMidea(code, bits, repeat);
- break;
-#endif
-#if SEND_MAGIQUEST
- case MAGIQUEST: // 35
- if (bits == 0)
- bits = kMagiquestBits;
- irsend->sendMagiQuest(code, bits, repeat);
- break;
-#endif
-#if SEND_LASERTAG
- case LASERTAG: // 36
- if (bits == 0)
- bits = kLasertagBits;
- irsend->sendLasertag(code, bits, repeat);
- break;
-#endif
-#if SEND_CARRIER_AC
- case CARRIER_AC: // 37
- if (bits == 0)
- bits = kCarrierAcBits;
- irsend->sendCarrierAC(code, bits, repeat);
- break;
-#endif
-#if SEND_MITSUBISHI2
- case MITSUBISHI2: // 39
- if (bits == 0)
- bits = kMitsubishiBits;
- repeat = std::max(repeat, kMitsubishiMinRepeat);
- irsend->sendMitsubishi2(code, bits, repeat);
- break;
-#endif
-#if SEND_GICABLE
- case GICABLE: // 43
- if (bits == 0)
- bits = kGicableBits;
- repeat = std::max(repeat, kGicableMinRepeat);
- irsend->sendGICable(code, bits, repeat);
- break;
-#endif
-#if SEND_LUTRON
- case LUTRON: // 47
- if (bits == 0)
- bits = kLutronBits;
- irsend->sendLutron(code, bits, repeat);
- break;
-#endif
-#if SEND_PIONEER
- case PIONEER: // 50
- if (bits == 0)
- bits = kPioneerBits;
- irsend->sendPioneer(code, bits, repeat);
- break;
-#endif
-#if SEND_LG
- case LG2: // 51
- if (bits == 0)
- bits = kLgBits;
- irsend->sendLG2(code, bits, repeat);
- break;
-#endif
-#if SEND_VESTEL_AC
- case VESTEL_AC: // 54
- if (bits == 0)
- bits = kVestelAcBits;
- irsend->sendVestelAc(code, bits, repeat);
- break;
-#endif
-#if SEND_TECO
- case TECO: // 55
- if (bits == 0)
- bits = kTecoBits;
- irsend->sendTeco(code, bits, repeat);
- break;
-#endif
-#if SEND_LEGOPF
- case LEGOPF: // 58
- if (bits == 0)
- bits = kLegoPfBits;
- irsend->sendLegoPf(code, bits, repeat);
- break;
-#endif
- default:
- // If we got here, we didn't know how to send it.
- success = false;
+ default: // Everything else.
+ if (hasACState(ir_type)) // protocols with > 64 bits
+ success = parseStringAndSendAirCon(irsend, ir_type, code_str);
+ else // protocols with <= 64 bits
+ success = irsend->send(ir_type, code, bits, repeat);
}
+#if IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING
+ // Turn IR capture back on if we need to.
+ if (irrecv != NULL) irrecv->enableIRIn(); // Restart the receiver
+#endif // IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING
lastSendTime = millis();
// Release the lock.
lockIr = false;
@@ -2810,9 +2562,7 @@ bool sendIRCode(IRsend *irsend, int const ir_type,
debug("Type:");
debug(String(ir_type).c_str());
// For "long" codes we basically repeat what we got.
- if (hasACState((decode_type_t) ir_type) ||
- ir_type == PRONTO ||
- ir_type == RAW ||
+ if (hasACState(ir_type) || ir_type == PRONTO || ir_type == RAW ||
ir_type == GLOBALCACHE) {
debug("Code: ");
debug(code_str);
@@ -2820,11 +2570,14 @@ bool sendIRCode(IRsend *irsend, int const ir_type,
#if MQTT_ENABLE
if (success) {
if (ir_type == PRONTO && repeat > 0)
- mqtt_client.publish(MqttAck.c_str(), (String(ir_type) + ",R" +
- String(repeat) + "," +
+ mqtt_client.publish(MqttAck.c_str(), (String(ir_type) +
+ kCommandDelimiter[0] + 'R' +
+ String(repeat) +
+ kCommandDelimiter[0] +
String(code_str)).c_str());
else
- mqtt_client.publish(MqttAck.c_str(), (String(ir_type) + "," +
+ mqtt_client.publish(MqttAck.c_str(), (String(ir_type) +
+ kCommandDelimiter[0] +
String(code_str)).c_str());
mqttSentCounter++;
}
@@ -2835,9 +2588,12 @@ bool sendIRCode(IRsend *irsend, int const ir_type,
debug(("Repeats: " + String(repeat)).c_str());
#if MQTT_ENABLE
if (success) {
- mqtt_client.publish(MqttAck.c_str(), (String(ir_type) + "," +
- uint64ToString(code, 16)
- + "," + String(bits) + "," +
+ mqtt_client.publish(MqttAck.c_str(), (String(ir_type) +
+ kCommandDelimiter[0] +
+ uint64ToString(code, 16) +
+ kCommandDelimiter[0] +
+ String(bits) +
+ kCommandDelimiter[0] +
String(repeat)).c_str());
mqttSentCounter++;
}
@@ -2882,62 +2638,135 @@ bool sendFloat(const String topic, const float_t temp, const bool retain) {
#endif // MQTT_ENABLE
}
-commonAcState_t updateClimate(commonAcState_t current, const String str,
- const String prefix, const String payload) {
- commonAcState_t result = current;
- String value = payload;
- value.toUpperCase();
+#if MQTT_CLIMATE_JSON
+void sendJsonState(const stdAc::state_t state, const String topic,
+ const bool retain, const bool ha_mode) {
+ DynamicJsonBuffer jsonBuffer;
+ JsonObject& json = jsonBuffer.createObject();
+ json[KEY_PROTOCOL] = typeToString(state.protocol);
+ json[KEY_MODEL] = state.model;
+ json[KEY_POWER] = IRac::boolToString(state.power);
+ json[KEY_MODE] = IRac::opmodeToString(state.mode);
+ // Home Assistant wants mode to be off if power is also off & vice-versa.
+ if (ha_mode && (state.mode == stdAc::opmode_t::kOff || !state.power)) {
+ json[KEY_MODE] = IRac::opmodeToString(stdAc::opmode_t::kOff);
+ json[KEY_POWER] = IRac::boolToString(false);
+ }
+ json[KEY_CELSIUS] = IRac::boolToString(state.celsius);
+ json[KEY_TEMP] = state.degrees;
+ json[KEY_FANSPEED] = IRac::fanspeedToString(state.fanspeed);
+ json[KEY_SWINGV] = IRac::swingvToString(state.swingv);
+ json[KEY_SWINGH] = IRac::swinghToString(state.swingh);
+ json[KEY_QUIET] = IRac::boolToString(state.quiet);
+ json[KEY_TURBO] = IRac::boolToString(state.turbo);
+ json[KEY_ECONO] = IRac::boolToString(state.econo);
+ json[KEY_LIGHT] = IRac::boolToString(state.light);
+ json[KEY_FILTER] = IRac::boolToString(state.filter);
+ json[KEY_CLEAN] = IRac::boolToString(state.clean);
+ json[KEY_BEEP] = IRac::boolToString(state.beep);
+ json[KEY_SLEEP] = state.sleep;
+
+ String payload = "";
+ payload.reserve(200);
+ json.printTo(payload);
+ sendString(topic, payload, retain);
+}
+
+stdAc::state_t jsonToState(const stdAc::state_t current, const String str) {
+ DynamicJsonBuffer jsonBuffer;
+ JsonObject& json = jsonBuffer.parseObject(str);
+ if (!json.success()) {
+ debug("json MQTT message did not parse. Skipping!");
+ return current;
+ }
+ stdAc::state_t result = current;
+ if (json.containsKey(KEY_PROTOCOL))
+ result.protocol = strToDecodeType(json[KEY_PROTOCOL]);
+ if (json.containsKey(KEY_MODEL))
+ result.model = IRac::strToModel(json[KEY_MODEL]);
+ if (json.containsKey(KEY_MODE))
+ result.mode = IRac::strToOpmode(json[KEY_MODE]);
+ if (json.containsKey(KEY_FANSPEED))
+ result.fanspeed = IRac::strToFanspeed(json[KEY_FANSPEED]);
+ if (json.containsKey(KEY_SWINGV))
+ result.swingv = IRac::strToSwingV(json[KEY_SWINGV]);
+ if (json.containsKey(KEY_SWINGH))
+ result.swingh = IRac::strToSwingH(json[KEY_SWINGH]);
+ if (json.containsKey(KEY_TEMP))
+ result.degrees = json[KEY_TEMP];
+ if (json.containsKey(KEY_SLEEP))
+ result.sleep = json[KEY_SLEEP];
+ if (json.containsKey(KEY_POWER))
+ result.power = IRac::strToBool(json[KEY_POWER]);
+ if (json.containsKey(KEY_QUIET))
+ result.quiet = IRac::strToBool(json[KEY_QUIET]);
+ if (json.containsKey(KEY_TURBO))
+ result.turbo = IRac::strToBool(json[KEY_TURBO]);
+ if (json.containsKey(KEY_ECONO))
+ result.econo = IRac::strToBool(json[KEY_ECONO]);
+ if (json.containsKey(KEY_LIGHT))
+ result.light = IRac::strToBool(json[KEY_LIGHT]);
+ if (json.containsKey(KEY_CLEAN))
+ result.clean = IRac::strToBool(json[KEY_CLEAN]);
+ if (json.containsKey(KEY_FILTER))
+ result.filter = IRac::strToBool(json[KEY_FILTER]);
+ if (json.containsKey(KEY_BEEP))
+ result.beep = IRac::strToBool(json[KEY_BEEP]);
+ if (json.containsKey(KEY_CELSIUS))
+ result.celsius = IRac::strToBool(json[KEY_CELSIUS]);
+ return result;
+}
+#endif // MQTT_CLIMATE_JSON
+
+stdAc::state_t updateClimate(stdAc::state_t current, const String str,
+ const String prefix, const String payload) {
+ stdAc::state_t result = current;
+#if MQTT_CLIMATE_JSON
+ if (str.equals(prefix + KEY_JSON))
+ result = jsonToState(result, payload.c_str());
+ else
+#endif // MQTT_CLIMATE_JSON
if (str.equals(prefix + KEY_PROTOCOL))
- result.protocol = strToDecodeType(value.c_str());
+ result.protocol = strToDecodeType(payload.c_str());
else if (str.equals(prefix + KEY_MODEL))
- result.model = IRac::strToModel(value.c_str());
+ result.model = IRac::strToModel(payload.c_str());
else if (str.equals(prefix + KEY_POWER))
- result.power = IRac::strToBool(value.c_str());
+ result.power = IRac::strToBool(payload.c_str());
else if (str.equals(prefix + KEY_MODE))
- result.mode = IRac::strToOpmode(value.c_str());
+ result.mode = IRac::strToOpmode(payload.c_str());
else if (str.equals(prefix + KEY_TEMP))
- result.degrees = value.toFloat();
+ result.degrees = payload.toFloat();
else if (str.equals(prefix + KEY_FANSPEED))
- result.fanspeed = IRac::strToFanspeed(value.c_str());
+ result.fanspeed = IRac::strToFanspeed(payload.c_str());
else if (str.equals(prefix + KEY_SWINGV))
- result.swingv = IRac::strToSwingV(value.c_str());
+ result.swingv = IRac::strToSwingV(payload.c_str());
else if (str.equals(prefix + KEY_SWINGH))
- result.swingh = IRac::strToSwingH(value.c_str());
+ result.swingh = IRac::strToSwingH(payload.c_str());
else if (str.equals(prefix + KEY_QUIET))
- result.quiet = IRac::strToBool(value.c_str());
+ result.quiet = IRac::strToBool(payload.c_str());
else if (str.equals(prefix + KEY_TURBO))
- result.turbo = IRac::strToBool(value.c_str());
+ result.turbo = IRac::strToBool(payload.c_str());
else if (str.equals(prefix + KEY_ECONO))
- result.econo = IRac::strToBool(value.c_str());
+ result.econo = IRac::strToBool(payload.c_str());
else if (str.equals(prefix + KEY_LIGHT))
- result.light = IRac::strToBool(value.c_str());
+ result.light = IRac::strToBool(payload.c_str());
else if (str.equals(prefix + KEY_BEEP))
- result.beep = IRac::strToBool(value.c_str());
+ result.beep = IRac::strToBool(payload.c_str());
else if (str.equals(prefix + KEY_FILTER))
- result.filter = IRac::strToBool(value.c_str());
+ result.filter = IRac::strToBool(payload.c_str());
else if (str.equals(prefix + KEY_CLEAN))
- result.clean = IRac::strToBool(value.c_str());
+ result.clean = IRac::strToBool(payload.c_str());
+ else if (str.equals(prefix + KEY_CELSIUS))
+ result.celsius = IRac::strToBool(payload.c_str());
else if (str.equals(prefix + KEY_SLEEP))
- result.sleep = value.toInt();
- else if (str.equals(prefix + KEY_CLOCK))
- result.clock = value.toInt();
+ result.sleep = payload.toInt();
return result;
}
-// Compare two AirCon states (climates).
-// Returns: True if they differ, False if they don't.
-bool cmpClimate(const commonAcState_t a, const commonAcState_t b) {
- return a.protocol != b.protocol || a.model != b.model || a.power != b.power ||
- a.mode != b.mode || a.degrees != b.degrees || a.celsius != b.celsius ||
- a.fanspeed != b.fanspeed || a.swingv != b.swingv ||
- a.swingh != b.swingh || a.quiet != b.quiet || a.turbo != b.turbo ||
- a.econo != b.econo || a.light != b.light || a.filter != b.filter ||
- a.clean != b.clean || a.beep != b.beep || a.sleep != b.sleep;
-}
-
-bool sendClimate(const commonAcState_t prev, const commonAcState_t next,
+bool sendClimate(const stdAc::state_t prev, const stdAc::state_t next,
const String topic_prefix, const bool retain,
- const bool forceMQTT, const bool forceIR) {
+ const bool forceMQTT, const bool forceIR,
+ const bool enableIR) {
bool diff = false;
bool success = true;
@@ -2954,7 +2783,8 @@ bool sendClimate(const commonAcState_t prev, const commonAcState_t next,
diff = true;
success &= sendBool(topic_prefix + KEY_POWER, next.power, retain);
success &= sendString(topic_prefix + KEY_MODE,
- (next.power ? opmodeToString(next.mode) : F("off")),
+ (next.power ? IRac::opmodeToString(next.mode)
+ : F("off")),
retain);
}
if (prev.degrees != next.degrees || forceMQTT) {
@@ -2968,17 +2798,17 @@ bool sendClimate(const commonAcState_t prev, const commonAcState_t next,
if (prev.fanspeed != next.fanspeed || forceMQTT) {
diff = true;
success &= sendString(topic_prefix + KEY_FANSPEED,
- fanspeedToString(next.fanspeed), retain);
+ IRac::fanspeedToString(next.fanspeed), retain);
}
if (prev.swingv != next.swingv || forceMQTT) {
diff = true;
success &= sendString(topic_prefix + KEY_SWINGV,
- swingvToString(next.swingv), retain);
+ IRac::swingvToString(next.swingv), retain);
}
if (prev.swingh != next.swingh || forceMQTT) {
diff = true;
success &= sendString(topic_prefix + KEY_SWINGH,
- swinghToString(next.swingh), retain);
+ IRac::swinghToString(next.swingh), retain);
}
if (prev.quiet != next.quiet || forceMQTT) {
diff = true;
@@ -3012,18 +2842,26 @@ bool sendClimate(const commonAcState_t prev, const commonAcState_t next,
diff = true;
success &= sendInt(topic_prefix + KEY_SLEEP, next.sleep, retain);
}
- if (diff && !forceMQTT)
+ if (diff && !forceMQTT) {
debug("Difference in common A/C state detected.");
- else
+#if MQTT_CLIMATE_JSON
+ sendJsonState(next, MqttClimateStat + KEY_JSON);
+#endif // MQTT_CLIMATE_JSON
+ } else {
debug("NO difference in common A/C state detected.");
+ }
// Only send an IR message if we need to.
- if ((diff && !forceMQTT) || forceIR) {
+ if (enableIR && ((diff && !forceMQTT) || forceIR)) {
debug("Sending common A/C state via IR.");
- lastClimateSucceeded = commonAc.sendAc(
- next.protocol, next.model, next.power, next.mode,
- next.degrees, next.celsius, next.fanspeed, next.swingv, next.swingh,
- next.quiet, next.turbo, next.econo, next.light, next.filter, next.clean,
- next.beep, next.sleep, -1);
+#if IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING
+ // Turn IR capture off if we need to.
+ if (irrecv != NULL) irrecv->disableIRIn(); // Stop the IR receiver
+#endif // IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING
+ lastClimateSucceeded = commonAc->sendAc(next, &prev);
+#if IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING
+ // Turn IR capture back on if we need to.
+ if (irrecv != NULL) irrecv->enableIRIn(); // Restart the receiver
+#endif // IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING
if (lastClimateSucceeded) hasClimateBeenSent = true;
success &= lastClimateSucceeded;
lastClimateIr.reset();
@@ -3032,3 +2870,48 @@ bool sendClimate(const commonAcState_t prev, const commonAcState_t next,
}
return success;
}
+
+#if USE_DECODED_AC_SETTINGS && IR_RX
+// Decode and use a valid IR A/C remote that we understand enough to convert
+// to a Common A/C format.
+// Args:
+// decode: A successful raw IR decode object.
+// Returns:
+// A boolean indicating success or failure.
+bool decodeCommonAc(const decode_results *decode) {
+ if (!IRac::isProtocolSupported(decode->decode_type)) {
+ debug("Inbound IR messages isn't a supported common A/C protocol");
+ return false;
+ }
+ stdAc::state_t state = climate;
+ debug("Converting inbound IR A/C message to common A/C");
+ if (!IRAcUtils::decodeToState(decode, &state, &climate)) {
+ debug("Failed to convert to common A/C."); // This shouldn't happen!
+ return false;
+ }
+#if IGNORE_DECODED_AC_PROTOCOL
+ if (climate.protocol != decode_type_t::UNKNOWN) {
+ // Use the previous protcol/model if set.
+ state.protocol = climate.protocol;
+ state.model = climate.model;
+ }
+#endif // IGNORE_DECODED_AC_PROTOCOL
+// Continue to use the previously prefered temperature units.
+// i.e. Keep using Celsius or Fahrenheit.
+if (climate.celsius != state.celsius) {
+ // We've got a mismatch, so we need to convert.
+ state.degrees = climate.celsius ? fahrenheitToCelsius(state.degrees)
+ : celsiusToFahrenheit(state.degrees);
+ state.celsius = climate.celsius;
+}
+#if MQTT_ENABLE
+ sendClimate(climate, state, MqttClimateStat, true, false,
+ REPLAY_DECODED_AC_MESSAGE, REPLAY_DECODED_AC_MESSAGE);
+#else // MQTT_ENABLE
+ sendClimate(climate, state, "", false, false, REPLAY_DECODED_AC_MESSAGE,
+ REPLAY_DECODED_AC_MESSAGE);
+#endif // MQTT_ENABLE
+ climate = state; // Copy over the new climate state.
+ return true;
+}
+#endif // USE_DECODED_AC_SETTINGS && IR_RX
diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/platformio.ini
new file mode 100644
index 000000000..2d82260ad
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/platformio.ini
@@ -0,0 +1,62 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags = -DMQTT_MAX_PACKET_SIZE=768
+
+[common]
+lib_deps_builtin =
+lib_deps_external =
+ PubSubClient
+ ArduinoJson@<6.0
+
+[common_esp8266]
+lib_deps_external =
+ ${common.lib_deps_builtin}
+ ${common.lib_deps_external}
+ WifiManager@>=0.14
+
+[common_esp32]
+lib_deps_external =
+ ${common.lib_deps_builtin}
+ ${common.lib_deps_external}
+ https://github.com/tzapu/WiFiManager.git#development
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+lib_deps = ${common_esp8266.lib_deps_external}
+
+[env:d1_mini]
+platform = espressif8266
+framework = arduino
+board = d1_mini
+lib_deps = ${common_esp8266.lib_deps_external}
+
+[env:d1_mini_no_mqtt]
+platform = espressif8266
+framework = arduino
+board = d1_mini
+build_flags =
+ ${env.build_flags}
+ -DMQTT_ENABLE=false
+lib_deps = ${common_esp8266.lib_deps_external}
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
+lib_deps = ${common_esp32.lib_deps_external}
+
+[env:esp01_1m]
+platform = espressif8266
+framework = arduino
+board = esp01_1m
+build_flags =
+ ${env.build_flags}
+ -Wl,-Teagle.flash.1m64.ld
+lib_deps = ${common_esp8266.lib_deps_external}
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRServer/IRServer.ino b/lib/IRremoteESP8266-2.6.5/examples/IRServer/IRServer.ino
similarity index 80%
rename from lib/IRremoteESP8266-2.6.0/examples/IRServer/IRServer.ino
rename to lib/IRremoteESP8266-2.6.5/examples/IRServer/IRServer.ino
index b378d3bd5..96fad95d2 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRServer/IRServer.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRServer/IRServer.ino
@@ -1,15 +1,17 @@
/*
* IRremoteESP8266: IRServer - demonstrates sending IR codes controlled from a webserver
+ * Version 0.3 May, 2019
* Version 0.2 June, 2017
* Copyright 2015 Mark Szabo
+ * Copyright 2019 David Conran
*
- * An IR LED circuit *MUST* be connected to the ESP8266 on a pin
+ * An IR LED circuit *MUST* be connected to the ESP on a pin
* as specified by kIrLed below.
*
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
- * https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -26,12 +28,17 @@
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
+#if defined(ESP8266)
#include
#include
#include
+#endif // ESP8266
+#if defined(ESP32)
+#include
+#include
+#include
+#endif // ESP32
#include
#include
#include
@@ -40,18 +47,27 @@ const char* kSsid = ".....";
const char* kPassword = ".....";
MDNSResponder mdns;
+#if defined(ESP8266)
ESP8266WebServer server(80);
+#undef HOSTNAME
+#define HOSTNAME "esp8266"
+#endif // ESP8266
+#if defined(ESP32)
+WebServer server(80);
+#undef HOSTNAME
+#define HOSTNAME "esp32"
+#endif // ESP32
-const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2).
+const uint16_t kIrLed = 4; // ESP GPIO pin to use. Recommended: 4 (D2).
IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message.
void handleRoot() {
server.send(200, "text/html",
"" \
- "ESP8266 Demo " \
+ "" HOSTNAME " Demo " \
"" \
- "Hello from ESP8266, you can send NEC encoded IR" \
+ "Hello from " HOSTNAME ", you can send NEC encoded IR" \
"signals from here! " \
" Send 0xFFE01F
" \
"Send 0xFAB123
" \
@@ -104,7 +120,11 @@ void setup(void) {
Serial.print("IP address: ");
Serial.println(WiFi.localIP().toString());
- if (mdns.begin("esp8266", WiFi.localIP())) {
+#if defined(ESP8266)
+ if (mdns.begin(HOSTNAME, WiFi.localIP())) {
+#else // ESP8266
+ if (mdns.begin(HOSTNAME)) {
+#endif // ESP8266
Serial.println("MDNS responder started");
}
diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRServer/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRServer/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/IRrecvDemo.ino b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/IRrecvDemo.ino
similarity index 94%
rename from lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/IRrecvDemo.ino
rename to lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/IRrecvDemo.ino
index 09babe4fe..5fd03f4b4 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/IRrecvDemo.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/IRrecvDemo.ino
@@ -6,7 +6,7 @@
* An IR detector/demodulator must be connected to the input kRecvPin.
* Copyright 2009 Ken Shirriff, http://arcfn.com
* Example circuit diagram:
- * https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-receiving
* Changes:
* Version 0.2 June, 2017
* Changed GPIO pin to the same as other examples.
@@ -16,9 +16,7 @@
* Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/IRrecvDump.ino b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/IRrecvDump.ino
similarity index 99%
rename from lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/IRrecvDump.ino
rename to lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/IRrecvDump.ino
index 34f10dc83..2a65cb624 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/IRrecvDump.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/IRrecvDump.ino
@@ -22,9 +22,7 @@
* LG added by Darryl Smith (based on the JVC protocol)
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/IRrecvDumpV2.ino
similarity index 51%
rename from lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/IRrecvDumpV2.ino
rename to lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/IRrecvDumpV2.ino
index 2dee0597c..f69c14aed 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/IRrecvDumpV2.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/IRrecvDumpV2.ino
@@ -3,12 +3,14 @@
* An IR detector/demodulator must be connected to the input kRecvPin.
*
* Copyright 2009 Ken Shirriff, http://arcfn.com
- * Copyright 2017 David Conran
+ * Copyright 2017-2019 David Conran
*
* Example circuit diagram:
- * https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-receiving
*
* Changes:
+ * Version 0.5 June, 2019
+ * - Move A/C description to IRac.cpp.
* Version 0.4 July, 2018
* - Minor improvements and more A/C unit support.
* Version 0.3 November, 2017
@@ -19,31 +21,11 @@
* Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009,
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
+#include
#include
-// The following are only needed for extended decoding of A/C Messages
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
// ==================== start of TUNEABLE PARAMETERS ====================
// An IR detector/demodulator is connected to GPIO pin 14
@@ -114,171 +96,19 @@ const uint16_t kMinUnknownSize = 12;
// Use turn on the save buffer feature for more complete capture coverage.
IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, true);
-
decode_results results; // Somewhere to store the results
-// Display the human readable state of an A/C message if we can.
-void dumpACInfo(decode_results *results) {
- String description = "";
-#if DECODE_DAIKIN
- if (results->decode_type == DAIKIN) {
- IRDaikinESP ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_DAIKIN
-#if DECODE_DAIKIN2
- if (results->decode_type == DAIKIN2) {
- IRDaikin2 ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_DAIKIN2
-#if DECODE_DAIKIN216
- if (results->decode_type == DAIKIN216) {
- IRDaikin216 ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_DAIKIN216
-#if DECODE_FUJITSU_AC
- if (results->decode_type == FUJITSU_AC) {
- IRFujitsuAC ac(0);
- ac.setRaw(results->state, results->bits / 8);
- description = ac.toString();
- }
-#endif // DECODE_FUJITSU_AC
-#if DECODE_KELVINATOR
- if (results->decode_type == KELVINATOR) {
- IRKelvinatorAC ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_KELVINATOR
-#if DECODE_MITSUBISHI_AC
- if (results->decode_type == MITSUBISHI_AC) {
- IRMitsubishiAC ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_MITSUBISHI_AC
-#if DECODE_MITSUBISHIHEAVY
- if (results->decode_type == MITSUBISHI_HEAVY_88) {
- IRMitsubishiHeavy88Ac ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
- if (results->decode_type == MITSUBISHI_HEAVY_152) {
- IRMitsubishiHeavy152Ac ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_MITSUBISHIHEAVY
-#if DECODE_TOSHIBA_AC
- if (results->decode_type == TOSHIBA_AC) {
- IRToshibaAC ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_TOSHIBA_AC
-#if DECODE_GREE
- if (results->decode_type == GREE) {
- IRGreeAC ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_GREE
-#if DECODE_MIDEA
- if (results->decode_type == MIDEA) {
- IRMideaAC ac(0);
- ac.setRaw(results->value); // Midea uses value instead of state.
- description = ac.toString();
- }
-#endif // DECODE_MIDEA
-#if DECODE_HAIER_AC
- if (results->decode_type == HAIER_AC) {
- IRHaierAC ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_HAIER_AC
-#if DECODE_HAIER_AC_YRW02
- if (results->decode_type == HAIER_AC_YRW02) {
- IRHaierACYRW02 ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_HAIER_AC_YRW02
-#if DECODE_SAMSUNG_AC
- if (results->decode_type == SAMSUNG_AC) {
- IRSamsungAc ac(0);
- ac.setRaw(results->state, results->bits / 8);
- description = ac.toString();
- }
-#endif // DECODE_SAMSUNG_AC
-#if DECODE_COOLIX
- if (results->decode_type == COOLIX) {
- IRCoolixAC ac(0);
- ac.setRaw(results->value); // Coolix uses value instead of state.
- description = ac.toString();
- }
-#endif // DECODE_COOLIX
-#if DECODE_PANASONIC_AC
- if (results->decode_type == PANASONIC_AC &&
- results->bits > kPanasonicAcShortBits) {
- IRPanasonicAc ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_PANASONIC_AC
-#if DECODE_HITACHI_AC
- if (results->decode_type == HITACHI_AC) {
- IRHitachiAc ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_HITACHI_AC
-#if DECODE_WHIRLPOOL_AC
- if (results->decode_type == WHIRLPOOL_AC) {
- IRWhirlpoolAc ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_WHIRLPOOL_AC
-#if DECODE_VESTEL_AC
- if (results->decode_type == VESTEL_AC) {
- IRVestelAc ac(0);
- ac.setRaw(results->value); // Like Coolix, use value instead of state.
- description = ac.toString();
- }
-#endif // DECODE_VESTEL_AC
-#if DECODE_TECO
- if (results->decode_type == TECO) {
- IRTecoAc ac(0);
- ac.setRaw(results->value); // Like Coolix, use value instead of state.
- description = ac.toString();
- }
-#endif // DECODE_TECO
-#if DECODE_TCL112AC
- if (results->decode_type == TCL112AC) {
- IRTcl112Ac ac(0);
- ac.setRaw(results->state);
- description = ac.toString();
- }
-#endif // DECODE_TCL112AC
- // If we got a human-readable description of the message, display it.
- if (description != "") Serial.println("Mesg Desc.: " + description);
-}
-
-// The section of code run only once at start-up.
+// This section of code runs only once at start-up.
void setup() {
+#if defined(ESP8266)
Serial.begin(kBaudRate, SERIAL_8N1, SERIAL_TX_ONLY);
+#else // ESP8266
+ Serial.begin(kBaudRate, SERIAL_8N1);
+#endif // ESP8266
while (!Serial) // Wait for the serial connection to be establised.
delay(50);
- Serial.println();
- Serial.print("IRrecvDumpV2 is now running and waiting for IR input on Pin ");
- Serial.println(kRecvPin);
-
+ Serial.printf("\nIRrecvDumpV2 is now running and waiting for IR input on Pin "
+ "%d\n", kRecvPin);
#if DECODE_HASH
// Ignore messages with less than minimum on or off pulses.
irrecv.setUnknownThreshold(kMinUnknownSize);
@@ -287,36 +117,33 @@ void setup() {
}
// The repeating section of the code
-//
void loop() {
// Check if the IR code has been received.
if (irrecv.decode(&results)) {
// Display a crude timestamp.
uint32_t now = millis();
Serial.printf("Timestamp : %06u.%03u\n", now / 1000, now % 1000);
+ // Check if we got an IR message tha was to big for our capture buffer.
if (results.overflow)
Serial.printf(
"WARNING: IR code is too big for buffer (>= %d). "
"This result shouldn't be trusted until this is resolved. "
"Edit & increase kCaptureBufferSize.\n",
kCaptureBufferSize);
+ // Display the library version the message was captured with.
+ Serial.println("Library : v" _IRREMOTEESP8266_VERSION_ "\n");
// Display the basic output of what we found.
Serial.print(resultToHumanReadableBasic(&results));
- dumpACInfo(&results); // Display any extra A/C info if we have it.
+ // Display any extra A/C info if we have it.
+ String description = IRAcUtils::resultAcToString(&results);
+ if (description.length()) Serial.println("Mesg Desc.: " + description);
yield(); // Feed the WDT as the text output can take a while to print.
-
- // Display the library version the message was captured with.
- Serial.print("Library : v");
- Serial.println(_IRREMOTEESP8266_VERSION_);
- Serial.println();
-
// Output RAW timing info of the result.
Serial.println(resultToTimingInfo(&results));
yield(); // Feed the WDT (again)
-
// Output the results as source code
Serial.println(resultToSourceCode(&results));
- Serial.println(""); // Blank line between entries
+ Serial.println(); // Blank line between entries
yield(); // Feed the WDT (again)
}
}
diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/IRsendDemo.ino b/lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/IRsendDemo.ino
similarity index 94%
rename from lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/IRsendDemo.ino
rename to lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/IRsendDemo.ino
index 19f118671..b9d995834 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/IRsendDemo.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/IRsendDemo.ino
@@ -10,7 +10,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
- * https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -28,9 +28,7 @@
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
@@ -53,7 +51,11 @@ uint8_t samsungState[kSamsungAcStateLength] = {
void setup() {
irsend.begin();
+#if ESP8266
Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
+#else // ESP8266
+ Serial.begin(115200, SERIAL_8N1);
+#endif // ESP8266
}
void loop() {
diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/IRsendProntoDemo.ino b/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/IRsendProntoDemo.ino
similarity index 98%
rename from lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/IRsendProntoDemo.ino
rename to lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/IRsendProntoDemo.ino
index 3bef2179e..09101c9dc 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/IRsendProntoDemo.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/IRsendProntoDemo.ino
@@ -11,7 +11,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
- * https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -29,9 +29,7 @@
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino
rename to lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino
index ee2422915..cce72c35d 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino
@@ -10,7 +10,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
- * https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -28,9 +28,7 @@
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/LGACSend/LGACSend.ino b/lib/IRremoteESP8266-2.6.5/examples/LGACSend/LGACSend.ino
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/examples/LGACSend/LGACSend.ino
rename to lib/IRremoteESP8266-2.6.5/examples/LGACSend/LGACSend.ino
diff --git a/lib/IRremoteESP8266-2.6.5/examples/LGACSend/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/LGACSend/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/LGACSend/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/SmartIRRepeater.ino b/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/SmartIRRepeater.ino
new file mode 100644
index 000000000..8dd202382
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/SmartIRRepeater.ino
@@ -0,0 +1,143 @@
+/*
+ * IRremoteESP8266: SmartIRRepeater.ino - Record and playback IR codes.
+ * Copyright 2019 David Conran (crankyoldgit)
+ *
+ * This program will try to capture incoming IR messages and tries to
+ * intelligently replay them back.
+ * It uses the advanced detection features of the library, and the custom
+ * sending routines. Thus it will try to use the correct frequencies,
+ * duty cycles, and repeats as it thinks is required.
+ * Anything it doesn't understand, it will try to replay back as best it can,
+ * but at 38kHz.
+ * Note:
+ * That might NOT be the frequency of the incoming message, so some not
+ * recogised messages that are replayed may not work. The frequency & duty
+ * cycle of unknown incoming messages is lost at the point of the Hardware IR
+ * demodulator. The ESP can't see it.
+ *
+ * W A R N I N G
+ * This code is just for educational/example use only. No help will be given
+ * to you to make it do something else, or to make it work with some
+ * weird device or circuit, or to make it more usable or practical.
+ * If it works for you. Great. If not, Congratulations on changing/fixing it.
+ *
+ * An IR detector/demodulator must be connected to the input, kRecvPin.
+ * An IR LED circuit must be connected to the output, kIrLedPin.
+ *
+ * Example circuit diagrams (both are needed):
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-receiving
+ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
+ *
+ * Common mistakes & tips:
+ * * Don't just connect the IR LED directly to the pin, it won't
+ * have enough current to drive the IR LED effectively.
+ * * Make sure you have the IR LED polarity correct.
+ * See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity
+ * * Some digital camera/phones can be used to see if the IR LED is flashed.
+ * Replace the IR LED with a normal LED if you don't have a digital camera
+ * when debugging.
+ * * Avoid using the following pins unless you really know what you are doing:
+ * * Pin 0/D3: Can interfere with the boot/program mode & support circuits.
+ * * Pin 1/TX/TXD0: Any serial transmissions from the ESP will interfere.
+ * * Pin 3/RX/RXD0: Any serial transmissions to the ESP will interfere.
+ * * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
+ * for your first time. e.g. ESP-12 etc.
+ *
+ * Changes:
+ * Version 1.0: June, 2019
+ * - Initial version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+// ==================== start of TUNEABLE PARAMETERS ====================
+
+// The GPIO an IR detector/demodulator is connected to. Recommended: 14 (D5)
+const uint16_t kRecvPin = 14;
+
+// GPIO to use to control the IR LED circuit. Recommended: 4 (D2).
+const uint16_t kIrLedPin = 4;
+
+// The Serial connection baud rate.
+// NOTE: Make sure you set your Serial Monitor to the same speed.
+const uint32_t kBaudRate = 115200;
+
+// As this program is a special purpose capture/resender, let's use a larger
+// than expected buffer so we can handle very large IR messages.
+const uint16_t kCaptureBufferSize = 1024; // 1024 == ~511 bits
+
+// kTimeout is the Nr. of milli-Seconds of no-more-data before we consider a
+// message ended.
+const uint8_t kTimeout = 50; // Milli-Seconds
+
+// kFrequency is the modulation frequency all UNKNOWN messages will be sent at.
+const uint16_t kFrequency = 38000; // in Hz. e.g. 38kHz.
+
+// ==================== end of TUNEABLE PARAMETERS ====================
+
+// The IR transmitter.
+IRsend irsend(kIrLedPin);
+// The IR receiver.
+IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, false);
+// Somewhere to store the captured message.
+decode_results results;
+
+// This section of code runs only once at start-up.
+void setup() {
+ irrecv.enableIRIn(); // Start up the IR receiver.
+ irsend.begin(); // Start up the IR sender.
+
+ Serial.begin(kBaudRate, SERIAL_8N1);
+ while (!Serial) // Wait for the serial connection to be establised.
+ delay(50);
+ Serial.println();
+
+ Serial.print("SmartIRRepeater is now running and waiting for IR input "
+ "on Pin ");
+ Serial.println(kRecvPin);
+ Serial.print("and will retransmit it on Pin ");
+ Serial.println(kIrLedPin);
+}
+
+// The repeating section of the code
+void loop() {
+ // Check if an IR message has been received.
+ if (irrecv.decode(&results)) { // We have captured something.
+ // The capture has stopped at this point.
+ decode_type_t protocol = results.decode_type;
+ uint16_t size = results.bits;
+ bool success = true;
+ // Is it a protocol we don't understand?
+ if (protocol == decode_type_t::UNKNOWN) { // Yes.
+ // Convert the results into an array suitable for sendRaw().
+ // resultToRawArray() allocates the memory we need for the array.
+ uint16_t *raw_array = resultToRawArray(&results);
+ // Find out how many elements are in the array.
+ size = getCorrectedRawLength(&results);
+ // Send it out via the IR LED circuit.
+ irsend.sendRaw(raw_array, size, kFrequency);
+ // Deallocate the memory allocated by resultToRawArray().
+ delete [] raw_array;
+ } else if (hasACState(protocol)) { // Does the message require a state[]?
+ // It does, so send with bytes instead.
+ success = irsend.send(protocol, results.state, size / 8);
+ } else { // Anything else must be a simple message protocol. ie. <= 64 bits
+ success = irsend.send(protocol, results.value, size);
+ }
+ // Resume capturing IR messages. It was not restarted until after we sent
+ // the message so we didn't capture our own message.
+ irrecv.resume();
+
+ // Display a crude timestamp & notification.
+ uint32_t now = millis();
+ Serial.printf(
+ "%06u.%03u: A %d-bit %s message was %ssuccessfully retransmitted.\n",
+ now / 1000, now % 1000, size, typeToString(protocol).c_str(),
+ success ? "" : "un");
+ }
+ yield(); // Or delay(milliseconds); This ensures the ESP doesn't WDT reset.
+}
diff --git a/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/TurnOnArgoAC.ino
similarity index 93%
rename from lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/TurnOnArgoAC.ino
rename to lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/TurnOnArgoAC.ino
index 3993d1151..9a5457d0c 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/TurnOnArgoAC.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/TurnOnArgoAC.ino
@@ -5,7 +5,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
-* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -23,9 +23,7 @@
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
@@ -44,7 +42,7 @@ void loop() {
// Set up what we want to send. See ir_Argo.cpp for all the options.
ac.setPower(true);
ac.setFan(kArgoFan1);
- ac.setCoolMode(kArgoCoolAuto);
+ ac.setMode(kArgoAuto);
ac.setTemp(25);
#if SEND_ARGO
diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino
similarity index 95%
rename from lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino
rename to lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino
index b3ab757de..d9eb9005f 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino
@@ -6,7 +6,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
-* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -24,9 +24,7 @@
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino
similarity index 90%
rename from lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino
rename to lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino
index 823a3f485..010d84cac 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino
@@ -1,7 +1,5 @@
// Copyright 2017 Jonny Graham, 2018 David Conran
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
@@ -30,11 +28,13 @@ void setup() {
Serial.println("Default state of the remote.");
printState();
Serial.println("Setting desired state for A/C.");
- ac.setCmd(kFujitsuAcCmdTurnOn);
- ac.setSwing(kFujitsuAcSwingBoth);
+ // See `fujitsu_ac_remote_model_t` in `ir_Fujitsu.h` for a list of models.
+ ac.setModel(ARRAH2E);
+ ac.setSwing(kFujitsuAcSwingOff);
ac.setMode(kFujitsuAcModeCool);
ac.setFanSpeed(kFujitsuAcFanHigh);
ac.setTemp(24); // 24C
+ ac.setCmd(kFujitsuAcCmdTurnOn);
}
void loop() {
diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino
rename to lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino
index b9b700741..ebdb7536b 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino
@@ -6,7 +6,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
-* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -23,9 +23,7 @@
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino
rename to lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino
index e719af68e..49bbb89ca 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino
@@ -6,7 +6,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
-* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -23,9 +23,7 @@
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino
rename to lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino
index 2ad2d7bc3..dbece716f 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino
@@ -6,7 +6,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
-* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -23,9 +23,7 @@
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino b/lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino
rename to lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino
index ea39ac5e2..b7e399f09 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino
@@ -6,7 +6,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
-* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -23,9 +23,7 @@
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino b/lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino
rename to lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino
index d78178098..a37a07e5c 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino
@@ -6,7 +6,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
-* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -23,9 +23,7 @@
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino b/lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino
similarity index 95%
rename from lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino
rename to lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino
index b7881eead..014272955 100644
--- a/lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino
@@ -5,7 +5,7 @@
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
-* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
+* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
@@ -23,9 +23,7 @@
* for your first time. e.g. ESP-12 etc.
*/
-#ifndef UNIT_TEST
#include
-#endif
#include
#include
#include
diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/platformio.ini
new file mode 100644
index 000000000..1aba0afcc
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+
+[env]
+lib_extra_dirs = ../../
+lib_ldf_mode = deep+
+lib_ignore = examples
+build_flags =
+
+[env:nodemcuv2]
+platform = espressif8266
+framework = arduino
+board = nodemcuv2
+
+[env:esp32dev]
+platform = espressif32
+framework = arduino
+board = esp32dev
diff --git a/lib/IRremoteESP8266-2.6.0/keywords.txt b/lib/IRremoteESP8266-2.6.5/keywords.txt
similarity index 79%
rename from lib/IRremoteESP8266-2.6.0/keywords.txt
rename to lib/IRremoteESP8266-2.6.5/keywords.txt
index a498c5d61..db2d398a1 100644
--- a/lib/IRremoteESP8266-2.6.0/keywords.txt
+++ b/lib/IRremoteESP8266-2.6.5/keywords.txt
@@ -20,12 +20,19 @@
# Datatypes & Classes (KEYWORD1)
#######################################
+IRAmcorAc KEYWORD1
IRArgoAC KEYWORD1
IRCoolixAC KEYWORD1
+IRDaikin128 KEYWORD1
+IRDaikin152 KEYWORD1
+IRDaikin160 KEYWORD1
+IRDaikin176 KEYWORD1
IRDaikin2 KEYWORD1
IRDaikin216 KEYWORD1
IRDaikinESP KEYWORD1
+IRElectraAc KEYWORD1
IRFujitsuAC KEYWORD1
+IRGoodweatherAc KEYWORD1
IRGreeAC KEYWORD1
IRHaierAC KEYWORD1
IRHaierACYRW02 KEYWORD1
@@ -35,8 +42,10 @@ IRMideaAC KEYWORD1
IRMitsubishiAC KEYWORD1
IRMitsubishiHeavy152Ac KEYWORD1
IRMitsubishiHeavy88Ac KEYWORD1
+IRNeoclimaAc KEYWORD1
IRPanasonicAc KEYWORD1
IRSamsungAc KEYWORD1
+IRSharpAc KEYWORD1
IRTcl112Ac KEYWORD1
IRTecoAc KEYWORD1
IRToshibaAC KEYWORD1
@@ -49,60 +58,100 @@ IRsend KEYWORD1
IRtimer KEYWORD1
TimerMs KEYWORD1
decode_results KEYWORD1
-ir_params_t KEYWORD1
+decode_type_t KEYWORD1
+fanspeed_t KEYWORD1
+fujitsu_ac_remote_model_t KEYWORD1
+gree_ac_remote_model_t KEYWORD1
+irparams_t KEYWORD1
match_result_t KEYWORD1
+opmode_t KEYWORD1
+panasonic_ac_remote_model_t KEYWORD1
+state_t KEYWORD1
+swingh_t KEYWORD1
+swingv_t KEYWORD1
+whirlpool_ac_remote_model_t KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
_delayMicroseconds KEYWORD2
+_matchGeneric KEYWORD2
_setMode KEYWORD2
_setTemp KEYWORD2
+_validTolerance KEYWORD2
add KEYWORD2
+addBoolToString KEYWORD2
+addFanToString KEYWORD2
+addIntToString KEYWORD2
+addLabeledString KEYWORD2
+addModeToString KEYWORD2
+addTempToString KEYWORD2
+amcor KEYWORD2
argo KEYWORD2
+bcdToUint8 KEYWORD2
begin KEYWORD2
+boolToString KEYWORD2
buildFromState KEYWORD2
buildState KEYWORD2
calcBlockChecksum KEYWORD2
calcChecksum KEYWORD2
+calcFirstChecksum KEYWORD2
calcLGChecksum KEYWORD2
+calcSecondChecksum KEYWORD2
calcUSecPeriod KEYWORD2
calculateChecksum KEYWORD2
calibrate KEYWORD2
cancelOffTimer KEYWORD2
cancelOnTimer KEYWORD2
cancelTimers KEYWORD2
+celsiusToFahrenheit KEYWORD2
checkZjsSig KEYWORD2
checkZmsSig KEYWORD2
checksum KEYWORD2
clearOnTimerFlag KEYWORD2
clearSensorTemp KEYWORD2
clearSleepTimerFlag KEYWORD2
+cmpStates KEYWORD2
compare KEYWORD2
+convertFan KEYWORD2
+convertMode KEYWORD2
+convertSwingH KEYWORD2
+convertSwingV KEYWORD2
coolix KEYWORD2
copyIrParams KEYWORD2
countBits KEYWORD2
daikin KEYWORD2
+daikin128 KEYWORD2
+daikin160 KEYWORD2
+daikin176 KEYWORD2
daikin2 KEYWORD2
daikin216 KEYWORD2
decode KEYWORD2
decodeAiwaRCT501 KEYWORD2
+decodeAmcor KEYWORD2
+decodeArgo KEYWORD2
decodeCOOLIX KEYWORD2
decodeCarrierAC KEYWORD2
decodeDISH KEYWORD2
decodeDaikin KEYWORD2
+decodeDaikin128 KEYWORD2
+decodeDaikin152 KEYWORD2
+decodeDaikin160 KEYWORD2
+decodeDaikin176 KEYWORD2
decodeDaikin2 KEYWORD2
decodeDaikin216 KEYWORD2
decodeDenon KEYWORD2
decodeElectraAC KEYWORD2
decodeFujitsuAC KEYWORD2
decodeGICable KEYWORD2
+decodeGoodweather KEYWORD2
decodeGree KEYWORD2
decodeHaierAC KEYWORD2
decodeHaierACYRW02 KEYWORD2
decodeHash KEYWORD2
decodeHitachiAC KEYWORD2
+decodeInax KEYWORD2
decodeJVC KEYWORD2
decodeKelvinator KEYWORD2
decodeLG KEYWORD2
@@ -117,6 +166,7 @@ decodeMitsubishi2 KEYWORD2
decodeMitsubishiAC KEYWORD2
decodeMitsubishiHeavy KEYWORD2
decodeNEC KEYWORD2
+decodeNeoclima KEYWORD2
decodeNikai KEYWORD2
decodePanasonic KEYWORD2
decodePanasonicAC KEYWORD2
@@ -130,18 +180,23 @@ decodeSamsungAC KEYWORD2
decodeSanyo KEYWORD2
decodeSanyoLC7461 KEYWORD2
decodeSharp KEYWORD2
+decodeSharpAc KEYWORD2
decodeSony KEYWORD2
decodeTcl112Ac KEYWORD2
decodeTeco KEYWORD2
+decodeToState KEYWORD2
decodeToshibaAC KEYWORD2
+decodeTrotec KEYWORD2
decodeVestelAc KEYWORD2
decodeWhirlpoolAC KEYWORD2
decodeWhynter KEYWORD2
+defaultBits KEYWORD2
disableIRIn KEYWORD2
disableOffTimer KEYWORD2
disableOnTimer KEYWORD2
disableSleepTimer KEYWORD2
elapsed KEYWORD2
+electra KEYWORD2
enableIRIn KEYWORD2
enableIROut KEYWORD2
enableOffTimer KEYWORD2
@@ -162,11 +217,13 @@ encodeSanyoLC7461 KEYWORD2
encodeSharp KEYWORD2
encodeSony KEYWORD2
encodeTime KEYWORD2
-fanspeed_t KEYWORD2
+fahrenheitToCelsius KEYWORD2
+fanspeedToString KEYWORD2
fixChecksum KEYWORD2
fixup KEYWORD2
fujitsu KEYWORD2
get3D KEYWORD2
+get8CHeat KEYWORD2
getBeep KEYWORD2
getBufSize KEYWORD2
getButton KEYWORD2
@@ -175,9 +232,9 @@ getClock KEYWORD2
getCmd KEYWORD2
getComfort KEYWORD2
getCommand KEYWORD2
-getCoolMode KEYWORD2
getCorrectedRawLength KEYWORD2
getCurrTime KEYWORD2
+getCurrentDay KEYWORD2
getCurrentTime KEYWORD2
getEcono KEYWORD2
getEye KEYWORD2
@@ -186,14 +243,19 @@ getFan KEYWORD2
getFanSpeed KEYWORD2
getFilter KEYWORD2
getFlap KEYWORD2
+getFollow KEYWORD2
+getFresh KEYWORD2
getFreshAir KEYWORD2
getFreshAirHigh KEYWORD2
getHealth KEYWORD2
-getHeatMode KEYWORD2
+getHold KEYWORD2
+getHumid KEYWORD2
+getIFeel KEYWORD2
getIon KEYWORD2
getIonFilter KEYWORD2
getLed KEYWORD2
getLight KEYWORD2
+getLightToggle KEYWORD2
getMax KEYWORD2
getMode KEYWORD2
getMold KEYWORD2
@@ -205,6 +267,7 @@ getOffTimerEnabled KEYWORD2
getOnTime KEYWORD2
getOnTimer KEYWORD2
getOnTimerEnabled KEYWORD2
+getOutsideQuiet KEYWORD2
getPower KEYWORD2
getPowerToggle KEYWORD2
getPowerful KEYWORD2
@@ -212,6 +275,8 @@ getPurify KEYWORD2
getQuiet KEYWORD2
getRClevel KEYWORD2
getRaw KEYWORD2
+getRoomTemp KEYWORD2
+getSave KEYWORD2
getSensor KEYWORD2
getSensorTemp KEYWORD2
getSilent KEYWORD2
@@ -224,7 +289,10 @@ getStateLength KEYWORD2
getStopClock KEYWORD2
getSuper KEYWORD2
getSwing KEYWORD2
+getSwingH KEYWORD2
getSwingHorizontal KEYWORD2
+getSwingV KEYWORD2
+getSwingVToggle KEYWORD2
getSwingVertical KEYWORD2
getSwingVerticalAuto KEYWORD2
getSwingVerticalPosition KEYWORD2
@@ -233,11 +301,18 @@ getTempOffset KEYWORD2
getTempRaw KEYWORD2
getTime KEYWORD2
getTimer KEYWORD2
+getTimerEnabled KEYWORD2
+getTolerance KEYWORD2
getTurbo KEYWORD2
+getUseCelsius KEYWORD2
getVane KEYWORD2
+getWeeklyTimerEnable KEYWORD2
+getWiFi KEYWORD2
+getWideVane KEYWORD2
getXFan KEYWORD2
getZoneFollow KEYWORD2
getiFeel KEYWORD2
+goodweather KEYWORD2
gree KEYWORD2
haier KEYWORD2
haierYrwo2 KEYWORD2
@@ -251,6 +326,7 @@ isOnTimerActive KEYWORD2
isOnTimerEnabled KEYWORD2
isProtocolSupported KEYWORD2
isSpecialState KEYWORD2
+isSwingVToggle KEYWORD2
isTimeCommand KEYWORD2
isTimerActive KEYWORD2
isTimerEnabled KEYWORD2
@@ -260,24 +336,29 @@ ledOn KEYWORD2
mark KEYWORD2
match KEYWORD2
matchAtLeast KEYWORD2
+matchBytes KEYWORD2
matchData KEYWORD2
+matchGeneric KEYWORD2
matchMark KEYWORD2
matchSpace KEYWORD2
midea KEYWORD2
+minRepeats KEYWORD2
+minsToString KEYWORD2
mitsubishi KEYWORD2
mitsubishiHeavy152 KEYWORD2
mitsubishiHeavy88 KEYWORD2
-mode) KEYWORD2
+msToString KEYWORD2
+neoclima KEYWORD2
off KEYWORD2
on KEYWORD2
-opmode_t KEYWORD2
+opmodeToString KEYWORD2
panasonic KEYWORD2
-position) KEYWORD2
recoverSavedState KEYWORD2
-renderTime KEYWORD2
reset KEYWORD2
+resultAcToString KEYWORD2
resultToHexidecimal KEYWORD2
resultToHumanReadableBasic KEYWORD2
+resultToRawArray KEYWORD2
resultToSourceCode KEYWORD2
resultToTimingInfo KEYWORD2
resume KEYWORD2
@@ -286,11 +367,16 @@ samsung KEYWORD2
send KEYWORD2
sendAc KEYWORD2
sendAiwaRCT501 KEYWORD2
+sendAmcor KEYWORD2
sendArgo KEYWORD2
sendCOOLIX KEYWORD2
sendCarrierAC KEYWORD2
sendDISH KEYWORD2
sendDaikin KEYWORD2
+sendDaikin128 KEYWORD2
+sendDaikin152 KEYWORD2
+sendDaikin160 KEYWORD2
+sendDaikin176 KEYWORD2
sendDaikin2 KEYWORD2
sendDaikin216 KEYWORD2
sendData KEYWORD2
@@ -301,12 +387,14 @@ sendFujitsuAC KEYWORD2
sendGC KEYWORD2
sendGICable KEYWORD2
sendGeneric KEYWORD2
+sendGoodweather KEYWORD2
sendGree KEYWORD2
sendHaierAC KEYWORD2
sendHaierACYRW02 KEYWORD2
sendHitachiAC KEYWORD2
sendHitachiAC1 KEYWORD2
sendHitachiAC2 KEYWORD2
+sendInax KEYWORD2
sendJVC KEYWORD2
sendKelvinator KEYWORD2
sendLG KEYWORD2
@@ -323,6 +411,7 @@ sendMitsubishiAC KEYWORD2
sendMitsubishiHeavy152 KEYWORD2
sendMitsubishiHeavy88 KEYWORD2
sendNEC KEYWORD2
+sendNeoclima KEYWORD2
sendNikai KEYWORD2
sendOff KEYWORD2
sendOn KEYWORD2
@@ -340,6 +429,7 @@ sendSamsung36 KEYWORD2
sendSamsungAC KEYWORD2
sendSanyoLC7461 KEYWORD2
sendSharp KEYWORD2
+sendSharpAc KEYWORD2
sendSharpRaw KEYWORD2
sendSherwood KEYWORD2
sendSony KEYWORD2
@@ -352,6 +442,7 @@ sendWhirlpoolAC KEYWORD2
sendWhynter KEYWORD2
serialPrintUint64 KEYWORD2
set3D KEYWORD2
+set8CHeat KEYWORD2
setAuto KEYWORD2
setBeep KEYWORD2
setButton KEYWORD2
@@ -360,8 +451,8 @@ setClock KEYWORD2
setCmd KEYWORD2
setComfort KEYWORD2
setCommand KEYWORD2
-setCoolMode KEYWORD2
setCurrTime KEYWORD2
+setCurrentDay KEYWORD2
setCurrentTime KEYWORD2
setEcono KEYWORD2
setEye KEYWORD2
@@ -370,14 +461,19 @@ setFan KEYWORD2
setFanSpeed KEYWORD2
setFilter KEYWORD2
setFlap KEYWORD2
+setFollow KEYWORD2
+setFresh KEYWORD2
setFreshAir KEYWORD2
setFreshAirHigh KEYWORD2
setHealth KEYWORD2
-setHeatMode KEYWORD2
+setHold KEYWORD2
+setHumid KEYWORD2
+setIFeel KEYWORD2
setIon KEYWORD2
setIonFilter KEYWORD2
setLed KEYWORD2
setLight KEYWORD2
+setLightToggle KEYWORD2
setMax KEYWORD2
setMode KEYWORD2
setModel KEYWORD2
@@ -385,8 +481,11 @@ setMold KEYWORD2
setNight KEYWORD2
setOffTimer KEYWORD2
setOffTimerActive KEYWORD2
+setOffTimerEnabled KEYWORD2
setOnTimer KEYWORD2
setOnTimerActive KEYWORD2
+setOnTimerEnabled KEYWORD2
+setOutsideQuiet KEYWORD2
setPower KEYWORD2
setPowerToggle KEYWORD2
setPowerful KEYWORD2
@@ -394,6 +493,7 @@ setPurify KEYWORD2
setQuiet KEYWORD2
setRaw KEYWORD2
setRoomTemp KEYWORD2
+setSave KEYWORD2
setSensor KEYWORD2
setSensorTemp KEYWORD2
setSensorTempRaw KEYWORD2
@@ -404,42 +504,54 @@ setStartClock KEYWORD2
setStopClock KEYWORD2
setSuper KEYWORD2
setSwing KEYWORD2
+setSwingH KEYWORD2
setSwingHorizontal KEYWORD2
+setSwingV KEYWORD2
+setSwingVToggle KEYWORD2
setSwingVertical KEYWORD2
setTemp KEYWORD2
setTempRaw KEYWORD2
setTime KEYWORD2
setTimer KEYWORD2
setTimerActive KEYWORD2
+setTimerEnabled KEYWORD2
+setTolerance KEYWORD2
setTurbo KEYWORD2
setUnknownThreshold KEYWORD2
+setUseCelsius KEYWORD2
setVane KEYWORD2
+setWeeklyTimerEnable KEYWORD2
+setWiFi KEYWORD2
+setWideVane KEYWORD2
setXFan KEYWORD2
setZoneFollow KEYWORD2
setiFeel KEYWORD2
+sharp KEYWORD2
space KEYWORD2
-speed) KEYWORD2
stateReset KEYWORD2
stepHoriz KEYWORD2
stepVert KEYWORD2
strToBool KEYWORD2
+strToDecodeType KEYWORD2
strToModel KEYWORD2
sumBytes KEYWORD2
-swingh_t KEYWORD2
-swingv) KEYWORD2
-swingv_t KEYWORD2
+sumNibbles KEYWORD2
+swinghToString KEYWORD2
+swingvToString KEYWORD2
tcl112 KEYWORD2
teco KEYWORD2
ticksHigh KEYWORD2
ticksLow KEYWORD2
-timeToString KEYWORD2
toString KEYWORD2
toggleRC5 KEYWORD2
toggleRC6 KEYWORD2
+toggleSwingHoriz KEYWORD2
+toggleSwingVert KEYWORD2
toshiba KEYWORD2
trotec KEYWORD2
typeToString KEYWORD2
uint64ToString KEYWORD2
+uint8ToBcd KEYWORD2
updateSavedState KEYWORD2
validChecksum KEYWORD2
vestel KEYWORD2
@@ -450,9 +562,11 @@ xorBytes KEYWORD2
# Constants (LITERAL1)
#######################################
+// LITERAL1
AIWA_RC_T501 LITERAL1
AIWA_RC_T501_BITS LITERAL1
ALLOW_DELAY_CALLS LITERAL1
+AMCOR LITERAL1
ARDB1 LITERAL1
ARGO LITERAL1
ARGO_COMMAND_LENGTH LITERAL1
@@ -477,12 +591,18 @@ ARGO_HEAT_BLINK LITERAL1
ARGO_HEAT_ON LITERAL1
ARGO_MAX_TEMP LITERAL1
ARGO_MIN_TEMP LITERAL1
+ARJW2 LITERAL1
ARRAH2E LITERAL1
+ARREB1E LITERAL1
CARRIER_AC LITERAL1
CARRIER_AC_BITS LITERAL1
COOLIX LITERAL1
COOLIX_BITS LITERAL1
DAIKIN LITERAL1
+DAIKIN128 LITERAL1
+DAIKIN152 LITERAL1
+DAIKIN160 LITERAL1
+DAIKIN176 LITERAL1
DAIKIN2 LITERAL1
DAIKIN216 LITERAL1
DAIKIN_AUTO LITERAL1
@@ -499,10 +619,15 @@ DAIKIN_MAX_TEMP LITERAL1
DAIKIN_MIN_TEMP LITERAL1
DECODE_AC LITERAL1
DECODE_AIWA_RC_T501 LITERAL1
+DECODE_AMCOR LITERAL1
DECODE_ARGO LITERAL1
DECODE_CARRIER_AC LITERAL1
DECODE_COOLIX LITERAL1
DECODE_DAIKIN LITERAL1
+DECODE_DAIKIN128 LITERAL1
+DECODE_DAIKIN152 LITERAL1
+DECODE_DAIKIN160 LITERAL1
+DECODE_DAIKIN176 LITERAL1
DECODE_DAIKIN2 LITERAL1
DECODE_DAIKIN216 LITERAL1
DECODE_DENON LITERAL1
@@ -511,6 +636,7 @@ DECODE_ELECTRA_AC LITERAL1
DECODE_FUJITSU_AC LITERAL1
DECODE_GICABLE LITERAL1
DECODE_GLOBALCACHE LITERAL1
+DECODE_GOODWEATHER LITERAL1
DECODE_GREE LITERAL1
DECODE_HAIER_AC LITERAL1
DECODE_HAIER_AC_YRW02 LITERAL1
@@ -518,6 +644,7 @@ DECODE_HASH LITERAL1
DECODE_HITACHI_AC LITERAL1
DECODE_HITACHI_AC1 LITERAL1
DECODE_HITACHI_AC2 LITERAL1
+DECODE_INAX LITERAL1
DECODE_JVC LITERAL1
DECODE_KELVINATOR LITERAL1
DECODE_LASERTAG LITERAL1
@@ -532,6 +659,7 @@ DECODE_MITSUBISHIHEAVY LITERAL1
DECODE_MITSUBISHI_AC LITERAL1
DECODE_MWM LITERAL1
DECODE_NEC LITERAL1
+DECODE_NEOCLIMA LITERAL1
DECODE_NIKAI LITERAL1
DECODE_PANASONIC LITERAL1
DECODE_PANASONIC_AC LITERAL1
@@ -545,6 +673,7 @@ DECODE_SAMSUNG36 LITERAL1
DECODE_SAMSUNG_AC LITERAL1
DECODE_SANYO LITERAL1
DECODE_SHARP LITERAL1
+DECODE_SHARP_AC LITERAL1
DECODE_SHERWOOD LITERAL1
DECODE_SONY LITERAL1
DECODE_TCL112AC LITERAL1
@@ -593,6 +722,7 @@ FUJITSU_AC_SWING_VERT LITERAL1
GICABLE LITERAL1
GICABLE_BITS LITERAL1
GLOBALCACHE LITERAL1
+GOODWEATHER LITERAL1
GREE LITERAL1
GREE_AUTO LITERAL1
GREE_COOL LITERAL1
@@ -682,6 +812,7 @@ HITACHI_AC2_STATE_LENGTH LITERAL1
HITACHI_AC_BITS LITERAL1
HITACHI_AC_STATE_LENGTH LITERAL1
ICACHE_RAM_ATTR LITERAL1
+INAX LITERAL1
JVC LITERAL1
JVC_BITS LITERAL1
KELVINATOR LITERAL1
@@ -749,6 +880,7 @@ MWM LITERAL1
NEC LITERAL1
NEC_BITS LITERAL1
NEC_LIKE LITERAL1
+NEOCLIMA LITERAL1
NIKAI LITERAL1
NIKAI_BITS LITERAL1
ONCE LITERAL1
@@ -777,10 +909,15 @@ SANYO_LC7461 LITERAL1
SANYO_LC7461_BITS LITERAL1
SANYO_SA8650B_BITS LITERAL1
SEND_AIWA_RC_T501 LITERAL1
+SEND_AMCOR LITERAL1
SEND_ARGO LITERAL1
SEND_CARRIER_AC LITERAL1
SEND_COOLIX LITERAL1
SEND_DAIKIN LITERAL1
+SEND_DAIKIN128 LITERAL1
+SEND_DAIKIN152 LITERAL1
+SEND_DAIKIN160 LITERAL1
+SEND_DAIKIN176 LITERAL1
SEND_DAIKIN2 LITERAL1
SEND_DAIKIN216 LITERAL1
SEND_DENON LITERAL1
@@ -789,12 +926,14 @@ SEND_ELECTRA_AC LITERAL1
SEND_FUJITSU_AC LITERAL1
SEND_GICABLE LITERAL1
SEND_GLOBALCACHE LITERAL1
+SEND_GOODWEATHER LITERAL1
SEND_GREE LITERAL1
SEND_HAIER_AC LITERAL1
SEND_HAIER_AC_YRW02 LITERAL1
SEND_HITACHI_AC LITERAL1
SEND_HITACHI_AC1 LITERAL1
SEND_HITACHI_AC2 LITERAL1
+SEND_INAX LITERAL1
SEND_JVC LITERAL1
SEND_KELVINATOR LITERAL1
SEND_LASERTAG LITERAL1
@@ -809,6 +948,7 @@ SEND_MITSUBISHIHEAVY LITERAL1
SEND_MITSUBISHI_AC LITERAL1
SEND_MWM LITERAL1
SEND_NEC LITERAL1
+SEND_NEOCLIMA LITERAL1
SEND_NIKAI LITERAL1
SEND_PANASONIC LITERAL1
SEND_PANASONIC_AC LITERAL1
@@ -823,6 +963,7 @@ SEND_SAMSUNG36 LITERAL1
SEND_SAMSUNG_AC LITERAL1
SEND_SANYO LITERAL1
SEND_SHARP LITERAL1
+SEND_SHARP_AC LITERAL1
SEND_SHERWOOD LITERAL1
SEND_SONY LITERAL1
SEND_TCL112AC LITERAL1
@@ -833,6 +974,7 @@ SEND_VESTEL_AC LITERAL1
SEND_WHIRLPOOL_AC LITERAL1
SEND_WHYNTER LITERAL1
SHARP LITERAL1
+SHARP_AC LITERAL1
SHARP_BITS LITERAL1
SHERWOOD LITERAL1
SHERWOOD_BITS LITERAL1
@@ -868,26 +1010,66 @@ TROTEC_MAX_TIMER LITERAL1
TROTEC_MIN_TEMP LITERAL1
UNKNOWN LITERAL1
UNUSED LITERAL1
+USE_IRAM_ATTR LITERAL1
VESTEL_AC LITERAL1
WHIRLPOOL_AC LITERAL1
WHYNTER LITERAL1
WHYNTER_BITS LITERAL1
+YAW1F LITERAL1
+YBOFB LITERAL1
kAiwaRcT501Bits LITERAL1
kAiwaRcT501MinRepeats LITERAL1
kAiwaRcT501PostBits LITERAL1
kAiwaRcT501PostData LITERAL1
kAiwaRcT501PreBits LITERAL1
kAiwaRcT501PreData LITERAL1
+kAmcorAuto LITERAL1
+kAmcorBits LITERAL1
+kAmcorChecksumByte LITERAL1
+kAmcorCool LITERAL1
+kAmcorDefaultRepeat LITERAL1
+kAmcorDry LITERAL1
+kAmcorFan LITERAL1
+kAmcorFanAuto LITERAL1
+kAmcorFanMask LITERAL1
+kAmcorFanMax LITERAL1
+kAmcorFanMed LITERAL1
+kAmcorFanMin LITERAL1
+kAmcorFooterMark LITERAL1
+kAmcorGap LITERAL1
+kAmcorHdrMark LITERAL1
+kAmcorHdrSpace LITERAL1
+kAmcorHeat LITERAL1
+kAmcorMaxMask LITERAL1
+kAmcorMaxTemp LITERAL1
+kAmcorMinTemp LITERAL1
+kAmcorModeFanByte LITERAL1
+kAmcorModeMask LITERAL1
+kAmcorOneMark LITERAL1
+kAmcorOneSpace LITERAL1
+kAmcorPowerByte LITERAL1
+kAmcorPowerMask LITERAL1
+kAmcorPowerOff LITERAL1
+kAmcorPowerOn LITERAL1
+kAmcorSpecialByte LITERAL1
+kAmcorStateLength LITERAL1
+kAmcorTempByte LITERAL1
+kAmcorTempMask LITERAL1
+kAmcorTolerance LITERAL1
+kAmcorVentMask LITERAL1
+kAmcorZeroMark LITERAL1
+kAmcorZeroSpace LITERAL1
+kArgoAuto LITERAL1
kArgoBitMark LITERAL1
-kArgoCoolAuto LITERAL1
-kArgoCoolHum LITERAL1
-kArgoCoolOff LITERAL1
-kArgoCoolOn LITERAL1
+kArgoBits LITERAL1
+kArgoCool LITERAL1
kArgoDefaultRepeat LITERAL1
+kArgoDry LITERAL1
kArgoFan1 LITERAL1
kArgoFan2 LITERAL1
kArgoFan3 LITERAL1
kArgoFanAuto LITERAL1
+kArgoFanMask LITERAL1
kArgoFlap1 LITERAL1
kArgoFlap2 LITERAL1
kArgoFlap3 LITERAL1
@@ -896,15 +1078,29 @@ kArgoFlap5 LITERAL1
kArgoFlap6 LITERAL1
kArgoFlapAuto LITERAL1
kArgoFlapFull LITERAL1
+kArgoGap LITERAL1
kArgoHdrMark LITERAL1
kArgoHdrSpace LITERAL1
+kArgoHeat LITERAL1
kArgoHeatAuto LITERAL1
+kArgoHeatBit LITERAL1
kArgoHeatBlink LITERAL1
-kArgoHeatOn LITERAL1
+kArgoIFeelBit LITERAL1
+kArgoMaxBit LITERAL1
+kArgoMaxRoomTemp LITERAL1
kArgoMaxTemp LITERAL1
kArgoMinTemp LITERAL1
+kArgoModeMask LITERAL1
+kArgoNightBit LITERAL1
+kArgoOff LITERAL1
kArgoOneSpace LITERAL1
+kArgoPowerBit LITERAL1
+kArgoRoomTempHighMask LITERAL1
+kArgoRoomTempLowMask LITERAL1
kArgoStateLength LITERAL1
+kArgoTempHighMask LITERAL1
+kArgoTempLowMask LITERAL1
+kArgoTempOffset LITERAL1
kArgoZeroSpace LITERAL1
kAuto LITERAL1
kCarrierAcBitMark LITERAL1
@@ -965,11 +1161,128 @@ kCoolixUnknown LITERAL1
kCoolixZeroSpace LITERAL1
kCoolixZeroSpaceTicks LITERAL1
kCoolixZoneFollowMask LITERAL1
+kDaikin128Auto LITERAL1
+kDaikin128BitCeiling LITERAL1
+kDaikin128BitEcono LITERAL1
+kDaikin128BitHalfHour LITERAL1
+kDaikin128BitMark LITERAL1
+kDaikin128BitPowerToggle LITERAL1
+kDaikin128BitSleep LITERAL1
+kDaikin128BitSwing LITERAL1
+kDaikin128BitTimerEnabled LITERAL1
+kDaikin128BitWall LITERAL1
+kDaikin128Bits LITERAL1
+kDaikin128ByteClockHours LITERAL1
+kDaikin128ByteClockMins LITERAL1
+kDaikin128ByteEconoLight LITERAL1
+kDaikin128ByteModeFan LITERAL1
+kDaikin128ByteOffTimer LITERAL1
+kDaikin128ByteOnTimer LITERAL1
+kDaikin128BytePowerSwingSleep LITERAL1
+kDaikin128ByteTemp LITERAL1
+kDaikin128Cool LITERAL1
+kDaikin128DefaultRepeat LITERAL1
+kDaikin128Dry LITERAL1
+kDaikin128Fan LITERAL1
+kDaikin128FanAuto LITERAL1
+kDaikin128FanHigh LITERAL1
+kDaikin128FanLow LITERAL1
+kDaikin128FanMed LITERAL1
+kDaikin128FanPowerful LITERAL1
+kDaikin128FanQuiet LITERAL1
+kDaikin128FooterMark LITERAL1
+kDaikin128Freq LITERAL1
+kDaikin128Gap LITERAL1
+kDaikin128HdrMark LITERAL1
+kDaikin128HdrSpace LITERAL1
+kDaikin128Heat LITERAL1
+kDaikin128LeaderMark LITERAL1
+kDaikin128LeaderSpace LITERAL1
+kDaikin128MaskFan LITERAL1
+kDaikin128MaskHours LITERAL1
+kDaikin128MaskLight LITERAL1
+kDaikin128MaskMode LITERAL1
+kDaikin128MaxTemp LITERAL1
+kDaikin128MinTemp LITERAL1
+kDaikin128OneSpace LITERAL1
+kDaikin128SectionLength LITERAL1
+kDaikin128Sections LITERAL1
+kDaikin128StateLength LITERAL1
+kDaikin128ZeroSpace LITERAL1
+kDaikin152BitMark LITERAL1
+kDaikin152Bits LITERAL1
+kDaikin152DefaultRepeat LITERAL1
+kDaikin152Freq LITERAL1
+kDaikin152Gap LITERAL1
+kDaikin152HdrMark LITERAL1
+kDaikin152HdrSpace LITERAL1
+kDaikin152LeaderBits LITERAL1
+kDaikin152OneSpace LITERAL1
+kDaikin152StateLength LITERAL1
+kDaikin152ZeroSpace LITERAL1
+kDaikin160BitMark LITERAL1
+kDaikin160Bits LITERAL1
+kDaikin160ByteFan LITERAL1
+kDaikin160ByteMode LITERAL1
+kDaikin160BytePower LITERAL1
+kDaikin160ByteSwingV LITERAL1
+kDaikin160ByteTemp LITERAL1
+kDaikin160DefaultRepeat LITERAL1
+kDaikin160Freq LITERAL1
+kDaikin160Gap LITERAL1
+kDaikin160HdrMark LITERAL1
+kDaikin160HdrSpace LITERAL1
+kDaikin160MaskFan LITERAL1
+kDaikin160MaskMode LITERAL1
+kDaikin160MaskSwingV LITERAL1
+kDaikin160MaskTemp LITERAL1
+kDaikin160OneSpace LITERAL1
+kDaikin160Section1Length LITERAL1
+kDaikin160Section2Length LITERAL1
+kDaikin160Sections LITERAL1
+kDaikin160StateLength LITERAL1
+kDaikin160SwingVAuto LITERAL1
+kDaikin160SwingVHigh LITERAL1
+kDaikin160SwingVHighest LITERAL1
+kDaikin160SwingVLow LITERAL1
+kDaikin160SwingVLowest LITERAL1
+kDaikin160SwingVMiddle LITERAL1
+kDaikin160ZeroSpace LITERAL1
+kDaikin176BitMark LITERAL1
+kDaikin176Bits LITERAL1
+kDaikin176ByteFan LITERAL1
+kDaikin176ByteMode LITERAL1
+kDaikin176ByteModeButton LITERAL1
+kDaikin176BytePower LITERAL1
+kDaikin176ByteSwingH LITERAL1
+kDaikin176ByteTemp LITERAL1
+kDaikin176Cool LITERAL1
+kDaikin176DefaultRepeat LITERAL1
+kDaikin176DryFanTemp LITERAL1
+kDaikin176FanMax LITERAL1
+kDaikin176Freq LITERAL1
+kDaikin176Gap LITERAL1
+kDaikin176HdrMark LITERAL1
+kDaikin176HdrSpace LITERAL1
+kDaikin176MaskFan LITERAL1
+kDaikin176MaskMode LITERAL1
+kDaikin176MaskSwingH LITERAL1
+kDaikin176MaskTemp LITERAL1
+kDaikin176ModeButton LITERAL1
+kDaikin176OneSpace LITERAL1
+kDaikin176Section1Length LITERAL1
+kDaikin176Section2Length LITERAL1
+kDaikin176Sections LITERAL1
+kDaikin176StateLength LITERAL1
+kDaikin176SwingHAuto LITERAL1
+kDaikin176SwingHOff LITERAL1
+kDaikin176ZeroSpace LITERAL1
kDaikin216BitMark LITERAL1
kDaikin216Bits LITERAL1
kDaikin216ByteFan LITERAL1
kDaikin216ByteMode LITERAL1
kDaikin216BytePower LITERAL1
+kDaikin216BytePowerful LITERAL1
kDaikin216ByteSwingH LITERAL1
kDaikin216ByteSwingV LITERAL1
kDaikin216ByteTemp LITERAL1
@@ -1039,6 +1352,7 @@ kDaikinBitPower LITERAL1
kDaikinBitPowerful LITERAL1
kDaikinBitSensor LITERAL1
kDaikinBitSilent LITERAL1
+kDaikinBitWeeklyTimer LITERAL1
kDaikinBits LITERAL1
kDaikinBitsShort LITERAL1
kDaikinByteChecksum1 LITERAL1
@@ -1063,6 +1377,7 @@ kDaikinByteSensor LITERAL1
kDaikinByteSilent LITERAL1
kDaikinByteSwingH LITERAL1
kDaikinByteTemp LITERAL1
+kDaikinByteWeeklyTimer LITERAL1
kDaikinCool LITERAL1
kDaikinCurBit LITERAL1
kDaikinCurIndex LITERAL1
@@ -1071,6 +1386,7 @@ kDaikinDry LITERAL1
kDaikinFan LITERAL1
kDaikinFanAuto LITERAL1
kDaikinFanMax LITERAL1
+kDaikinFanMed LITERAL1
kDaikinFanMin LITERAL1
kDaikinFanQuiet LITERAL1
kDaikinFirstHeader64 LITERAL1
@@ -1095,7 +1411,9 @@ kDaikinStateLengthShort LITERAL1
kDaikinTolerance LITERAL1
kDaikinUnusedTime LITERAL1
kDaikinZeroSpace LITERAL1
+kDefaultESP32Timer LITERAL1
kDefaultMessageGap LITERAL1
+kDenon48Bits LITERAL1
kDenonBitMark LITERAL1
kDenonBitMarkTicks LITERAL1
kDenonBits LITERAL1
@@ -1131,13 +1449,32 @@ kDishZeroSpaceTicks LITERAL1
kDry LITERAL1
kDutyDefault LITERAL1
kDutyMax LITERAL1
+kElectraAcAuto LITERAL1
kElectraAcBitMark LITERAL1
kElectraAcBits LITERAL1
+kElectraAcCool LITERAL1
+kElectraAcDry LITERAL1
+kElectraAcFan LITERAL1
+kElectraAcFanAuto LITERAL1
+kElectraAcFanHigh LITERAL1
+kElectraAcFanLow LITERAL1
+kElectraAcFanMask LITERAL1
+kElectraAcFanMed LITERAL1
kElectraAcHdrMark LITERAL1
kElectraAcHdrSpace LITERAL1
+kElectraAcHeat LITERAL1
+kElectraAcMaxTemp LITERAL1
kElectraAcMessageGap LITERAL1
+kElectraAcMinRepeat LITERAL1
+kElectraAcMinTemp LITERAL1
+kElectraAcModeMask LITERAL1
+kElectraAcOffsetTemp LITERAL1
kElectraAcOneSpace LITERAL1
+kElectraAcPowerMask LITERAL1
kElectraAcStateLength LITERAL1
+kElectraAcSwingHMask LITERAL1
+kElectraAcSwingVMask LITERAL1
+kElectraAcTempMask LITERAL1
kElectraAcZeroSpace LITERAL1
kFan LITERAL1
kFnvBasis32 LITERAL1
@@ -1145,9 +1482,13 @@ kFnvPrime32 LITERAL1
kFooter LITERAL1
kFujitsuAcBitMark LITERAL1
kFujitsuAcBits LITERAL1
+kFujitsuAcCmdEcono LITERAL1
+kFujitsuAcCmdPowerful LITERAL1
kFujitsuAcCmdStayOn LITERAL1
kFujitsuAcCmdStepHoriz LITERAL1
kFujitsuAcCmdStepVert LITERAL1
+kFujitsuAcCmdToggleSwingHoriz LITERAL1
+kFujitsuAcCmdToggleSwingVert LITERAL1
kFujitsuAcCmdTurnOff LITERAL1
kFujitsuAcCmdTurnOn LITERAL1
kFujitsuAcFanAuto LITERAL1
@@ -1191,6 +1532,58 @@ kGlobalCacheMinUsec LITERAL1
kGlobalCacheRptIndex LITERAL1
kGlobalCacheRptStartIndex LITERAL1
kGlobalCacheStartIndex LITERAL1
+kGoodweatherAuto LITERAL1
+kGoodweatherBitCommand LITERAL1
+kGoodweatherBitFan LITERAL1
+kGoodweatherBitLight LITERAL1
+kGoodweatherBitMark LITERAL1
+kGoodweatherBitMode LITERAL1
+kGoodweatherBitPower LITERAL1
+kGoodweatherBitSleep LITERAL1
+kGoodweatherBitSwing LITERAL1
+kGoodweatherBitTemp LITERAL1
+kGoodweatherBitTurbo LITERAL1
+kGoodweatherBits LITERAL1
+kGoodweatherCmdAirFlow LITERAL1
+kGoodweatherCmdDownTemp LITERAL1
+kGoodweatherCmdFan LITERAL1
+kGoodweatherCmdHold LITERAL1
+kGoodweatherCmdLight LITERAL1
+kGoodweatherCmdMode LITERAL1
+kGoodweatherCmdPower LITERAL1
+kGoodweatherCmdSleep LITERAL1
+kGoodweatherCmdSwing LITERAL1
+kGoodweatherCmdTimer LITERAL1
+kGoodweatherCmdTurbo LITERAL1
+kGoodweatherCmdUpTemp LITERAL1
+kGoodweatherCommandMask LITERAL1
+kGoodweatherCool LITERAL1
+kGoodweatherDry LITERAL1
+kGoodweatherFan LITERAL1
+kGoodweatherFanAuto LITERAL1
+kGoodweatherFanHigh LITERAL1
+kGoodweatherFanLow LITERAL1
+kGoodweatherFanMask LITERAL1
+kGoodweatherFanMed LITERAL1
+kGoodweatherHdrMark LITERAL1
+kGoodweatherHdrSpace LITERAL1
+kGoodweatherHeat LITERAL1
+kGoodweatherLightMask LITERAL1
+kGoodweatherMinRepeat LITERAL1
+kGoodweatherModeMask LITERAL1
+kGoodweatherOneSpace LITERAL1
+kGoodweatherPowerMask LITERAL1
+kGoodweatherSleepMask LITERAL1
+kGoodweatherSwingFast LITERAL1
+kGoodweatherSwingMask LITERAL1
+kGoodweatherSwingOff LITERAL1
+kGoodweatherSwingSlow LITERAL1
+kGoodweatherTempMask LITERAL1
+kGoodweatherTempMax LITERAL1
+kGoodweatherTempMin LITERAL1
+kGoodweatherTurboMask LITERAL1
+kGoodweatherZeroSpace LITERAL1
+kGpioUnused LITERAL1
kGreeAuto LITERAL1
kGreeBitMark LITERAL1
kGreeBits LITERAL1
@@ -1203,10 +1596,12 @@ kGreeFan LITERAL1
kGreeFanAuto LITERAL1
kGreeFanMask LITERAL1
kGreeFanMax LITERAL1
+kGreeFanMed LITERAL1
kGreeFanMin LITERAL1
kGreeHdrMark LITERAL1
kGreeHdrSpace LITERAL1
kGreeHeat LITERAL1
+kGreeIFeelMask LITERAL1
kGreeLightMask LITERAL1
kGreeMaxTemp LITERAL1
kGreeMinTemp LITERAL1
@@ -1229,7 +1624,15 @@ kGreeSwingMiddleUp LITERAL1
kGreeSwingPosMask LITERAL1
kGreeSwingUp LITERAL1
kGreeSwingUpAuto LITERAL1
+kGreeTempMask LITERAL1
+kGreeTimer1Mask LITERAL1
+kGreeTimerEnabledBit LITERAL1
+kGreeTimerHalfHrBit LITERAL1
+kGreeTimerHoursMask LITERAL1
+kGreeTimerMax LITERAL1
+kGreeTimerTensHrMask LITERAL1
kGreeTurboMask LITERAL1
+kGreeWiFiMask LITERAL1
kGreeXfanMask LITERAL1
kGreeZeroSpace LITERAL1
kHaierACBits LITERAL1
@@ -1265,8 +1668,10 @@ kHaierAcMaxTemp LITERAL1
kHaierAcMaxTime LITERAL1
kHaierAcMinGap LITERAL1
kHaierAcMinTemp LITERAL1
+kHaierAcModeMask LITERAL1
kHaierAcOneSpace LITERAL1
kHaierAcPrefix LITERAL1
+kHaierAcSleepBit LITERAL1
kHaierAcSwingChg LITERAL1
kHaierAcSwingDown LITERAL1
kHaierAcSwingOff LITERAL1
@@ -1324,6 +1729,7 @@ kHitachiAcFan LITERAL1
kHitachiAcFanAuto LITERAL1
kHitachiAcFanHigh LITERAL1
kHitachiAcFanLow LITERAL1
+kHitachiAcFanMed LITERAL1
kHitachiAcHdrMark LITERAL1
kHitachiAcHdrSpace LITERAL1
kHitachiAcHeat LITERAL1
@@ -1334,6 +1740,15 @@ kHitachiAcOneSpace LITERAL1
kHitachiAcStateLength LITERAL1
kHitachiAcZeroSpace LITERAL1
kIdleState LITERAL1
+kInaxBitMark LITERAL1
+kInaxBits LITERAL1
+kInaxHdrMark LITERAL1
+kInaxHdrSpace LITERAL1
+kInaxMinGap LITERAL1
+kInaxMinRepeat LITERAL1
+kInaxOneSpace LITERAL1
+kInaxTick LITERAL1
+kInaxZeroSpace LITERAL1
kJvcBitMark LITERAL1
kJvcBitMarkTicks LITERAL1
kJvcBits LITERAL1
@@ -1367,6 +1782,7 @@ kKelvinatorFan LITERAL1
kKelvinatorFanAuto LITERAL1
kKelvinatorFanMask LITERAL1
kKelvinatorFanMax LITERAL1
+kKelvinatorFanMin LITERAL1
kKelvinatorFanOffset LITERAL1
kKelvinatorGapSpace LITERAL1
kKelvinatorGapSpaceTicks LITERAL1
@@ -1409,6 +1825,10 @@ kLasertagMinSamples LITERAL1
kLasertagTick LITERAL1
kLasertagTolerance LITERAL1
kLastDecodeType LITERAL1
+kLastFanspeedEnum LITERAL1
+kLastOpmodeEnum LITERAL1
+kLastSwinghEnum LITERAL1
+kLastSwingvEnum LITERAL1
kLeft LITERAL1
kLeftMax LITERAL1
kLegoPfBitMark LITERAL1
@@ -1480,6 +1900,7 @@ kMaxTimeoutMs LITERAL1
kMedium LITERAL1
kMiddle LITERAL1
kMideaACAuto LITERAL1
+kMideaACCelsiusBit LITERAL1
kMideaACChecksumMask LITERAL1
kMideaACCool LITERAL1
kMideaACDry LITERAL1
@@ -1499,6 +1920,7 @@ kMideaACPower LITERAL1
kMideaACSleep LITERAL1
kMideaACStateMask LITERAL1
kMideaACTempMask LITERAL1
+kMideaACToggleSwingV LITERAL1
kMideaBitMark LITERAL1
kMideaBitMarkTicks LITERAL1
kMideaBits LITERAL1
@@ -1531,6 +1953,7 @@ kMitsubishiAcCool LITERAL1
kMitsubishiAcDry LITERAL1
kMitsubishiAcFanAuto LITERAL1
kMitsubishiAcFanMax LITERAL1
+kMitsubishiAcFanQuiet LITERAL1
kMitsubishiAcFanRealMax LITERAL1
kMitsubishiAcFanSilent LITERAL1
kMitsubishiAcHdrMark LITERAL1
@@ -1548,6 +1971,7 @@ kMitsubishiAcStartTimer LITERAL1
kMitsubishiAcStopTimer LITERAL1
kMitsubishiAcVaneAuto LITERAL1
kMitsubishiAcVaneAutoMove LITERAL1
+kMitsubishiAcWideVaneAuto LITERAL1
kMitsubishiAcZeroSpace LITERAL1
kMitsubishiBitMark LITERAL1
kMitsubishiBitMarkTicks LITERAL1
@@ -1666,6 +2090,60 @@ kNecRptSpaceTicks LITERAL1
kNecTick LITERAL1
kNecZeroSpace LITERAL1
kNecZeroSpaceTicks LITERAL1
+kNeoclima8CHeatMask LITERAL1
+kNeoclimaAuto LITERAL1
+kNeoclimaBitMark LITERAL1
+kNeoclimaBits LITERAL1
+kNeoclimaButton8CHeat LITERAL1
+kNeoclimaButtonAirFlow LITERAL1
+kNeoclimaButtonEye LITERAL1
+kNeoclimaButtonFanSpeed LITERAL1
+kNeoclimaButtonFollow LITERAL1
+kNeoclimaButtonFresh LITERAL1
+kNeoclimaButtonHold LITERAL1
+kNeoclimaButtonIon LITERAL1
+kNeoclimaButtonLight LITERAL1
+kNeoclimaButtonMask LITERAL1
+kNeoclimaButtonMode LITERAL1
+kNeoclimaButtonPower LITERAL1
+kNeoclimaButtonSleep LITERAL1
+kNeoclimaButtonSwing LITERAL1
+kNeoclimaButtonTempDown LITERAL1
+kNeoclimaButtonTempUp LITERAL1
+kNeoclimaButtonTurbo LITERAL1
+kNeoclimaCool LITERAL1
+kNeoclimaDry LITERAL1
+kNeoclimaEyeMask LITERAL1
+kNeoclimaFan LITERAL1
+kNeoclimaFanAuto LITERAL1
+kNeoclimaFanHigh LITERAL1
+kNeoclimaFanLow LITERAL1
+kNeoclimaFanMask LITERAL1
+kNeoclimaFanMed LITERAL1
+kNeoclimaFollowMe LITERAL1
+kNeoclimaFreshMask LITERAL1
+kNeoclimaHdrMark LITERAL1
+kNeoclimaHdrSpace LITERAL1
+kNeoclimaHeat LITERAL1
+kNeoclimaHoldMask LITERAL1
+kNeoclimaIonMask LITERAL1
+kNeoclimaLightMask LITERAL1
+kNeoclimaMaxTemp LITERAL1
+kNeoclimaMinGap LITERAL1
+kNeoclimaMinRepeat LITERAL1
+kNeoclimaMinTemp LITERAL1
+kNeoclimaModeMask LITERAL1
+kNeoclimaOneSpace LITERAL1
+kNeoclimaPowerMask LITERAL1
+kNeoclimaSleepMask LITERAL1
+kNeoclimaStateLength LITERAL1
+kNeoclimaSwingHMask LITERAL1
+kNeoclimaSwingVMask LITERAL1
+kNeoclimaSwingVOff LITERAL1
+kNeoclimaSwingVOn LITERAL1
+kNeoclimaTempMask LITERAL1
+kNeoclimaTurboMask LITERAL1
+kNeoclimaZeroSpace LITERAL1
kNikaiBitMark LITERAL1
kNikaiBitMarkTicks LITERAL1
kNikaiBits LITERAL1
@@ -1692,6 +2170,7 @@ kPanasonicAcExcess LITERAL1
kPanasonicAcFan LITERAL1
kPanasonicAcFanAuto LITERAL1
kPanasonicAcFanMax LITERAL1
+kPanasonicAcFanMed LITERAL1
kPanasonicAcFanMin LITERAL1
kPanasonicAcFanModeTemp LITERAL1
kPanasonicAcFanOffset LITERAL1
@@ -1751,7 +2230,22 @@ kPanasonicUnknown LITERAL1
kPanasonicZeroSpace LITERAL1
kPanasonicZeroSpaceTicks LITERAL1
kPeriodOffset LITERAL1
+kPioneerBitMark LITERAL1
+kPioneerBitMarkTicks LITERAL1
kPioneerBits LITERAL1
+kPioneerHdrMark LITERAL1
+kPioneerHdrMarkTicks LITERAL1
+kPioneerHdrSpace LITERAL1
+kPioneerHdrSpaceTicks LITERAL1
+kPioneerMinCommandLength LITERAL1
+kPioneerMinCommandLengthTicks LITERAL1
+kPioneerMinGap LITERAL1
+kPioneerMinGapTicks LITERAL1
+kPioneerOneSpace LITERAL1
+kPioneerOneSpaceTicks LITERAL1
+kPioneerTick LITERAL1
+kPioneerZeroSpace LITERAL1
+kPioneerZeroSpaceTicks LITERAL1
kProntoDataOffset LITERAL1
kProntoFreqFactor LITERAL1
kProntoFreqOffset LITERAL1
@@ -1835,9 +2329,12 @@ kSamsungAcMinTemp LITERAL1
kSamsungAcModeMask LITERAL1
kSamsungAcOneSpace LITERAL1
kSamsungAcPowerMask1 LITERAL1
-kSamsungAcPowerMask2 LITERAL1
+kSamsungAcPowerMask6 LITERAL1
kSamsungAcPowerSection LITERAL1
-kSamsungAcQuietMask11 LITERAL1
+kSamsungAcPowerfulMask10 LITERAL1
+kSamsungAcPowerfulMask8 LITERAL1
+kSamsungAcQuietMask1 LITERAL1
+kSamsungAcQuietMask5 LITERAL1
kSamsungAcSectionGap LITERAL1
kSamsungAcSectionMark LITERAL1
kSamsungAcSectionSpace LITERAL1
@@ -1885,6 +2382,37 @@ kSanyoSa8650bHdrSpace LITERAL1
kSanyoSa8650bOneMark LITERAL1
kSanyoSa8650bRptLength LITERAL1
kSanyoSa8650bZeroMark LITERAL1
+kSharpAcAuto LITERAL1
+kSharpAcBitFanManual LITERAL1
+kSharpAcBitMark LITERAL1
+kSharpAcBitPower LITERAL1
+kSharpAcBitTempManual LITERAL1
+kSharpAcBits LITERAL1
+kSharpAcByteFan LITERAL1
+kSharpAcByteManual LITERAL1
+kSharpAcByteMode LITERAL1
+kSharpAcBytePower LITERAL1
+kSharpAcByteTemp LITERAL1
+kSharpAcCool LITERAL1
+kSharpAcDefaultRepeat LITERAL1
+kSharpAcDry LITERAL1
+kSharpAcFanAuto LITERAL1
+kSharpAcFanHigh LITERAL1
+kSharpAcFanMax LITERAL1
+kSharpAcFanMed LITERAL1
+kSharpAcFanMin LITERAL1
+kSharpAcGap LITERAL1
+kSharpAcHdrMark LITERAL1
+kSharpAcHdrSpace LITERAL1
+kSharpAcHeat LITERAL1
+kSharpAcMaskFan LITERAL1
+kSharpAcMaskMode LITERAL1
+kSharpAcMaskTemp LITERAL1
+kSharpAcMaxTemp LITERAL1
+kSharpAcMinTemp LITERAL1
+kSharpAcOneSpace LITERAL1
+kSharpAcStateLength LITERAL1
+kSharpAcZeroSpace LITERAL1
kSharpAddressBits LITERAL1
kSharpAddressMask LITERAL1
kSharpBitMark LITERAL1
@@ -1954,6 +2482,7 @@ kTcl112AcPowerMask LITERAL1
kTcl112AcStateLength LITERAL1
kTcl112AcTempMax LITERAL1
kTcl112AcTempMin LITERAL1
+kTcl112AcTolerance LITERAL1
kTcl112AcZeroSpace LITERAL1
kTecoAuto LITERAL1
kTecoBitMark LITERAL1
@@ -1971,12 +2500,15 @@ kTecoGap LITERAL1
kTecoHdrMark LITERAL1
kTecoHdrSpace LITERAL1
kTecoHeat LITERAL1
+kTecoHumid LITERAL1
+kTecoLight LITERAL1
kTecoMaxTemp LITERAL1
kTecoMinTemp LITERAL1
kTecoModeMask LITERAL1
kTecoOneSpace LITERAL1
kTecoPower LITERAL1
kTecoReset LITERAL1
+kTecoSave LITERAL1
kTecoSleep LITERAL1
kTecoSwing LITERAL1
kTecoTempMask LITERAL1
@@ -1996,6 +2528,8 @@ kToshibaAcCool LITERAL1
kToshibaAcDry LITERAL1
kToshibaAcFanAuto LITERAL1
kToshibaAcFanMax LITERAL1
+kToshibaAcFanMed LITERAL1
+kToshibaAcFanMin LITERAL1
kToshibaAcHdrMark LITERAL1
kToshibaAcHdrSpace LITERAL1
kToshibaAcHeat LITERAL1
@@ -2006,6 +2540,8 @@ kToshibaAcOneSpace LITERAL1
kToshibaAcPower LITERAL1
kToshibaAcZeroSpace LITERAL1
kTrotecAuto LITERAL1
+kTrotecBitMark LITERAL1
+kTrotecBits LITERAL1
kTrotecCool LITERAL1
kTrotecDefTemp LITERAL1
kTrotecDefaultRepeat LITERAL1
@@ -2023,15 +2559,14 @@ kTrotecIntro2 LITERAL1
kTrotecMaxTemp LITERAL1
kTrotecMaxTimer LITERAL1
kTrotecMinTemp LITERAL1
-kTrotecOneMark LITERAL1
kTrotecOneSpace LITERAL1
kTrotecPowerBit LITERAL1
kTrotecSleepBit LITERAL1
kTrotecStateLength LITERAL1
kTrotecTimerBit LITERAL1
-kTrotecZeroMark LITERAL1
kTrotecZeroSpace LITERAL1
kUnknownThreshold LITERAL1
+kUseDefTol LITERAL1
kVestelAcAuto LITERAL1
kVestelAcBitMark LITERAL1
kVestelAcBits LITERAL1
@@ -2153,3 +2688,4 @@ kWhynterOneSpaceTicks LITERAL1
kWhynterTick LITERAL1
kWhynterZeroSpace LITERAL1
kWhynterZeroSpaceTicks LITERAL1
+kWide LITERAL1
diff --git a/lib/IRremoteESP8266-2.6.0/library.json b/lib/IRremoteESP8266-2.6.5/library.json
similarity index 79%
rename from lib/IRremoteESP8266-2.6.0/library.json
rename to lib/IRremoteESP8266-2.6.5/library.json
index 95867de1d..c5136f18e 100644
--- a/lib/IRremoteESP8266-2.6.0/library.json
+++ b/lib/IRremoteESP8266-2.6.5/library.json
@@ -1,17 +1,18 @@
{
"name": "IRremoteESP8266",
- "version": "2.6.0",
- "keywords": "infrared, ir, remote, esp8266",
- "description": "Send and receive infrared signals with multiple protocols (ESP8266)",
+ "version": "2.6.5",
+ "keywords": "infrared, ir, remote, esp8266, esp32",
+ "description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)",
"repository":
{
"type": "git",
- "url": "https://github.com/markszabo/IRremoteESP8266.git"
+ "url": "https://github.com/crankyoldgit/IRremoteESP8266.git"
},
"authors": [
{
- "name": "Ken Shirriff",
- "email": "zetoslab@gmail.com"
+ "name": "David Conran",
+ "url": "https://plus.google.com/+davidconran",
+ "maintainer": true
},
{
"name": "Mark Szabo",
@@ -24,9 +25,8 @@
"maintainer": true
},
{
- "name": "David Conran",
- "url": "https://plus.google.com/+davidconran",
- "maintainer": true
+ "name": "Ken Shirriff",
+ "email": "zetoslab@gmail.com"
},
{
"name": "Roi Dayan",
@@ -40,5 +40,5 @@
}
],
"frameworks": "arduino",
- "platforms": "espressif8266"
+ "platforms": ["espressif8266", "espressif32"]
}
diff --git a/lib/IRremoteESP8266-2.6.0/library.properties b/lib/IRremoteESP8266-2.6.5/library.properties
similarity index 54%
rename from lib/IRremoteESP8266-2.6.0/library.properties
rename to lib/IRremoteESP8266-2.6.5/library.properties
index f122067c5..f83a80428 100644
--- a/lib/IRremoteESP8266-2.6.0/library.properties
+++ b/lib/IRremoteESP8266-2.6.5/library.properties
@@ -1,9 +1,9 @@
name=IRremoteESP8266
-version=2.6.0
-author=Sebastien Warin, Mark Szabo, Ken Shirriff, David Conran
+version=2.6.5
+author=David Conran, Sebastien Warin, Mark Szabo, Ken Shirriff
maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto
-sentence=Send and receive infrared signals with multiple protocols (ESP8266)
-paragraph=This library enables you to send and receive infra-red signals on an ESP8266.
+sentence=Send and receive infrared signals with multiple protocols (ESP8266/ESP32)
+paragraph=This library enables you to send and receive infra-red signals on an ESP8266 or an ESP32.
category=Device Control
-url=https://github.com/markszabo/IRremoteESP8266
-architectures=esp8266
+url=https://github.com/crankyoldgit/IRremoteESP8266
+architectures=esp8266,esp32
diff --git a/lib/IRremoteESP8266-2.6.0/pylintrc b/lib/IRremoteESP8266-2.6.5/pylintrc
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/pylintrc
rename to lib/IRremoteESP8266-2.6.5/pylintrc
diff --git a/lib/IRremoteESP8266-2.6.0/src/CPPLINT.cfg b/lib/IRremoteESP8266-2.6.5/src/CPPLINT.cfg
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/src/CPPLINT.cfg
rename to lib/IRremoteESP8266-2.6.5/src/CPPLINT.cfg
diff --git a/lib/IRremoteESP8266-2.6.5/src/IRac.cpp b/lib/IRremoteESP8266-2.6.5/src/IRac.cpp
new file mode 100644
index 000000000..df668d836
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/IRac.cpp
@@ -0,0 +1,2084 @@
+// Copyright 2019 David Conran
+
+// Provide a universal/standard interface for sending A/C nessages.
+// It does not provide complete and maximum granular control but tries
+// to off most common functionallity across all supported devices.
+
+#include "IRac.h"
+#ifndef UNIT_TEST
+#include
+#endif
+#include
+#ifndef ARDUINO
+#include
+#endif
+#include "IRsend.h"
+#include "IRremoteESP8266.h"
+#include "IRutils.h"
+#include "ir_Amcor.h"
+#include "ir_Argo.h"
+#include "ir_Coolix.h"
+#include "ir_Daikin.h"
+#include "ir_Electra.h"
+#include "ir_Fujitsu.h"
+#include "ir_Haier.h"
+#include "ir_Hitachi.h"
+#include "ir_Kelvinator.h"
+#include "ir_Midea.h"
+#include "ir_Mitsubishi.h"
+#include "ir_MitsubishiHeavy.h"
+#include "ir_Neoclima.h"
+#include "ir_Panasonic.h"
+#include "ir_Samsung.h"
+#include "ir_Sharp.h"
+#include "ir_Tcl.h"
+#include "ir_Teco.h"
+#include "ir_Toshiba.h"
+#include "ir_Trotec.h"
+#include "ir_Vestel.h"
+#include "ir_Whirlpool.h"
+
+IRac::IRac(const uint16_t pin, const bool inverted, const bool use_modulation) {
+ _pin = pin;
+ _inverted = inverted;
+ _modulation = use_modulation;
+}
+
+// Is the given protocol supported by the IRac class?
+bool IRac::isProtocolSupported(const decode_type_t protocol) {
+ switch (protocol) {
+#if SEND_AMCOR
+ case decode_type_t::AMCOR:
+#endif
+#if SEND_AMCOR
+ case decode_type_t::ARGO:
+#endif
+#if SEND_COOLIX
+ case decode_type_t::COOLIX:
+#endif
+#if SEND_DAIKIN
+ case decode_type_t::DAIKIN:
+#endif
+#if SEND_DAIKIN128
+ case decode_type_t::DAIKIN128:
+#endif
+#if SEND_DAIKIN160
+ case decode_type_t::DAIKIN160:
+#endif
+#if SEND_DAIKIN176
+ case decode_type_t::DAIKIN176:
+#endif
+#if SEND_DAIKIN2
+ case decode_type_t::DAIKIN2:
+#endif
+#if SEND_DAIKIN216
+ case decode_type_t::DAIKIN216:
+#endif
+#if SEND_ELECTRA_AC
+ case decode_type_t::ELECTRA_AC:
+#endif
+#if SEND_FUJITSU_AC
+ case decode_type_t::FUJITSU_AC:
+#endif
+#if SEND_GOODWEATHER
+ case decode_type_t::GOODWEATHER:
+#endif
+#if SEND_GREE
+ case decode_type_t::GREE:
+#endif
+#if SEND_HAIER_AC
+ case decode_type_t::HAIER_AC:
+#endif
+#if SEND_HAIER_AC_YRW02
+ case decode_type_t::HAIER_AC_YRW02:
+#endif
+#if SEND_HITACHI_AC
+ case decode_type_t::HITACHI_AC:
+#endif
+#if SEND_KELVINATOR
+ case decode_type_t::KELVINATOR:
+#endif
+#if SEND_MIDEA
+ case decode_type_t::MIDEA:
+#endif
+#if SEND_MITSUBISHI_AC
+ case decode_type_t::MITSUBISHI_AC:
+#endif
+#if SEND_MITSUBISHIHEAVY
+ case decode_type_t::MITSUBISHI_HEAVY_88:
+ case decode_type_t::MITSUBISHI_HEAVY_152:
+#endif
+#if SEND_NEOCLIMA
+ case decode_type_t::NEOCLIMA:
+#endif
+#if SEND_PANASONIC_AC
+ case decode_type_t::PANASONIC_AC:
+#endif
+#if SEND_SAMSUNG_AC
+ case decode_type_t::SAMSUNG_AC:
+#endif
+#if SEND_SHARP_AC
+ case decode_type_t::SHARP_AC:
+#endif
+#if SEND_TCL112AC
+ case decode_type_t::TCL112AC:
+#endif
+#if SEND_TECO
+ case decode_type_t::TECO:
+#endif
+#if SEND_TOSHIBA_AC
+ case decode_type_t::TOSHIBA_AC:
+#endif
+#if SEND_TROTEC
+ case decode_type_t::TROTEC:
+#endif
+#if SEND_VESTEL_AC
+ case decode_type_t::VESTEL_AC:
+#endif
+#if SEND_WHIRLPOOL_AC
+ case decode_type_t::WHIRLPOOL_AC:
+#endif
+ return true;
+ default:
+ return false;
+ }
+}
+
+#if SEND_AMCOR
+void IRac::amcor(IRAmcorAc *ac,
+ const bool on, const stdAc::opmode_t mode, const float degrees,
+ const stdAc::fanspeed_t fan) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ // No Swing setting available.
+ // No Quiet setting available.
+ // No Light setting available.
+ // No Filter setting available.
+ // No Turbo setting available.
+ // No Economy setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ // No Sleep setting available.
+ ac->send();
+}
+#endif // SEND_AMCOR
+
+#if SEND_ARGO
+void IRac::argo(IRArgoAC *ac,
+ const bool on, const stdAc::opmode_t mode, const float degrees,
+ const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
+ const bool turbo, const int16_t sleep) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setFlap(ac->convertSwingV(swingv));
+ // No Quiet setting available.
+ // No Light setting available.
+ // No Filter setting available.
+ ac->setMax(turbo);
+ // No Economy setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setNight(sleep >= 0); // Convert to a boolean.
+ ac->send();
+}
+#endif // SEND_ARGO
+
+#if SEND_COOLIX
+void IRac::coolix(IRCoolixAC *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool turbo, const bool light, const bool clean,
+ const int16_t sleep) {
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ // No Filter setting available.
+ // No Beep setting available.
+ // No Clock setting available.
+ // No Econo setting available.
+ // No Quiet setting available.
+ if (swingv != stdAc::swingv_t::kOff || swingh != stdAc::swingh_t::kOff) {
+ // Swing has a special command that needs to be sent independently.
+ ac->setSwing();
+ ac->send();
+ }
+ if (turbo) {
+ // Turbo has a special command that needs to be sent independently.
+ ac->setTurbo();
+ ac->send();
+ }
+ if (sleep > 0) {
+ // Sleep has a special command that needs to be sent independently.
+ ac->setSleep();
+ ac->send();
+ }
+ if (light) {
+ // Light has a special command that needs to be sent independently.
+ ac->setLed();
+ ac->send();
+ }
+ if (clean) {
+ // Clean has a special command that needs to be sent independently.
+ ac->setClean();
+ ac->send();
+ }
+ // Power gets done last, as off has a special command.
+ ac->setPower(on);
+ ac->send();
+}
+#endif // SEND_COOLIX
+
+#if SEND_DAIKIN
+void IRac::daikin(IRDaikinESP *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool quiet, const bool turbo, const bool econo,
+ const bool clean) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical((int8_t)swingv >= 0);
+ ac->setSwingHorizontal((int8_t)swingh >= 0);
+ ac->setQuiet(quiet);
+ // No Light setting available.
+ // No Filter setting available.
+ ac->setPowerful(turbo);
+ ac->setEcono(econo);
+ ac->setMold(clean);
+ // No Beep setting available.
+ // No Sleep setting available.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_DAIKIN
+
+#if SEND_DAIKIN128
+void IRac::daikin128(IRDaikin128 *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv,
+ const bool quiet, const bool turbo, const bool light,
+ const bool econo, const int16_t sleep, const int16_t clock) {
+ ac->setPowerToggle(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical((int8_t)swingv >= 0);
+ // No Horizontal Swing setting avaliable.
+ ac->setQuiet(quiet);
+ ac->setLightToggle(light ? kDaikin128BitWall : 0);
+ // No Filter setting available.
+ ac->setPowerful(turbo);
+ ac->setEcono(econo);
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setSleep(sleep > 0);
+ if (clock >= 0) ac->setClock(clock);
+ ac->send();
+}
+#endif // SEND_DAIKIN128
+
+#if SEND_DAIKIN160
+void IRac::daikin160(IRDaikin160 *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical(ac->convertSwingV(swingv));
+ ac->send();
+}
+#endif // SEND_DAIKIN160
+
+#if SEND_DAIKIN176
+void IRac::daikin176(IRDaikin176 *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingh_t swingh) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingHorizontal(ac->convertSwingH(swingh));
+ ac->send();
+}
+#endif // SEND_DAIKIN176
+
+#if SEND_DAIKIN2
+void IRac::daikin2(IRDaikin2 *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool quiet, const bool turbo, const bool light,
+ const bool econo, const bool filter, const bool clean,
+ const bool beep, const int16_t sleep, const int16_t clock) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical(ac->convertSwingV(swingv));
+ ac->setSwingHorizontal((int8_t)swingh >= 0);
+ ac->setQuiet(quiet);
+ ac->setLight(light);
+ ac->setPowerful(turbo);
+ ac->setEcono(econo);
+ ac->setPurify(filter);
+ ac->setMold(clean);
+ ac->setBeep(beep);
+ if (sleep > 0) ac->enableSleepTimer(sleep);
+ if (clock >= 0) ac->setCurrentTime(clock);
+ ac->send();
+}
+#endif // SEND_DAIKIN2
+
+#if SEND_DAIKIN216
+void IRac::daikin216(IRDaikin216 *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool quiet, const bool turbo) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical((int8_t)swingv >= 0);
+ ac->setSwingHorizontal((int8_t)swingh >= 0);
+ ac->setQuiet(quiet);
+ ac->setPowerful(turbo);
+ ac->send();
+}
+#endif // SEND_DAIKIN216
+
+#if SEND_ELECTRA_AC
+void IRac::electra(IRElectraAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv,
+ const stdAc::swingh_t swingh) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingV(swingv != stdAc::swingv_t::kOff);
+ ac->setSwingH(swingh != stdAc::swingh_t::kOff);
+ // No Quiet setting available.
+ // No Turbo setting available.
+ // No Light setting available.
+ // No Econo setting available.
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ // No Sleep setting available.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_ELECTRA_AC
+
+#if SEND_FUJITSU_AC
+void IRac::fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool quiet, const bool turbo, const bool econo) {
+ ac->setModel(model);
+ if (on) {
+ // Do all special messages (except "Off") first,
+ // These need to be sent separately.
+ switch (ac->getModel()) {
+ // Some functions are only available on some models.
+ case fujitsu_ac_remote_model_t::ARREB1E:
+ if (turbo) {
+ ac->setCmd(kFujitsuAcCmdPowerful);
+ // Powerful is a separate command.
+ ac->send();
+ }
+ if (econo) {
+ ac->setCmd(kFujitsuAcCmdEcono);
+ // Econo is a separate command.
+ ac->send();
+ }
+ break;
+ default:
+ {};
+ }
+ // Normal operation.
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFanSpeed(ac->convertFan(fan));
+ uint8_t swing = kFujitsuAcSwingOff;
+ if (swingv > stdAc::swingv_t::kOff) swing |= kFujitsuAcSwingVert;
+ if (swingh > stdAc::swingh_t::kOff) swing |= kFujitsuAcSwingHoriz;
+ ac->setSwing(swing);
+ if (quiet) ac->setFanSpeed(kFujitsuAcFanQuiet);
+ // No Light setting available.
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ // No Sleep setting available.
+ // No Clock setting available.
+ ac->on(); // Ref: Issue #860
+ } else {
+ // Off is special case/message. We don't need to send other messages.
+ ac->off();
+ }
+ ac->send();
+}
+#endif // SEND_FUJITSU_AC
+
+#if SEND_GOODWEATHER
+void IRac::goodweather(IRGoodweatherAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees,
+ const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv,
+ const bool turbo, const bool light,
+ const int16_t sleep) {
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwing(swingv == stdAc::swingv_t::kOff ? kGoodweatherSwingOff
+ : kGoodweatherSwingSlow);
+ ac->setTurbo(turbo);
+ ac->setLight(light);
+ // No Clean setting available.
+ ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
+ // No Horizontal Swing setting available.
+ // No Econo setting available.
+ // No Filter setting available.
+ // No Beep setting available.
+ // No Quiet setting available.
+ // No Clock setting available.
+ ac->setPower(on);
+ ac->send();
+}
+#endif // SEND_GOODWEATHER
+
+#if SEND_GREE
+void IRac::gree(IRGreeAC *ac, const gree_ac_remote_model_t model,
+ const bool on, const stdAc::opmode_t mode, const float degrees,
+ const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
+ const bool turbo, const bool light, const bool clean,
+ const int16_t sleep) {
+ ac->setModel(model);
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical(swingv == stdAc::swingv_t::kAuto, // Set auto flag.
+ ac->convertSwingV(swingv));
+ ac->setLight(light);
+ ac->setTurbo(turbo);
+ ac->setXFan(clean);
+ ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
+ // No Horizontal Swing setting available.
+ // No Econo setting available.
+ // No Filter setting available.
+ // No Beep setting available.
+ // No Quiet setting available.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_GREE
+
+#if SEND_HAIER_AC
+void IRac::haier(IRHaierAC *ac,
+ const bool on, const stdAc::opmode_t mode, const float degrees,
+ const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
+ const bool filter, const int16_t sleep, const int16_t clock) {
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwing(ac->convertSwingV(swingv));
+ // No Horizontal Swing setting available.
+ // No Quiet setting available.
+ // No Turbo setting available.
+ // No Light setting available.
+ ac->setHealth(filter);
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
+ if (clock >=0) ac->setCurrTime(clock);
+ if (on)
+ ac->setCommand(kHaierAcCmdOn);
+ else
+ ac->setCommand(kHaierAcCmdOff);
+ ac->send();
+}
+#endif // SEND_HAIER_AC
+
+#if SEND_HAIER_AC_YRW02
+void IRac::haierYrwo2(IRHaierACYRW02 *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const bool turbo,
+ const bool filter, const int16_t sleep) {
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwing(ac->convertSwingV(swingv));
+ // No Horizontal Swing setting available.
+ // No Quiet setting available.
+ ac->setTurbo(turbo);
+ // No Light setting available.
+ ac->setHealth(filter);
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
+ ac->setPower(on);
+ ac->send();
+}
+#endif // SEND_HAIER_AC_YRW02
+
+#if SEND_HITACHI_AC
+void IRac::hitachi(IRHitachiAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical(swingv != stdAc::swingv_t::kOff);
+ ac->setSwingHorizontal(swingh != stdAc::swingh_t::kOff);
+ // No Quiet setting available.
+ // No Turbo setting available.
+ // No Light setting available.
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ // No Sleep setting available.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_HITACHI_AC
+
+#if SEND_KELVINATOR
+void IRac::kelvinator(IRKelvinatorAC *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv,
+ const stdAc::swingh_t swingh,
+ const bool quiet, const bool turbo, const bool light,
+ const bool filter, const bool clean) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan((uint8_t)fan); // No conversion needed.
+ ac->setSwingVertical((int8_t)swingv >= 0);
+ ac->setSwingHorizontal((int8_t)swingh >= 0);
+ ac->setQuiet(quiet);
+ ac->setTurbo(turbo);
+ ac->setLight(light);
+ ac->setIonFilter(filter);
+ ac->setXFan(clean);
+ // No Beep setting available.
+ // No Sleep setting available.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_KELVINATOR
+
+#if SEND_MIDEA
+void IRac::midea(IRMideaAC *ac,
+ const bool on, const stdAc::opmode_t mode, const bool celsius,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const int16_t sleep) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setUseCelsius(celsius);
+ ac->setTemp(degrees, celsius);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVToggle(swingv != stdAc::swingv_t::kOff);
+ // No Horizontal swing setting available.
+ // No Quiet setting available.
+ // No Turbo setting available.
+ // No Light setting available.
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_MIDEA
+
+#if SEND_MITSUBISHI_AC
+void IRac::mitsubishi(IRMitsubishiAC *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees,
+ const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
+ const stdAc::swingh_t swingh,
+ const bool quiet, const int16_t clock) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setVane(ac->convertSwingV(swingv));
+ ac->setWideVane(ac->convertSwingH(swingh));
+ if (quiet) ac->setFan(kMitsubishiAcFanSilent);
+ // No Turbo setting available.
+ // No Light setting available.
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ // No Sleep setting available.
+ if (clock >= 0) ac->setClock(clock / 10); // Clock is in 10 min increments.
+ ac->send();
+}
+#endif // SEND_MITSUBISHI_AC
+
+#if SEND_MITSUBISHIHEAVY
+void IRac::mitsubishiHeavy88(IRMitsubishiHeavy88Ac *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees,
+ const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv,
+ const stdAc::swingh_t swingh,
+ const bool turbo, const bool econo,
+ const bool clean) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical(ac->convertSwingV(swingv));
+ ac->setSwingHorizontal(ac->convertSwingH(swingh));
+ // No Quiet setting available.
+ ac->setTurbo(turbo);
+ // No Light setting available.
+ ac->setEcono(econo);
+ // No Filter setting available.
+ ac->setClean(clean);
+ // No Beep setting available.
+ // No Sleep setting available.
+ // No Clock setting available.
+ ac->send();
+}
+
+void IRac::mitsubishiHeavy152(IRMitsubishiHeavy152Ac *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees,
+ const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv,
+ const stdAc::swingh_t swingh,
+ const bool quiet, const bool turbo,
+ const bool econo, const bool filter,
+ const bool clean, const int16_t sleep) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical(ac->convertSwingV(swingv));
+ ac->setSwingHorizontal(ac->convertSwingH(swingh));
+ ac->setSilent(quiet);
+ ac->setTurbo(turbo);
+ // No Light setting available.
+ ac->setEcono(econo);
+ ac->setClean(clean);
+ ac->setFilter(filter);
+ // No Beep setting available.
+ ac->setNight(sleep >= 0); // Sleep is either on/off, so convert to boolean.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_MITSUBISHIHEAVY
+
+#if SEND_NEOCLIMA
+void IRac::neoclima(IRNeoclimaAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool turbo, const bool light, const bool filter,
+ const int16_t sleep) {
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingV(swingv != stdAc::swingv_t::kOff);
+ ac->setSwingH(swingh != stdAc::swingh_t::kOff);
+ // No Quiet setting available.
+ ac->setTurbo(turbo);
+ ac->setLight(light);
+ // No Econo setting available.
+ ac->setIon(filter);
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
+ // No Clock setting available.
+ ac->setPower(on);
+ ac->send();
+}
+#endif // SEND_NEOCLIMA
+
+#if SEND_PANASONIC_AC
+void IRac::panasonic(IRPanasonicAc *ac, const panasonic_ac_remote_model_t model,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool quiet, const bool turbo, const int16_t clock) {
+ ac->setModel(model);
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical(ac->convertSwingV(swingv));
+ ac->setSwingHorizontal(ac->convertSwingH(swingh));
+ ac->setQuiet(quiet);
+ ac->setPowerful(turbo);
+ // No Light setting available.
+ // No Econo setting available.
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ // No Sleep setting available.
+ if (clock >= 0) ac->setClock(clock);
+ ac->send();
+}
+#endif // SEND_PANASONIC_AC
+
+#if SEND_SAMSUNG_AC
+void IRac::samsung(IRSamsungAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees,
+ const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
+ const bool quiet, const bool turbo, const bool clean,
+ const bool beep, const bool dopower) {
+ // dopower is for unit testing only. It should only ever be false in tests.
+ if (dopower) ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwing(swingv != stdAc::swingv_t::kOff);
+ // No Horizontal swing setting available.
+ ac->setQuiet(quiet);
+ ac->setPowerful(turbo);
+ // No Light setting available.
+ // No Econo setting available.
+ // No Filter setting available.
+ ac->setClean(clean);
+ ac->setBeep(beep);
+ // No Sleep setting available.
+ // No Clock setting available.
+ // Do setMode() again as it can affect fan speed.
+ ac->setMode(ac->convertMode(mode));
+ ac->send();
+}
+#endif // SEND_SAMSUNG_AC
+
+#if SEND_SHARP_AC
+void IRac::sharp(IRSharpAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ // No Vertical swing setting available.
+ // No Horizontal swing setting available.
+ // No Quiet setting available.
+ // No Turbo setting available.
+ // No Light setting available.
+ // No Econo setting available.
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ // No Sleep setting available.
+ // No Clock setting available.
+ // Do setMode() again as it can affect fan speed and temp.
+ ac->setMode(ac->convertMode(mode));
+ ac->send();
+}
+#endif // SEND_SHARP_AC
+
+#if SEND_TCL112AC
+void IRac::tcl112(IRTcl112Ac *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool turbo, const bool light, const bool econo,
+ const bool filter) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwingVertical(swingv != stdAc::swingv_t::kOff);
+ ac->setSwingHorizontal(swingh != stdAc::swingh_t::kOff);
+ // No Quiet setting available.
+ ac->setTurbo(turbo);
+ ac->setLight(light);
+ ac->setEcono(econo);
+ ac->setHealth(filter);
+ // No Clean setting available.
+ // No Beep setting available.
+ // No Sleep setting available.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_TCL112AC
+
+#if SEND_TECO
+void IRac::teco(IRTecoAc *ac,
+ const bool on, const stdAc::opmode_t mode, const float degrees,
+ const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
+ const bool light, const int16_t sleep) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwing(swingv != stdAc::swingv_t::kOff);
+ // No Horizontal swing setting available.
+ // No Quiet setting available.
+ // No Turbo setting available.
+ ac->setLight(light);
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_TECO
+
+#if SEND_TOSHIBA_AC
+void IRac::toshiba(IRToshibaAC *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ // No Vertical swing setting available.
+ // No Horizontal swing setting available.
+ // No Quiet setting available.
+ // No Turbo setting available.
+ // No Light setting available.
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ // No Sleep setting available.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_TOSHIBA_AC
+
+#if SEND_TROTEC
+void IRac::trotec(IRTrotecESP *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const int16_t sleep) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setSpeed(ac->convertFan(fan));
+ // No Vertical swing setting available.
+ // No Horizontal swing setting available.
+ // No Quiet setting available.
+ // No Turbo setting available.
+ // No Light setting available.
+ // No Filter setting available.
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
+ // No Clock setting available.
+ ac->send();
+}
+#endif // SEND_TROTEC
+
+#if SEND_VESTEL_AC
+void IRac::vestel(IRVestelAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees,
+ const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
+ const bool turbo, const bool filter, const int16_t sleep,
+ const int16_t clock, const bool sendNormal) {
+ ac->setPower(on);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwing(swingv != stdAc::swingv_t::kOff);
+ // No Horizontal swing setting available.
+ // No Quiet setting available.
+ ac->setTurbo(turbo);
+ // No Light setting available.
+ ac->setIon(filter);
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
+ if (sendNormal) ac->send(); // Send the normal message.
+ if (clock >= 0) {
+ ac->setTime(clock);
+ ac->send(); // Setting the clock requires a different "timer" message.
+ }
+}
+#endif // SEND_VESTEL_AC
+
+#if SEND_WHIRLPOOL_AC
+void IRac::whirlpool(IRWhirlpoolAc *ac, const whirlpool_ac_remote_model_t model,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees,
+ const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
+ const bool turbo, const bool light,
+ const int16_t sleep, const int16_t clock) {
+ ac->setModel(model);
+ ac->setMode(ac->convertMode(mode));
+ ac->setTemp(degrees);
+ ac->setFan(ac->convertFan(fan));
+ ac->setSwing(swingv != stdAc::swingv_t::kOff);
+ // No Horizontal swing setting available.
+ // No Quiet setting available.
+ ac->setSuper(turbo);
+ ac->setLight(light);
+ // No Filter setting available
+ // No Clean setting available.
+ // No Beep setting available.
+ ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
+ if (clock >= 0) ac->setClock(clock);
+ ac->setPowerToggle(on);
+ ac->send();
+}
+#endif // SEND_WHIRLPOOL_AC
+
+// Create a new state base on desired & previous states but handle
+// any state changes for options that need to be toggled.
+// Args:
+// desired: The state_t structure describing the desired a/c state.
+// prev: Ptr to the previous state_t structure.
+//
+// Returns:
+// A stdAc::state_t with the needed settings.
+stdAc::state_t IRac::handleToggles(const stdAc::state_t desired,
+ const stdAc::state_t *prev) {
+ stdAc::state_t result = desired;
+ // If we've been given a previous state AND the it's the same A/C basically.
+ if (prev != NULL && desired.protocol == prev->protocol &&
+ desired.model == prev->model) {
+ // Check if we have to handle toggle settings for specific A/C protocols.
+ switch (desired.protocol) {
+ case decode_type_t::COOLIX:
+ if ((desired.swingv == stdAc::swingv_t::kOff) ^
+ (prev->swingv == stdAc::swingv_t::kOff)) // It changed, so toggle.
+ result.swingv = stdAc::swingv_t::kAuto;
+ else
+ result.swingv = stdAc::swingv_t::kOff; // No change, so no toggle.
+ result.turbo = desired.turbo ^ prev->turbo;
+ result.light = desired.light ^ prev->light;
+ result.clean = desired.clean ^ prev->clean;
+ result.sleep = ((desired.sleep >= 0) ^ (prev->sleep >= 0)) ? 0 : -1;
+ break;
+ case decode_type_t::DAIKIN128:
+ result.power = desired.power ^ prev->power;
+ result.light = desired.light ^ prev->light;
+ break;
+ case decode_type_t::MIDEA:
+ if ((desired.swingv == stdAc::swingv_t::kOff) ^
+ (prev->swingv == stdAc::swingv_t::kOff)) // It changed, so toggle.
+ result.swingv = stdAc::swingv_t::kAuto;
+ else
+ result.swingv = stdAc::swingv_t::kOff; // No change, so no toggle.
+ break;
+ case decode_type_t::WHIRLPOOL_AC:
+ result.power = desired.power ^ prev->power;
+ break;
+ case decode_type_t::PANASONIC_AC:
+ // CKP models use a power mode toggle.
+ if (desired.model == panasonic_ac_remote_model_t::kPanasonicCkp)
+ result.power = desired.power ^ prev->power;
+ break;
+ default:
+ {};
+ }
+ }
+ return result;
+}
+
+// Send A/C message for a given device using common A/C settings.
+// Args:
+// vendor: The type of A/C protocol to use.
+// model: The specific model of A/C if supported/applicable.
+// on: Should the unit be powered on? (or in some cases, toggled)
+// mode: What operating mode should the unit perform? e.g. Cool, Heat etc.
+// degrees: What temperature should the unit be set to?
+// celsius: Use degrees Celsius, otherwise Fahrenheit.
+// fan: Fan speed.
+// The following args are all "if supported" by the underlying A/C classes.
+// swingv: Control the vertical swing of the vanes.
+// swingh: Control the horizontal swing of the vanes.
+// quiet: Set the unit to quiet (fan) operation mode.
+// turbo: Set the unit to turbo operating mode. e.g. Max fan & cooling etc.
+// econo: Set the unit to economical operating mode.
+// light: Turn on the display/LEDs etc.
+// filter: Turn on any particle/ion/allergy filter etc.
+// clean: Turn on any settings to reduce mold etc. (Not self-clean mode.)
+// beep: Control if the unit beeps upon receiving commands.
+// sleep: Nr. of mins of sleep mode, or use sleep mode. (< 0 means off.)
+// clock: Nr. of mins past midnight to set the clock to. (< 0 means off.)
+// Returns:
+// boolean: True, if accepted/converted/attempted. False, if unsupported.
+bool IRac::sendAc(const decode_type_t vendor, const int16_t model,
+ const bool power, const stdAc::opmode_t mode,
+ const float degrees, const bool celsius,
+ const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool quiet, const bool turbo, const bool econo,
+ const bool light, const bool filter, const bool clean,
+ const bool beep, const int16_t sleep, const int16_t clock) {
+ // Convert the temperature to Celsius.
+ float degC;
+ if (celsius)
+ degC = degrees;
+ else
+ degC = fahrenheitToCelsius(degrees);
+ bool on = power;
+ // A hack for Home Assistant, it appears to need/want an Off opmode.
+ if (mode == stdAc::opmode_t::kOff) on = false;
+ // Per vendor settings & setup.
+ switch (vendor) {
+#if SEND_AMCOR
+ case AMCOR:
+ {
+ IRAmcorAc ac(_pin, _inverted, _modulation);
+ amcor(&ac, on, mode, degC, fan);
+ break;
+ }
+#endif // SEND_AMCOR
+#if SEND_ARGO
+ case ARGO:
+ {
+ IRArgoAC ac(_pin, _inverted, _modulation);
+ argo(&ac, on, mode, degC, fan, swingv, turbo, sleep);
+ break;
+ }
+#endif // SEND_ARGO
+#if SEND_COOLIX
+ case COOLIX:
+ {
+ IRCoolixAC ac(_pin, _inverted, _modulation);
+ coolix(&ac, on, mode, degC, fan, swingv, swingh,
+ turbo, light, clean, sleep);
+ break;
+ }
+#endif // SEND_COOLIX
+#if SEND_DAIKIN
+ case DAIKIN:
+ {
+ IRDaikinESP ac(_pin, _inverted, _modulation);
+ daikin(&ac, on, mode, degC, fan, swingv, swingh,
+ quiet, turbo, econo, clean);
+ break;
+ }
+#endif // SEND_DAIKIN
+#if SEND_DAIKIN128
+ case DAIKIN128:
+ {
+ IRDaikin128 ac(_pin, _inverted, _modulation);
+ daikin128(&ac, on, mode, degC, fan, swingv, quiet, turbo,
+ light, econo, sleep, clock);
+ break;
+ }
+#endif // SEND_DAIKIN2
+#if SEND_DAIKIN160
+ case DAIKIN160:
+ {
+ IRDaikin160 ac(_pin, _inverted, _modulation);
+ daikin160(&ac, on, mode, degC, fan, swingv);
+ break;
+ }
+#endif // SEND_DAIKIN160
+#if SEND_DAIKIN176
+ case DAIKIN176:
+ {
+ IRDaikin176 ac(_pin, _inverted, _modulation);
+ daikin176(&ac, on, mode, degC, fan, swingh);
+ break;
+ }
+#endif // SEND_DAIKIN176
+#if SEND_DAIKIN2
+ case DAIKIN2:
+ {
+ IRDaikin2 ac(_pin, _inverted, _modulation);
+ daikin2(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo,
+ light, econo, filter, clean, beep, sleep, clock);
+ break;
+ }
+#endif // SEND_DAIKIN2
+#if SEND_DAIKIN216
+ case DAIKIN216:
+ {
+ IRDaikin216 ac(_pin, _inverted, _modulation);
+ daikin216(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo);
+ break;
+ }
+#endif // SEND_DAIKIN216
+#if SEND_ELECTRA_AC
+ case ELECTRA_AC:
+ {
+ IRElectraAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ electra(&ac, on, mode, degC, fan, swingv, swingh);
+ break;
+ }
+#endif // SEND_ELECTRA_AC
+#if SEND_FUJITSU_AC
+ case FUJITSU_AC:
+ {
+ IRFujitsuAC ac(_pin, (fujitsu_ac_remote_model_t)model, _inverted,
+ _modulation);
+ ac.begin();
+ fujitsu(&ac, (fujitsu_ac_remote_model_t)model, on, mode, degC, fan,
+ swingv, swingh, quiet, turbo, econo);
+ break;
+ }
+#endif // SEND_FUJITSU_AC
+#if SEND_GOODWEATHER
+ case GOODWEATHER:
+ {
+ IRGoodweatherAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ goodweather(&ac, on, mode, degC, fan, swingv, turbo, light, sleep);
+ break;
+ }
+#endif // SEND_GOODWEATHER
+#if SEND_GREE
+ case GREE:
+ {
+ IRGreeAC ac(_pin, (gree_ac_remote_model_t)model, _inverted, _modulation);
+ ac.begin();
+ gree(&ac, (gree_ac_remote_model_t)model, on, mode, degC, fan, swingv,
+ turbo, light, clean, sleep);
+ break;
+ }
+#endif // SEND_GREE
+#if SEND_HAIER_AC
+ case HAIER_AC:
+ {
+ IRHaierAC ac(_pin, _inverted, _modulation);
+ ac.begin();
+ haier(&ac, on, mode, degC, fan, swingv, filter, sleep, clock);
+ break;
+ }
+#endif // SEND_HAIER_AC
+#if SEND_HAIER_AC_YRW02
+ case HAIER_AC_YRW02:
+ {
+ IRHaierACYRW02 ac(_pin, _inverted, _modulation);
+ ac.begin();
+ haierYrwo2(&ac, on, mode, degC, fan, swingv, turbo, filter, sleep);
+ break;
+ }
+#endif // SEND_HAIER_AC_YRW02
+#if SEND_HITACHI_AC
+ case HITACHI_AC:
+ {
+ IRHitachiAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ hitachi(&ac, on, mode, degC, fan, swingv, swingh);
+ break;
+ }
+#endif // SEND_HITACHI_AC
+#if SEND_KELVINATOR
+ case KELVINATOR:
+ {
+ IRKelvinatorAC ac(_pin, _inverted, _modulation);
+ ac.begin();
+ kelvinator(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo,
+ light, filter, clean);
+ break;
+ }
+#endif // SEND_KELVINATOR
+#if SEND_MIDEA
+ case MIDEA:
+ {
+ IRMideaAC ac(_pin, _inverted, _modulation);
+ ac.begin();
+ midea(&ac, on, mode, celsius, degrees, fan, swingv, sleep);
+ break;
+ }
+#endif // SEND_MIDEA
+#if SEND_MITSUBISHI_AC
+ case MITSUBISHI_AC:
+ {
+ IRMitsubishiAC ac(_pin, _inverted, _modulation);
+ ac.begin();
+ mitsubishi(&ac, on, mode, degC, fan, swingv, swingh, quiet, clock);
+ break;
+ }
+#endif // SEND_MITSUBISHI_AC
+#if SEND_MITSUBISHIHEAVY
+ case MITSUBISHI_HEAVY_88:
+ {
+ IRMitsubishiHeavy88Ac ac(_pin, _inverted, _modulation);
+ ac.begin();
+ mitsubishiHeavy88(&ac, on, mode, degC, fan, swingv, swingh,
+ turbo, econo, clean);
+ break;
+ }
+ case MITSUBISHI_HEAVY_152:
+ {
+ IRMitsubishiHeavy152Ac ac(_pin, _inverted, _modulation);
+ ac.begin();
+ mitsubishiHeavy152(&ac, on, mode, degC, fan, swingv, swingh,
+ quiet, turbo, econo, filter, clean, sleep);
+ break;
+ }
+#endif // SEND_MITSUBISHIHEAVY
+#if SEND_NEOCLIMA
+ case NEOCLIMA:
+ {
+ IRNeoclimaAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ neoclima(&ac, on, mode, degC, fan, swingv, swingh, turbo, light, filter,
+ sleep);
+ break;
+ }
+#endif // SEND_NEOCLIMA
+#if SEND_PANASONIC_AC
+ case PANASONIC_AC:
+ {
+ IRPanasonicAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ panasonic(&ac, (panasonic_ac_remote_model_t)model, on, mode, degC, fan,
+ swingv, swingh, quiet, turbo, clock);
+ break;
+ }
+#endif // SEND_PANASONIC_AC
+#if SEND_SAMSUNG_AC
+ case SAMSUNG_AC:
+ {
+ IRSamsungAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ samsung(&ac, on, mode, degC, fan, swingv, quiet, turbo, clean, beep);
+ break;
+ }
+#endif // SEND_SAMSUNG_AC
+#if SEND_SHARP_AC
+ case SHARP_AC:
+ {
+ IRSharpAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ sharp(&ac, on, mode, degC, fan);
+ break;
+ }
+#endif // SEND_SHARP_AC
+#if SEND_TCL112AC
+ case TCL112AC:
+ {
+ IRTcl112Ac ac(_pin, _inverted, _modulation);
+ ac.begin();
+ tcl112(&ac, on, mode, degC, fan, swingv, swingh, turbo, light, econo,
+ filter);
+ break;
+ }
+#endif // SEND_TCL112AC
+#if SEND_TECO
+ case TECO:
+ {
+ IRTecoAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ teco(&ac, on, mode, degC, fan, swingv, light, sleep);
+ break;
+ }
+#endif // SEND_TECO
+#if SEND_TOSHIBA_AC
+ case TOSHIBA_AC:
+ {
+ IRToshibaAC ac(_pin, _inverted, _modulation);
+ ac.begin();
+ toshiba(&ac, on, mode, degC, fan);
+ break;
+ }
+#endif // SEND_TOSHIBA_AC
+#if SEND_TROTEC
+ case TROTEC:
+ {
+ IRTrotecESP ac(_pin, _inverted, _modulation);
+ ac.begin();
+ trotec(&ac, on, mode, degC, fan, sleep);
+ break;
+ }
+#endif // SEND_TROTEC
+#if SEND_VESTEL_AC
+ case VESTEL_AC:
+ {
+ IRVestelAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ vestel(&ac, on, mode, degC, fan, swingv, turbo, filter, sleep, clock);
+ break;
+ }
+#endif // SEND_VESTEL_AC
+#if SEND_WHIRLPOOL_AC
+ case WHIRLPOOL_AC:
+ {
+ IRWhirlpoolAc ac(_pin, _inverted, _modulation);
+ ac.begin();
+ whirlpool(&ac, (whirlpool_ac_remote_model_t)model, on, mode, degC, fan,
+ swingv, turbo, light, sleep, clock);
+ break;
+ }
+#endif // SEND_WHIRLPOOL_AC
+ default:
+ return false; // Fail, didn't match anything.
+ }
+ return true; // Success.
+}
+
+// Send A/C message for a given device using state_t structures.
+// Args:
+// desired: The state_t structure describing the desired new a/c state.
+// prev: Ptr to the previous state_t structure.
+//
+// Returns:
+// boolean: True, if accepted/converted/attempted. False, if unsupported.
+bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
+ stdAc::state_t final = this->handleToggles(desired, prev);
+ return this->sendAc(final.protocol, final.model, final.power, final.mode,
+ final.degrees, final.celsius, final.fanspeed,
+ final.swingv, final.swingh, final.quiet, final.turbo,
+ final.econo, final.light, final.filter, final.clean,
+ final.beep, final.sleep, final.clock);
+}
+
+// Compare two AirCon states.
+// Returns: True if they differ, False if they don't.
+// Note: Excludes clock.
+bool IRac::cmpStates(const stdAc::state_t a, const stdAc::state_t b) {
+ return a.protocol != b.protocol || a.model != b.model || a.power != b.power ||
+ a.mode != b.mode || a.degrees != b.degrees || a.celsius != b.celsius ||
+ a.fanspeed != b.fanspeed || a.swingv != b.swingv ||
+ a.swingh != b.swingh || a.quiet != b.quiet || a.turbo != b.turbo ||
+ a.econo != b.econo || a.light != b.light || a.filter != b.filter ||
+ a.clean != b.clean || a.beep != b.beep || a.sleep != b.sleep;
+}
+
+stdAc::opmode_t IRac::strToOpmode(const char *str,
+ const stdAc::opmode_t def) {
+ if (!strcasecmp(str, "AUTO") || !strcasecmp(str, "AUTOMATIC"))
+ return stdAc::opmode_t::kAuto;
+ else if (!strcasecmp(str, "OFF") || !strcasecmp(str, "STOP"))
+ return stdAc::opmode_t::kOff;
+ else if (!strcasecmp(str, "COOL") || !strcasecmp(str, "COOLING"))
+ return stdAc::opmode_t::kCool;
+ else if (!strcasecmp(str, "HEAT") || !strcasecmp(str, "HEATING"))
+ return stdAc::opmode_t::kHeat;
+ else if (!strcasecmp(str, "DRY") || !strcasecmp(str, "DRYING") ||
+ !strcasecmp(str, "DEHUMIDIFY"))
+ return stdAc::opmode_t::kDry;
+ else if (!strcasecmp(str, "FAN") || !strcasecmp(str, "FANONLY") ||
+ !strcasecmp(str, "FAN_ONLY"))
+ return stdAc::opmode_t::kFan;
+ else
+ return def;
+}
+
+stdAc::fanspeed_t IRac::strToFanspeed(const char *str,
+ const stdAc::fanspeed_t def) {
+ if (!strcasecmp(str, "AUTO") || !strcasecmp(str, "AUTOMATIC"))
+ return stdAc::fanspeed_t::kAuto;
+ else if (!strcasecmp(str, "MIN") || !strcasecmp(str, "MINIMUM") ||
+ !strcasecmp(str, "LOWEST"))
+ return stdAc::fanspeed_t::kMin;
+ else if (!strcasecmp(str, "LOW"))
+ return stdAc::fanspeed_t::kLow;
+ else if (!strcasecmp(str, "MED") || !strcasecmp(str, "MEDIUM") ||
+ !strcasecmp(str, "MID"))
+ return stdAc::fanspeed_t::kMedium;
+ else if (!strcasecmp(str, "HIGH") || !strcasecmp(str, "HI"))
+ return stdAc::fanspeed_t::kHigh;
+ else if (!strcasecmp(str, "MAX") || !strcasecmp(str, "MAXIMUM") ||
+ !strcasecmp(str, "HIGHEST"))
+ return stdAc::fanspeed_t::kMax;
+ else
+ return def;
+}
+
+stdAc::swingv_t IRac::strToSwingV(const char *str,
+ const stdAc::swingv_t def) {
+ if (!strcasecmp(str, "AUTO") || !strcasecmp(str, "AUTOMATIC") ||
+ !strcasecmp(str, "ON") || !strcasecmp(str, "SWING"))
+ return stdAc::swingv_t::kAuto;
+ else if (!strcasecmp(str, "OFF") || !strcasecmp(str, "STOP"))
+ return stdAc::swingv_t::kOff;
+ else if (!strcasecmp(str, "MIN") || !strcasecmp(str, "MINIMUM") ||
+ !strcasecmp(str, "LOWEST") || !strcasecmp(str, "BOTTOM") ||
+ !strcasecmp(str, "DOWN"))
+ return stdAc::swingv_t::kLowest;
+ else if (!strcasecmp(str, "LOW"))
+ return stdAc::swingv_t::kLow;
+ else if (!strcasecmp(str, "MID") || !strcasecmp(str, "MIDDLE") ||
+ !strcasecmp(str, "MED") || !strcasecmp(str, "MEDIUM") ||
+ !strcasecmp(str, "CENTRE") || !strcasecmp(str, "CENTER"))
+ return stdAc::swingv_t::kMiddle;
+ else if (!strcasecmp(str, "HIGH") || !strcasecmp(str, "HI"))
+ return stdAc::swingv_t::kHigh;
+ else if (!strcasecmp(str, "HIGHEST") || !strcasecmp(str, "MAX") ||
+ !strcasecmp(str, "MAXIMUM") || !strcasecmp(str, "TOP") ||
+ !strcasecmp(str, "UP"))
+ return stdAc::swingv_t::kHighest;
+ else
+ return def;
+}
+
+stdAc::swingh_t IRac::strToSwingH(const char *str,
+ const stdAc::swingh_t def) {
+ if (!strcasecmp(str, "AUTO") || !strcasecmp(str, "AUTOMATIC") ||
+ !strcasecmp(str, "ON") || !strcasecmp(str, "SWING"))
+ return stdAc::swingh_t::kAuto;
+ else if (!strcasecmp(str, "OFF") || !strcasecmp(str, "STOP"))
+ return stdAc::swingh_t::kOff;
+ else if (!strcasecmp(str, "LEFTMAX") || !strcasecmp(str, "LEFT MAX") ||
+ !strcasecmp(str, "MAXLEFT") || !strcasecmp(str, "MAX LEFT") ||
+ !strcasecmp(str, "FARLEFT") || !strcasecmp(str, "FAR LEFT"))
+ return stdAc::swingh_t::kLeftMax;
+ else if (!strcasecmp(str, "LEFT"))
+ return stdAc::swingh_t::kLeft;
+ else if (!strcasecmp(str, "MID") || !strcasecmp(str, "MIDDLE") ||
+ !strcasecmp(str, "MED") || !strcasecmp(str, "MEDIUM") ||
+ !strcasecmp(str, "CENTRE") || !strcasecmp(str, "CENTER"))
+ return stdAc::swingh_t::kMiddle;
+ else if (!strcasecmp(str, "RIGHT"))
+ return stdAc::swingh_t::kRight;
+ else if (!strcasecmp(str, "RIGHTMAX") || !strcasecmp(str, "RIGHT MAX") ||
+ !strcasecmp(str, "MAXRIGHT") || !strcasecmp(str, "MAX RIGHT") ||
+ !strcasecmp(str, "FARRIGHT") || !strcasecmp(str, "FAR RIGHT"))
+ return stdAc::swingh_t::kRightMax;
+ else if (!strcasecmp(str, "WIDE"))
+ return stdAc::swingh_t::kWide;
+ else
+ return def;
+}
+
+// Assumes str is the model or an integer >= 1.
+int16_t IRac::strToModel(const char *str, const int16_t def) {
+ // Gree
+ if (!strcasecmp(str, "YAW1F")) {
+ return gree_ac_remote_model_t::YAW1F;
+ } else if (!strcasecmp(str, "YBOFB")) {
+ return gree_ac_remote_model_t::YBOFB;
+ // Fujitsu A/C models
+ } else if (!strcasecmp(str, "ARRAH2E")) {
+ return fujitsu_ac_remote_model_t::ARRAH2E;
+ } else if (!strcasecmp(str, "ARDB1")) {
+ return fujitsu_ac_remote_model_t::ARDB1;
+ } else if (!strcasecmp(str, "ARREB1E")) {
+ return fujitsu_ac_remote_model_t::ARREB1E;
+ } else if (!strcasecmp(str, "ARJW2")) {
+ return fujitsu_ac_remote_model_t::ARJW2;
+ // Panasonic A/C families
+ } else if (!strcasecmp(str, "LKE") || !strcasecmp(str, "PANASONICLKE")) {
+ return panasonic_ac_remote_model_t::kPanasonicLke;
+ } else if (!strcasecmp(str, "NKE") || !strcasecmp(str, "PANASONICNKE")) {
+ return panasonic_ac_remote_model_t::kPanasonicNke;
+ } else if (!strcasecmp(str, "DKE") || !strcasecmp(str, "PANASONICDKE")) {
+ return panasonic_ac_remote_model_t::kPanasonicDke;
+ } else if (!strcasecmp(str, "JKE") || !strcasecmp(str, "PANASONICJKE")) {
+ return panasonic_ac_remote_model_t::kPanasonicJke;
+ } else if (!strcasecmp(str, "CKP") || !strcasecmp(str, "PANASONICCKP")) {
+ return panasonic_ac_remote_model_t::kPanasonicCkp;
+ } else if (!strcasecmp(str, "RKR") || !strcasecmp(str, "PANASONICRKR")) {
+ return panasonic_ac_remote_model_t::kPanasonicRkr;
+ // Whirlpool A/C models
+ } else if (!strcasecmp(str, "DG11J13A") || !strcasecmp(str, "DG11J104") ||
+ !strcasecmp(str, "DG11J1-04")) {
+ return whirlpool_ac_remote_model_t::DG11J13A;
+ } else if (!strcasecmp(str, "DG11J191")) {
+ return whirlpool_ac_remote_model_t::DG11J191;
+ } else {
+ int16_t number = atoi(str);
+ if (number > 0)
+ return number;
+ else
+ return def;
+ }
+}
+
+bool IRac::strToBool(const char *str, const bool def) {
+ if (!strcasecmp(str, "ON") || !strcasecmp(str, "1") ||
+ !strcasecmp(str, "YES") || !strcasecmp(str, "TRUE"))
+ return true;
+ else if (!strcasecmp(str, "OFF") || !strcasecmp(str, "0") ||
+ !strcasecmp(str, "NO") || !strcasecmp(str, "FALSE"))
+ return false;
+ else
+ return def;
+}
+
+String IRac::boolToString(const bool value) {
+ return value ? F("on") : F("off");
+}
+
+String IRac::opmodeToString(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kOff:
+ return F("off");
+ case stdAc::opmode_t::kAuto:
+ return F("auto");
+ case stdAc::opmode_t::kCool:
+ return F("cool");
+ case stdAc::opmode_t::kHeat:
+ return F("heat");
+ case stdAc::opmode_t::kDry:
+ return F("dry");
+ case stdAc::opmode_t::kFan:
+ return F("fan_only");
+ default:
+ return F("unknown");
+ }
+}
+
+String IRac::fanspeedToString(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kAuto:
+ return F("auto");
+ case stdAc::fanspeed_t::kMax:
+ return F("max");
+ case stdAc::fanspeed_t::kHigh:
+ return F("high");
+ case stdAc::fanspeed_t::kMedium:
+ return F("medium");
+ case stdAc::fanspeed_t::kLow:
+ return F("low");
+ case stdAc::fanspeed_t::kMin:
+ return F("min");
+ default:
+ return F("unknown");
+ }
+}
+
+String IRac::swingvToString(const stdAc::swingv_t swingv) {
+ switch (swingv) {
+ case stdAc::swingv_t::kOff:
+ return F("off");
+ case stdAc::swingv_t::kAuto:
+ return F("auto");
+ case stdAc::swingv_t::kHighest:
+ return F("highest");
+ case stdAc::swingv_t::kHigh:
+ return F("high");
+ case stdAc::swingv_t::kMiddle:
+ return F("middle");
+ case stdAc::swingv_t::kLow:
+ return F("low");
+ case stdAc::swingv_t::kLowest:
+ return F("lowest");
+ default:
+ return F("unknown");
+ }
+}
+
+String IRac::swinghToString(const stdAc::swingh_t swingh) {
+ switch (swingh) {
+ case stdAc::swingh_t::kOff:
+ return F("off");
+ case stdAc::swingh_t::kAuto:
+ return F("auto");
+ case stdAc::swingh_t::kLeftMax:
+ return F("leftmax");
+ case stdAc::swingh_t::kLeft:
+ return F("left");
+ case stdAc::swingh_t::kMiddle:
+ return F("middle");
+ case stdAc::swingh_t::kRight:
+ return F("right");
+ case stdAc::swingh_t::kRightMax:
+ return F("rightmax");
+ case stdAc::swingh_t::kWide:
+ return F("wide");
+ default:
+ return F("unknown");
+ }
+}
+
+namespace IRAcUtils {
+ // Display the human readable state of an A/C message if we can.
+ // Args:
+ // result: A Ptr to the captured `decode_results` that contains an A/C mesg.
+ // Returns:
+ // A string with the human description of the A/C message. "" if we can't.
+ String resultAcToString(const decode_results * const result) {
+ switch (result->decode_type) {
+#if DECODE_AMCOR
+ case decode_type_t::AMCOR: {
+ IRAmcorAc ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_AMCOR
+#if DECODE_ARGO
+ case decode_type_t::ARGO: {
+ IRArgoAC ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_ARGO
+#if DECODE_DAIKIN
+ case decode_type_t::DAIKIN: {
+ IRDaikinESP ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_DAIKIN
+#if DECODE_DAIKIN128
+ case decode_type_t::DAIKIN128: {
+ IRDaikin128 ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_DAIKIN128
+#if DECODE_DAIKIN160
+ case decode_type_t::DAIKIN160: {
+ IRDaikin160 ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_DAIKIN160
+#if DECODE_DAIKIN176
+ case decode_type_t::DAIKIN176: {
+ IRDaikin176 ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_DAIKIN160
+#if DECODE_DAIKIN2
+ case decode_type_t::DAIKIN2: {
+ IRDaikin2 ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_DAIKIN2
+#if DECODE_DAIKIN216
+ case decode_type_t::DAIKIN216: {
+ IRDaikin216 ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_DAIKIN216
+#if DECODE_ELECTRA_AC
+ case decode_type_t::ELECTRA_AC: {
+ IRElectraAc ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_ELECTRA_AC
+#if DECODE_FUJITSU_AC
+ case decode_type_t::FUJITSU_AC: {
+ IRFujitsuAC ac(0);
+ ac.setRaw(result->state, result->bits / 8);
+ return ac.toString();
+ }
+#endif // DECODE_FUJITSU_AC
+#if DECODE_KELVINATOR
+ case decode_type_t::KELVINATOR: {
+ IRKelvinatorAC ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_KELVINATOR
+#if DECODE_MITSUBISHI_AC
+ case decode_type_t::MITSUBISHI_AC: {
+ IRMitsubishiAC ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_MITSUBISHI_AC
+#if DECODE_MITSUBISHIHEAVY
+ case decode_type_t::MITSUBISHI_HEAVY_88: {
+ IRMitsubishiHeavy88Ac ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+ case decode_type_t::MITSUBISHI_HEAVY_152: {
+ IRMitsubishiHeavy152Ac ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_MITSUBISHIHEAVY
+#if DECODE_NEOCLIMA
+ case decode_type_t::NEOCLIMA: {
+ IRNeoclimaAc ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_NEOCLIMA
+#if DECODE_TOSHIBA_AC
+ case decode_type_t::TOSHIBA_AC: {
+ IRToshibaAC ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_TOSHIBA_AC
+#if DECODE_TROTEC
+ case decode_type_t::TROTEC: {
+ IRTrotecESP ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_TROTEC
+#if DECODE_GOODWEATHER
+ case decode_type_t::GOODWEATHER: {
+ IRGoodweatherAc ac(0);
+ ac.setRaw(result->value); // Goodweather uses value instead of state.
+ return ac.toString();
+ }
+#endif // DECODE_GOODWEATHER
+#if DECODE_GREE
+ case decode_type_t::GREE: {
+ IRGreeAC ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_GREE
+#if DECODE_MIDEA
+ case decode_type_t::MIDEA: {
+ IRMideaAC ac(0);
+ ac.setRaw(result->value); // Midea uses value instead of state.
+ return ac.toString();
+ }
+#endif // DECODE_MIDEA
+#if DECODE_HAIER_AC
+ case decode_type_t::HAIER_AC: {
+ IRHaierAC ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_HAIER_AC
+#if DECODE_HAIER_AC_YRW02
+ case decode_type_t::HAIER_AC_YRW02: {
+ IRHaierACYRW02 ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_HAIER_AC_YRW02
+#if DECODE_SAMSUNG_AC
+ case decode_type_t::SAMSUNG_AC: {
+ IRSamsungAc ac(0);
+ ac.setRaw(result->state, result->bits / 8);
+ return ac.toString();
+ }
+#endif // DECODE_SAMSUNG_AC
+#if DECODE_SHARP_AC
+ case decode_type_t::SHARP_AC: {
+ IRSharpAc ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_SHARP_AC
+#if DECODE_COOLIX
+ case decode_type_t::COOLIX: {
+ IRCoolixAC ac(0);
+ ac.setRaw(result->value); // Coolix uses value instead of state.
+ return ac.toString();
+ }
+#endif // DECODE_COOLIX
+#if DECODE_PANASONIC_AC
+ case decode_type_t::PANASONIC_AC: {
+ if (result->bits > kPanasonicAcShortBits) {
+ IRPanasonicAc ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+ return "";
+ }
+#endif // DECODE_PANASONIC_AC
+#if DECODE_HITACHI_AC
+ case decode_type_t::HITACHI_AC: {
+ IRHitachiAc ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_HITACHI_AC
+#if DECODE_WHIRLPOOL_AC
+ case decode_type_t::WHIRLPOOL_AC: {
+ IRWhirlpoolAc ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_WHIRLPOOL_AC
+#if DECODE_VESTEL_AC
+ case decode_type_t::VESTEL_AC: {
+ IRVestelAc ac(0);
+ ac.setRaw(result->value); // Like Coolix, use value instead of state.
+ return ac.toString();
+ }
+#endif // DECODE_VESTEL_AC
+#if DECODE_TECO
+ case decode_type_t::TECO: {
+ IRTecoAc ac(0);
+ ac.setRaw(result->value); // Like Coolix, use value instead of state.
+ return ac.toString();
+ }
+#endif // DECODE_TECO
+#if DECODE_TCL112AC
+ case decode_type_t::TCL112AC: {
+ IRTcl112Ac ac(0);
+ ac.setRaw(result->state);
+ return ac.toString();
+ }
+#endif // DECODE_TCL112AC
+ default:
+ return "";
+ }
+ }
+
+ // Convert a valid IR A/C remote message that we understand enough into a
+ // Common A/C state.
+ //
+ // Args:
+ // decode: A PTR to a successful raw IR decode object.
+ // result: A PTR to a state structure to store the result in.
+ // prev: A PTR to a state structure which has the prev. state. (optional)
+ // Returns:
+ // A boolean indicating success or failure.
+ bool decodeToState(const decode_results *decode, stdAc::state_t *result,
+ const stdAc::state_t *prev) {
+ if (decode == NULL || result == NULL) return false; // Safety check.
+ switch (decode->decode_type) {
+#if DECODE_AMCOR
+ case decode_type_t::AMCOR: {
+ IRAmcorAc ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_AMCOR
+#if DECODE_ARGO
+ case decode_type_t::ARGO: {
+ IRArgoAC ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_ARGO
+#if DECODE_COOLIX
+ case decode_type_t::COOLIX: {
+ IRCoolixAC ac(kGpioUnused);
+ ac.setRaw(decode->value); // Uses value instead of state.
+ *result = ac.toCommon(prev);
+ break;
+ }
+#endif // DECODE_COOLIX
+#if DECODE_DAIKIN
+ case decode_type_t::DAIKIN: {
+ IRDaikinESP ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_DAIKIN
+#if DECODE_DAIKIN160
+ case decode_type_t::DAIKIN160: {
+ IRDaikin160 ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_DAIKIN160
+#if DECODE_DAIKIN176
+ case decode_type_t::DAIKIN176: {
+ IRDaikin176 ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_DAIKIN160
+#if DECODE_DAIKIN2
+ case decode_type_t::DAIKIN2: {
+ IRDaikin2 ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_DAIKIN2
+#if DECODE_DAIKIN216
+ case decode_type_t::DAIKIN216: {
+ IRDaikin216 ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_DAIKIN216
+#if DECODE_ELECTRA_AC
+ case decode_type_t::ELECTRA_AC: {
+ IRElectraAc ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_ELECTRA_AC
+#if DECODE_FUJITSU_AC
+ case decode_type_t::FUJITSU_AC: {
+ IRFujitsuAC ac(kGpioUnused);
+ ac.setRaw(decode->state, decode->bits / 8);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_FUJITSU_AC
+#if DECODE_GOODWEATHER
+ case decode_type_t::GOODWEATHER: {
+ IRGoodweatherAc ac(kGpioUnused);
+ ac.setRaw(decode->value); // Uses value instead of state.
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_GOODWEATHER
+#if DECODE_GREE
+ case decode_type_t::GREE: {
+ IRGreeAC ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_GREE
+#if DECODE_HAIER_AC
+ case decode_type_t::HAIER_AC: {
+ IRHaierAC ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_HAIER_AC
+#if DECODE_HAIER_AC_YRW02
+ case decode_type_t::HAIER_AC_YRW02: {
+ IRHaierACYRW02 ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_HAIER_AC_YRW02
+#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC2)
+ case decode_type_t::HITACHI_AC: {
+ IRHitachiAc ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC2)
+#if DECODE_KELVINATOR
+ case decode_type_t::KELVINATOR: {
+ IRKelvinatorAC ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_KELVINATOR
+#if DECODE_MIDEA
+ case decode_type_t::MIDEA: {
+ IRMideaAC ac(kGpioUnused);
+ ac.setRaw(decode->value); // Uses value instead of state.
+ *result = ac.toCommon(prev);
+ break;
+ }
+#endif // DECODE_MIDEA
+#if DECODE_MITSUBISHI_AC
+ case decode_type_t::MITSUBISHI_AC: {
+ IRMitsubishiAC ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_MITSUBISHI_AC
+#if DECODE_MITSUBISHIHEAVY
+ case decode_type_t::MITSUBISHI_HEAVY_88: {
+ IRMitsubishiHeavy88Ac ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+ case decode_type_t::MITSUBISHI_HEAVY_152: {
+ IRMitsubishiHeavy152Ac ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_MITSUBISHIHEAVY
+#if DECODE_NEOCLIMA
+ case decode_type_t::NEOCLIMA: {
+ IRNeoclimaAc ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_NEOCLIMA
+#if DECODE_PANASONIC_AC
+ case decode_type_t::PANASONIC_AC: {
+ IRPanasonicAc ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_PANASONIC_AC
+#if DECODE_SAMSUNG_AC
+ case decode_type_t::SAMSUNG_AC: {
+ IRSamsungAc ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_SAMSUNG_AC
+#if DECODE_SHARP_AC
+ case decode_type_t::SHARP_AC: {
+ IRSharpAc ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_SHARP_AC
+#if DECODE_TCL112AC
+ case decode_type_t::TCL112AC: {
+ IRTcl112Ac ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_TCL112AC
+#if DECODE_TECO
+ case decode_type_t::TECO: {
+ IRTecoAc ac(kGpioUnused);
+ ac.setRaw(decode->value); // Uses value instead of state.
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_TECO
+#if DECODE_TOSHIBA_AC
+ case decode_type_t::TOSHIBA_AC: {
+ IRToshibaAC ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_TOSHIBA_AC
+#if DECODE_TROTEC
+ case decode_type_t::TROTEC: {
+ IRTrotecESP ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_TROTEC
+#if DECODE_VESTEL_AC
+ case decode_type_t::VESTEL_AC: {
+ IRVestelAc ac(kGpioUnused);
+ ac.setRaw(decode->value); // Uses value instead of state.
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_VESTEL_AC
+#if DECODE_WHIRLPOOL_AC
+ case decode_type_t::WHIRLPOOL_AC: {
+ IRWhirlpoolAc ac(kGpioUnused);
+ ac.setRaw(decode->state);
+ *result = ac.toCommon();
+ break;
+ }
+#endif // DECODE_WHIRLPOOL_AC
+ default:
+ return false;
+ }
+ return true;
+ }
+} // namespace IRAcUtils
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRac.h b/lib/IRremoteESP8266-2.6.5/src/IRac.h
similarity index 68%
rename from lib/IRremoteESP8266-2.6.0/src/IRac.h
rename to lib/IRremoteESP8266-2.6.5/src/IRac.h
index ce8d50507..73ee4b2a3 100644
--- a/lib/IRremoteESP8266-2.6.0/src/IRac.h
+++ b/lib/IRremoteESP8266-2.6.5/src/IRac.h
@@ -6,14 +6,14 @@
#ifndef UNIT_TEST
#include
#endif
-#ifndef ARDUINO
-#include
-#endif
#include "IRremoteESP8266.h"
+#include "ir_Amcor.h"
#include "ir_Argo.h"
#include "ir_Coolix.h"
#include "ir_Daikin.h"
#include "ir_Fujitsu.h"
+#include "ir_Electra.h"
+#include "ir_Goodweather.h"
#include "ir_Gree.h"
#include "ir_Haier.h"
#include "ir_Hitachi.h"
@@ -21,8 +21,10 @@
#include "ir_Midea.h"
#include "ir_Mitsubishi.h"
#include "ir_MitsubishiHeavy.h"
+#include "ir_Neoclima.h"
#include "ir_Panasonic.h"
#include "ir_Samsung.h"
+#include "ir_Sharp.h"
#include "ir_Tcl.h"
#include "ir_Teco.h"
#include "ir_Toshiba.h"
@@ -30,9 +32,14 @@
#include "ir_Vestel.h"
#include "ir_Whirlpool.h"
+// Constants
+const int8_t kGpioUnused = -1;
+
+// Class
class IRac {
public:
- explicit IRac(uint8_t pin);
+ explicit IRac(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
static bool isProtocolSupported(const decode_type_t protocol);
bool sendAc(const decode_type_t vendor, const int16_t model,
const bool power, const stdAc::opmode_t mode, const float degrees,
@@ -42,23 +49,36 @@ class IRac {
const bool light, const bool filter, const bool clean,
const bool beep, const int16_t sleep = -1,
const int16_t clock = -1);
-
+ bool sendAc(const stdAc::state_t desired, const stdAc::state_t *prev = NULL);
+ static bool cmpStates(const stdAc::state_t a, const stdAc::state_t b);
static bool strToBool(const char *str, const bool def = false);
static int16_t strToModel(const char *str, const int16_t def = -1);
static stdAc::opmode_t strToOpmode(
- const char *str, const stdAc::opmode_t def = stdAc::opmode_t::kAuto);
+ const char *str, const stdAc::opmode_t def = stdAc::opmode_t::kAuto);
static stdAc::fanspeed_t strToFanspeed(
- const char *str,
- const stdAc::fanspeed_t def = stdAc::fanspeed_t::kAuto);
+ const char *str,
+ const stdAc::fanspeed_t def = stdAc::fanspeed_t::kAuto);
static stdAc::swingv_t strToSwingV(
- const char *str, const stdAc::swingv_t def = stdAc::swingv_t::kOff);
+ const char *str, const stdAc::swingv_t def = stdAc::swingv_t::kOff);
static stdAc::swingh_t strToSwingH(
- const char *str, const stdAc::swingh_t def = stdAc::swingh_t::kOff);
+ const char *str, const stdAc::swingh_t def = stdAc::swingh_t::kOff);
+ static String boolToString(const bool value);
+ static String opmodeToString(const stdAc::opmode_t mode);
+ static String fanspeedToString(const stdAc::fanspeed_t speed);
+ static String swingvToString(const stdAc::swingv_t swingv);
+ static String swinghToString(const stdAc::swingh_t swingh);
#ifndef UNIT_TEST
private:
#endif
- uint8_t _pin;
+ uint16_t _pin;
+ bool _inverted;
+ bool _modulation;
+#if SEND_AMCOR
+ void amcor(IRAmcorAc *ac,
+ const bool on, const stdAc::opmode_t mode, const float degrees,
+ const stdAc::fanspeed_t fan);
+#endif // SEND_AMCOR
#if SEND_ARGO
void argo(IRArgoAC *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
@@ -81,6 +101,27 @@ class IRac {
const bool quiet, const bool turbo, const bool econo,
const bool clean);
#endif // SEND_DAIKIN
+#if SEND_DAIKIN128
+ void daikin128(IRDaikin128 *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv,
+ const bool quiet, const bool turbo, const bool light,
+ const bool econo, const int16_t sleep = -1,
+ const int16_t clock = -1);
+#endif // SEND_DAIKIN128
+#if SEND_DAIKIN160
+void daikin160(IRDaikin160 *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv);
+#endif // SEND_DAIKIN160
+#if SEND_DAIKIN176
+void daikin176(IRDaikin176 *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingh_t swingh);
+#endif // SEND_DAIKIN176
#if SEND_DAIKIN2
void daikin2(IRDaikin2 *ac,
const bool on, const stdAc::opmode_t mode,
@@ -96,17 +137,33 @@ void daikin216(IRDaikin216 *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool quiet);
+ const bool quiet, const bool turbo);
#endif // SEND_DAIKIN216
+#if SEND_ELECTRA_AC
+void electra(IRElectraAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv,
+ const stdAc::swingh_t swingh);
+#endif // SEND_ELECTRA_AC
#if SEND_FUJITSU_AC
void fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
- const bool quiet);
+ const bool quiet, const bool turbo, const bool econo);
#endif // SEND_FUJITSU_AC
+#if SEND_GOODWEATHER
+ void goodweather(IRGoodweatherAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees,
+ const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv,
+ const bool turbo, const bool light,
+ const int16_t sleep = -1);
+#endif // SEND_GOODWEATHER
#if SEND_GREE
- void gree(IRGreeAC *ac,
+ void gree(IRGreeAC *ac, const gree_ac_remote_model_t model,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool turbo, const bool light, const bool clean,
@@ -143,14 +200,16 @@ void daikin216(IRDaikin216 *ac,
#endif // SEND_KELVINATOR
#if SEND_MIDEA
void midea(IRMideaAC *ac,
- const bool on, const stdAc::opmode_t mode, const float degrees,
- const stdAc::fanspeed_t fan, const int16_t sleep = -1);
+ const bool on, const stdAc::opmode_t mode, const bool celsius,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const int16_t sleep = -1);
#endif // SEND_MIDEA
#if SEND_MITSUBISHI_AC
void mitsubishi(IRMitsubishiAC *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
+ const stdAc::swingh_t swingh,
const bool quiet, const int16_t clock = -1);
#endif // SEND_MITSUBISHI_AC
#if SEND_MITSUBISHIHEAVY
@@ -169,6 +228,13 @@ void daikin216(IRDaikin216 *ac,
const bool filter, const bool clean,
const int16_t sleep = -1);
#endif // SEND_MITSUBISHIHEAVY
+#if SEND_NEOCLIMA
+ void neoclima(IRNeoclimaAc *ac, const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan,
+ const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
+ const bool turbo, const bool light, const bool filter,
+ const int16_t sleep = -1);
+#endif // SEND_NEOCLIMA
#if SEND_PANASONIC_AC
void panasonic(IRPanasonicAc *ac, const panasonic_ac_remote_model_t model,
const bool on, const stdAc::opmode_t mode, const float degrees,
@@ -181,8 +247,13 @@ void daikin216(IRDaikin216 *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool quiet, const bool turbo, const bool clean,
- const bool beep, const bool sendOnOffHack = true);
+ const bool beep, const bool dopower = true);
#endif // SEND_SAMSUNG_AC
+#if SEND_SHARP_AC
+ void sharp(IRSharpAc *ac,
+ const bool on, const stdAc::opmode_t mode,
+ const float degrees, const stdAc::fanspeed_t fan);
+#endif // SEND_SHARP_AC
#if SEND_TCL112AC
void tcl112(IRTcl112Ac *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
@@ -195,7 +266,7 @@ void daikin216(IRDaikin216 *ac,
void teco(IRTecoAc *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
- const int16_t sleep = -1);
+ const bool light, const int16_t sleep = -1);
#endif // SEND_TECO
#if SEND_TOSHIBA_AC
void toshiba(IRToshibaAC *ac,
@@ -222,27 +293,13 @@ void daikin216(IRDaikin216 *ac,
const bool turbo, const bool light,
const int16_t sleep = -1, const int16_t clock = -1);
#endif // SEND_WHIRLPOOL_AC
+static stdAc::state_t handleToggles(const stdAc::state_t desired,
+ const stdAc::state_t *prev = NULL);
}; // IRac class
-// Structure to hold a common A/C state.
-typedef struct {
- decode_type_t protocol;
- int16_t model;
- bool power;
- stdAc::opmode_t mode;
- float degrees;
- bool celsius;
- stdAc::fanspeed_t fanspeed;
- stdAc::swingv_t swingv;
- stdAc::swingh_t swingh;
- bool quiet;
- bool turbo;
- bool econo;
- bool light;
- bool filter;
- bool clean;
- bool beep;
- int16_t sleep;
- int16_t clock;
-} commonAcState_t;
+namespace IRAcUtils {
+ String resultAcToString(const decode_results * const results);
+ bool decodeToState(const decode_results *decode, stdAc::state_t *result,
+ const stdAc::state_t *prev = NULL);
+} // namespace IRAcUtils
#endif // IRAC_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRrecv.cpp b/lib/IRremoteESP8266-2.6.5/src/IRrecv.cpp
similarity index 56%
rename from lib/IRremoteESP8266-2.6.0/src/IRrecv.cpp
rename to lib/IRremoteESP8266-2.6.5/src/IRrecv.cpp
index eac868084..739ced38f 100644
--- a/lib/IRremoteESP8266-2.6.0/src/IRrecv.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/IRrecv.cpp
@@ -1,18 +1,23 @@
// Copyright 2009 Ken Shirriff
// Copyright 2015 Mark Szabo
// Copyright 2015 Sebastien Warin
-// Copyright 2017 David Conran
+// Copyright 2017, 2019 David Conran
#include "IRrecv.h"
#include
#ifndef UNIT_TEST
+#if defined(ESP8266)
extern "C" {
#include
#include
}
+#endif // ESP8266
#include
#endif
#include
+#ifdef UNIT_TEST
+#include
+#endif // UNIT_TEST
#include "IRremoteESP8266.h"
#include "IRutils.h"
@@ -20,32 +25,68 @@ extern "C" {
#undef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR
#endif
+
+#ifndef USE_IRAM_ATTR
+#if defined(ESP8266)
+#define USE_IRAM_ATTR ICACHE_RAM_ATTR
+#endif // ESP8266
+#if defined(ESP32)
+#define USE_IRAM_ATTR IRAM_ATTR
+#endif // ESP32
+#endif // USE_IRAM_ATTR
+
+#define ONCE 0
+
+// Updated by David Conran (https://github.com/crankyoldgit) for receiving IR
+// code on ESP32
// Updated by Sebastien Warin (http://sebastien.warin.fr) for receiving IR code
// on ESP8266
-// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for
+// Updated by markszabo (https://github.com/crankyoldgit/IRremoteESP8266) for
// sending IR code on ESP8266
// Globals
#ifndef UNIT_TEST
+#if defined(ESP8266)
static ETSTimer timer;
-#endif
+#endif // ESP8266
+#if defined(ESP32)
+static hw_timer_t * timer = NULL;
+#endif // ESP32
+#endif // UNIT_TEST
+
+#if defined(ESP32)
+portMUX_TYPE irremote_mux = portMUX_INITIALIZER_UNLOCKED;
+#endif // ESP32
volatile irparams_t irparams;
irparams_t *irparams_save; // A copy of the interrupt state while decoding.
#ifndef UNIT_TEST
-static void ICACHE_RAM_ATTR read_timeout(void *arg __attribute__((unused))) {
+#if defined(ESP8266)
+static void USE_IRAM_ATTR read_timeout(void *arg __attribute__((unused))) {
os_intr_lock();
+#endif // ESP8266
+#if defined(ESP32)
+static void USE_IRAM_ATTR read_timeout(void) {
+ portENTER_CRITICAL(&irremote_mux);
+#endif // ESP32
if (irparams.rawlen) irparams.rcvstate = kStopState;
+#if defined(ESP8266)
os_intr_unlock();
+#endif // ESP8266
+#if defined(ESP32)
+ portEXIT_CRITICAL(&irremote_mux);
+#endif // ESP32
}
-static void ICACHE_RAM_ATTR gpio_intr() {
- uint32_t now = system_get_time();
- uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
+static void USE_IRAM_ATTR gpio_intr() {
+ uint32_t now = micros();
static uint32_t start = 0;
+#if defined(ESP8266)
+ uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
os_timer_disarm(&timer);
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
+#endif // ESP8266
// Grab a local copy of rawlen to reduce instructions used in IRAM.
// This is an ugly premature optimisation code-wise, but we do everything we
@@ -74,8 +115,14 @@ static void ICACHE_RAM_ATTR gpio_intr() {
irparams.rawlen++;
start = now;
-#define ONCE 0
+
+#if defined(ESP8266)
os_timer_arm(&timer, irparams.timeout, ONCE);
+#endif // ESP8266
+#if defined(ESP32)
+ timerWrite(timer, 0); // Reset the timeout.
+ timerAlarmEnable(timer);
+#endif // ESP32
}
#endif // UNIT_TEST
@@ -87,11 +134,21 @@ static void ICACHE_RAM_ATTR gpio_intr() {
// bufsize: Nr. of entries to have in the capture buffer. (Default: kRawBuf)
// timeout: Nr. of milli-Seconds of no signal before we stop capturing data.
// (Default: kTimeoutMs)
-// save_buffer: Use a second (save) buffer to decode from. (Def: false)
+// save_buffer: Use a second (save) buffer to decode from. (Default: false)
+// timer_num: Which ESP32 timer number to use? ESP32 only, otherwise unused.
+// (Range: 0-3. Default: kDefaultESP32Timer)
// Returns:
// An IRrecv class object.
-IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize, uint8_t timeout,
- bool save_buffer) {
+#if defined(ESP32)
+IRrecv::IRrecv(const uint16_t recvpin, const uint16_t bufsize,
+ const uint8_t timeout, const bool save_buffer,
+ const uint8_t timer_num) {
+ // There are only 4 timers. 0 to 3.
+ _timer_num = std::min(timer_num, (uint8_t)3);
+#else // ESP32
+IRrecv::IRrecv(const uint16_t recvpin, const uint16_t bufsize,
+ const uint8_t timeout, const bool save_buffer) {
+#endif // ESP32
irparams.recvpin = recvpin;
irparams.bufsize = bufsize;
// Ensure we are going to be able to store all possible values in the
@@ -123,8 +180,9 @@ IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize, uint8_t timeout,
irparams_save = NULL;
}
#if DECODE_HASH
- unknown_threshold = kUnknownThreshold;
+ _unknown_threshold = kUnknownThreshold;
#endif // DECODE_HASH
+ _tolerance = kTolerance;
}
// Class destructor
@@ -134,35 +192,70 @@ IRrecv::~IRrecv(void) {
delete[] irparams_save->rawbuf;
delete irparams_save;
}
+ disableIRIn();
+#if defined(ESP32)
+ if (timer != NULL) timerEnd(timer); // Cleanup the ESP32 timeout timer.
+#endif // ESP32
}
-// initialization
-void IRrecv::enableIRIn() {
- // initialize state machine variables
+// Set up and (re)start the IR capture mechanism.
+//
+// Args:
+// pullup: A flag indicating should the GPIO use the internal pullup resistor.
+// (Default: `false`. i.e. No.)
+void IRrecv::enableIRIn(const bool pullup) {
+ // ESP32's seem to require explicitly setting the GPIO to INPUT etc.
+ // This wasn't required on the ESP8266s, but it shouldn't hurt to make sure.
+ if (pullup) {
+#ifndef UNIT_TEST
+ pinMode(irparams.recvpin, INPUT_PULLUP);
+ } else {
+ pinMode(irparams.recvpin, INPUT);
+#endif // UNIT_TEST
+ }
+#if defined(ESP32)
+ // Initialize the ESP32 timer.
+ timer = timerBegin(_timer_num, 80, true); // 80MHz / 80 = 1 uSec granularity.
+ // Set the timer so it only fires once, and set it's trigger in uSeconds.
+ timerAlarmWrite(timer, MS_TO_USEC(irparams.timeout), ONCE);
+ // Note: Interrupt needs to be attached before it can be enabled or disabled.
+ timerAttachInterrupt(timer, &read_timeout, true);
+#endif // ESP32
+
+ // Initialize state machine variables
resume();
#ifndef UNIT_TEST
- // Initialize timer
+#if defined(ESP8266)
+ // Initialize ESP8266 timer.
os_timer_disarm(&timer);
os_timer_setfn(&timer, reinterpret_cast(read_timeout),
NULL);
-
+#endif // ESP8266
// Attach Interrupt
attachInterrupt(irparams.recvpin, gpio_intr, CHANGE);
-#endif
+#endif // UNIT_TEST
}
-void IRrecv::disableIRIn() {
+void IRrecv::disableIRIn(void) {
#ifndef UNIT_TEST
+#if defined(ESP8266)
os_timer_disarm(&timer);
+#endif // ESP8266
+#if defined(ESP32)
+ timerAlarmDisable(timer);
+#endif // ESP32
detachInterrupt(irparams.recvpin);
-#endif
+#endif // UNIT_TEST
}
-void IRrecv::resume() {
+void IRrecv::resume(void) {
irparams.rcvstate = kIdleState;
irparams.rawlen = 0;
irparams.overflow = false;
+#if defined(ESP32)
+ timerAlarmDisable(timer);
+#endif // ESP32
}
// Make a copy of the interrupt state & buffer data.
@@ -196,15 +289,24 @@ void IRrecv::copyIrParams(volatile irparams_t *src, irparams_t *dst) {
// Obtain the maximum number of entries possible in the capture buffer.
// i.e. It's size.
-uint16_t IRrecv::getBufSize() { return irparams.bufsize; }
+uint16_t IRrecv::getBufSize(void) { return irparams.bufsize; }
#if DECODE_HASH
// Set the minimum length we will consider for reporting UNKNOWN message types.
-void IRrecv::setUnknownThreshold(uint16_t length) {
- unknown_threshold = length;
+void IRrecv::setUnknownThreshold(const uint16_t length) {
+ _unknown_threshold = length;
}
#endif // DECODE_HASH
+
+// Set the base tolerance percentage for matching incoming IR messages.
+void IRrecv::setTolerance(const uint8_t percent) {
+ _tolerance = std::min(percent, (uint8_t)100);
+}
+
+// Get the base tolerance percentage for matching incoming IR messages.
+uint8_t IRrecv::getTolerance(void) { return _tolerance; }
+
// Decodes the received IR message.
// If the interrupt state is saved, we will immediately resume waiting
// for the next IR message to avoid missing messages.
@@ -335,7 +437,7 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) {
#if DECODE_DENON
// Denon needs to precede Panasonic as it is a special case of Panasonic.
DPRINTLN("Attempting Denon decode");
- if (decodeDenon(results, DENON_48_BITS) || decodeDenon(results, DENON_BITS) ||
+ if (decodeDenon(results, kDenon48Bits) || decodeDenon(results, kDenonBits) ||
decodeDenon(results, kDenonLegacyBits))
return true;
#endif
@@ -523,6 +625,50 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) {
DPRINTLN("Attempting MITSUBISHIHEAVY (88 bit) decode");
if (decodeMitsubishiHeavy(results, kMitsubishiHeavy88Bits)) return true;
#endif
+#if DECODE_ARGO
+ DPRINTLN("Attempting Argo decode");
+ if (decodeArgo(results)) return true;
+#endif // DECODE_ARGO
+#if DECODE_SHARP_AC
+ DPRINTLN("Attempting SHARP_AC decode");
+ if (decodeSharpAc(results)) return true;
+#endif
+#if DECODE_GOODWEATHER
+ DPRINTLN("Attempting GOODWEATHER decode");
+ if (decodeGoodweather(results)) return true;
+#endif // DECODE_GOODWEATHER
+#if DECODE_INAX
+ DPRINTLN("Attempting Inax decode");
+ if (decodeInax(results)) return true;
+#endif // DECODE_INAX
+#if DECODE_TROTEC
+ DPRINTLN("Attempting Trotec decode");
+ if (decodeTrotec(results)) return true;
+#endif // DECODE_TROTEC
+#if DECODE_DAIKIN160
+ DPRINTLN("Attempting Daikin160 decode");
+ if (decodeDaikin160(results)) return true;
+#endif // DECODE_DAIKIN160
+#if DECODE_NEOCLIMA
+ DPRINTLN("Attempting Neoclima decode");
+ if (decodeNeoclima(results)) return true;
+#endif // DECODE_NEOCLIMA
+#if DECODE_DAIKIN176
+ DPRINTLN("Attempting Daikin176 decode");
+ if (decodeDaikin176(results)) return true;
+#endif // DECODE_DAIKIN176
+#if DECODE_DAIKIN128
+ DPRINTLN("Attempting Daikin128 decode");
+ if (decodeDaikin128(results)) return true;
+#endif // DECODE_DAIKIN128
+#if DECODE_AMCOR
+ DPRINTLN("Attempting Amcor decode");
+ if (decodeAmcor(results)) return true;
+#endif // DECODE_AMCOR
+#if DECODE_DAIKIN152
+ DPRINTLN("Attempting Daikin152 decode");
+ if (decodeDaikin152(results)) return true;
+#endif // DECODE_DAIKIN152
#if DECODE_HASH
// decodeHash returns a hash on any input.
// Thus, it needs to be last in the list.
@@ -537,6 +683,11 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) {
return false;
}
+// Convert the tolerance percentage into something valid.
+uint8_t IRrecv::_validTolerance(const uint8_t percentage) {
+ return (percentage > 100) ? _tolerance : percentage;
+}
+
// Calculate the lower bound of the nr. of ticks.
//
// Args:
@@ -545,10 +696,12 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) {
// delta: A non-scaling amount to reduce usecs by.
// Returns:
// Nr. of ticks.
-uint32_t IRrecv::ticksLow(uint32_t usecs, uint8_t tolerance, uint16_t delta) {
+uint32_t IRrecv::ticksLow(const uint32_t usecs, const uint8_t tolerance,
+ const uint16_t delta) {
// max() used to ensure the result can't drop below 0 before the cast.
return ((uint32_t)std::max(
- (int32_t)(usecs * (1.0 - tolerance / 100.0) - delta), 0));
+ (int32_t)(usecs * (1.0 - _validTolerance(tolerance) / 100.0) - delta),
+ 0));
}
// Calculate the upper bound of the nr. of ticks.
@@ -559,8 +712,10 @@ uint32_t IRrecv::ticksLow(uint32_t usecs, uint8_t tolerance, uint16_t delta) {
// delta: A non-scaling amount to increase usecs by.
// Returns:
// Nr. of ticks.
-uint32_t IRrecv::ticksHigh(uint32_t usecs, uint8_t tolerance, uint16_t delta) {
- return ((uint32_t)(usecs * (1.0 + tolerance / 100.0)) + 1 + delta);
+uint32_t IRrecv::ticksHigh(const uint32_t usecs, const uint8_t tolerance,
+ const uint16_t delta) {
+ return ((uint32_t)(usecs * (1.0 + _validTolerance(tolerance) / 100.0)) + 1 +
+ delta);
}
// Check if we match a pulse(measured) with the desired within
@@ -583,6 +738,17 @@ bool IRrecv::match(uint32_t measured, uint32_t desired, uint8_t tolerance,
DPRINT(measured);
DPRINT(" <= ");
DPRINTLN(ticksHigh(desired, tolerance, delta));
+#ifdef UNIT_TEST
+ // Sanity checks that we don't have values that cause integer over/underflow.
+ // Only performed during testing so there is no performance hit in normal
+ // operation.
+ assert(ticksLow(desired, tolerance, delta) <= desired);
+ // Check if we overflowed. (UINT32_MAX >> 3 is approx 9 minutes!)
+ assert(ticksHigh(desired, tolerance, delta) < UINT32_MAX >> 3);
+ // Check if our high mark is below where we started. This could happen.
+ // If there is a legit case, then this should be removed.
+ assert(ticksHigh(desired, tolerance, delta) >= desired);
+#endif // UNIT_TEST
return (measured >= ticksLow(desired, tolerance, delta) &&
measured <= ticksHigh(desired, tolerance, delta));
}
@@ -616,6 +782,17 @@ bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired,
DPRINT(", ");
DPRINT(ticksLow(MS_TO_USEC(irparams.timeout), tolerance, delta));
DPRINTLN(")]");
+#ifdef UNIT_TEST
+ // Sanity checks that we don't have values that cause integer over/underflow.
+ // Only performed during testing so there is no performance hit in normal
+ // operation.
+ assert(ticksLow(desired, tolerance, delta) <= desired);
+ // Check if we overflowed. (UINT32_MAX >> 3 is approx 9 minutes!)
+ assert(ticksHigh(desired, tolerance, delta) < UINT32_MAX >> 3);
+ // Check if our high mark is below where we started. This could happen.
+ // If there is a legit case, then this should be removed.
+ assert(ticksHigh(desired, tolerance, delta) >= desired);
+#endif // UNIT_TEST
// We really should never get a value of 0, except as the last value
// in the buffer. If that is the case, then assume infinity and return true.
if (measured == 0) return true;
@@ -686,7 +863,7 @@ bool IRrecv::matchSpace(uint32_t measured, uint32_t desired, uint8_t tolerance,
// Compare two tick values, returning 0 if newval is shorter,
// 1 if newval is equal, and 2 if newval is longer
// Use a tolerance of 20%
-int16_t IRrecv::compare(uint16_t oldval, uint16_t newval) {
+uint16_t IRrecv::compare(const uint16_t oldval, const uint16_t newval) {
if (newval < oldval * 0.8)
return 0;
else if (oldval < newval * 0.8)
@@ -702,14 +879,14 @@ int16_t IRrecv::compare(uint16_t oldval, uint16_t newval) {
*/
bool IRrecv::decodeHash(decode_results *results) {
// Require at least some samples to prevent triggering on noise
- if (results->rawlen < unknown_threshold) return false;
+ if (results->rawlen < _unknown_threshold) return false;
int32_t hash = kFnvBasis32;
// 'rawlen - 2' to avoid the look ahead from going out of bounds.
// Should probably be -3 to avoid comparing the trailing space entry,
// however it is left this way for compatibility with previously captured
// values.
for (uint16_t i = 1; i < results->rawlen - 2; i++) {
- int16_t value = compare(results->rawbuf[i], results->rawbuf[i + 2]);
+ uint16_t value = compare(results->rawbuf[i], results->rawbuf[i + 2]);
// Add value into the hash
hash = (hash * kFnvPrime32) ^ value;
}
@@ -733,7 +910,7 @@ bool IRrecv::decodeHash(decode_results *results) {
// onespace: Nr. of uSeconds in an expected space signal for a '1' bit.
// zeromark: Nr. of uSeconds in an expected mark signal for a '0' bit.
// zerospace: Nr. of uSeconds in an expected space signal for a '0' bit.
-// tolerance: Percentage error margin to allow. (Def: kTolerance)
+// tolerance: Percentage error margin to allow. (Def: kUseDefTol)
// excess: Nr. of useconds. (Def: kMarkExcess)
// MSBfirst: Bit order to save the data in. (Def: true)
// Returns:
@@ -765,4 +942,236 @@ match_result_t IRrecv::matchData(
return result;
}
+// Match & decode the typical data section of an IR message.
+// The bytes are stored at result_ptr. The first byte in the result equates to
+// the first byte encountered, and so on.
+//
+// Args:
+// data_ptr: A pointer to where we are at in the capture buffer.
+// result_ptr: A pointer to where to start storing the bytes we decoded.
+// remaining: The size of the capture buffer are remaining.
+// nbytes: Nr. of data bytes we expect.
+// onemark: Nr. of uSeconds in an expected mark signal for a '1' bit.
+// onespace: Nr. of uSeconds in an expected space signal for a '1' bit.
+// zeromark: Nr. of uSeconds in an expected mark signal for a '0' bit.
+// zerospace: Nr. of uSeconds in an expected space signal for a '0' bit.
+// tolerance: Percentage error margin to allow. (Def: kUseDefTol)
+// excess: Nr. of useconds. (Def: kMarkExcess)
+// MSBfirst: Bit order to save the data in. (Def: true)
+// Returns:
+// A uint16_t: If successful, how many buffer entries were used. Otherwise 0.
+uint16_t IRrecv::matchBytes(volatile uint16_t *data_ptr, uint8_t *result_ptr,
+ const uint16_t remaining, const uint16_t nbytes,
+ const uint16_t onemark, const uint32_t onespace,
+ const uint16_t zeromark, const uint32_t zerospace,
+ const uint8_t tolerance, const int16_t excess,
+ const bool MSBfirst) {
+ // Check if there is enough capture buffer to possibly have the desired bytes.
+ if (remaining < nbytes * 8 * 2) return 0; // Nope, so abort.
+ uint16_t offset = 0;
+ for (uint16_t byte_pos = 0; byte_pos < nbytes; byte_pos++) {
+ match_result_t result = matchData(data_ptr + offset, 8, onemark, onespace,
+ zeromark, zerospace, tolerance, excess,
+ MSBfirst);
+ if (result.success == false) return 0; // Fail
+ result_ptr[byte_pos] = (uint8_t)result.data;
+ offset += result.used;
+ }
+ return offset;
+}
+
+// Match & decode a generic/typical IR message.
+// The data is stored in result_bits_ptr or result_bytes_ptr depending on flag
+// `use_bits`.
+// Values of 0 for hdrmark, hdrspace, footermark, or footerspace mean skip
+// that requirement.
+//
+// Args:
+// data_ptr: A pointer to where we are at in the capture buffer.
+// result_bits_ptr: A pointer to where to start storing the bits we decoded.
+// result_bytes_ptr: A pointer to where to start storing the bytes we decoded.
+// use_bits: A flag indicating if we are to decode bits or bytes.
+// remaining: The size of the capture buffer are remaining.
+// nbits: Nr. of data bits we expect.
+// hdrmark: Nr. of uSeconds for the expected header mark signal.
+// hdrspace: Nr. of uSeconds for the expected header space signal.
+// onemark: Nr. of uSeconds in an expected mark signal for a '1' bit.
+// onespace: Nr. of uSeconds in an expected space signal for a '1' bit.
+// zeromark: Nr. of uSeconds in an expected mark signal for a '0' bit.
+// zerospace: Nr. of uSeconds in an expected space signal for a '0' bit.
+// footermark: Nr. of uSeconds for the expected footer mark signal.
+// footerspace: Nr. of uSeconds for the expected footer space/gap signal.
+// atleast: Is the match on the footerspace a matchAtLeast or matchSpace?
+// tolerance: Percentage error margin to allow. (Def: kUseDefTol)
+// excess: Nr. of useconds. (Def: kMarkExcess)
+// MSBfirst: Bit order to save the data in. (Def: true)
+// Returns:
+// A uint16_t: If successful, how many buffer entries were used. Otherwise 0.
+uint16_t IRrecv::_matchGeneric(volatile uint16_t *data_ptr,
+ uint64_t *result_bits_ptr,
+ uint8_t *result_bytes_ptr,
+ const bool use_bits,
+ const uint16_t remaining,
+ const uint16_t nbits,
+ const uint16_t hdrmark,
+ const uint32_t hdrspace,
+ const uint16_t onemark,
+ const uint32_t onespace,
+ const uint16_t zeromark,
+ const uint32_t zerospace,
+ const uint16_t footermark,
+ const uint32_t footerspace,
+ const bool atleast,
+ const uint8_t tolerance,
+ const int16_t excess,
+ const bool MSBfirst) {
+ // If we are expecting byte sizes, check it's a factor of 8 or fail.
+ if (!use_bits && nbits % 8 != 0) return 0;
+ // Calculate how much remaining buffer is required.
+ uint16_t min_remaining = nbits * 2;
+
+ if (hdrmark) min_remaining++;
+ if (hdrspace) min_remaining++;
+ if (footermark) min_remaining++;
+ // Don't need to extend for footerspace because it could be the end of message
+
+ // Check if there is enough capture buffer to possibly have the message.
+ if (remaining < min_remaining) return 0; // Nope, so abort.
+ uint16_t offset = 0;
+
+ // Header
+ if (hdrmark && !matchMark(*(data_ptr + offset++), hdrmark, tolerance, excess))
+ return 0;
+ if (hdrspace && !matchSpace(*(data_ptr + offset++), hdrspace, tolerance,
+ excess))
+ return 0;
+
+ // Data
+ if (use_bits) { // Bits.
+ match_result_t result = IRrecv::matchData(data_ptr + offset, nbits,
+ onemark, onespace,
+ zeromark, zerospace, tolerance,
+ excess, MSBfirst);
+ if (!result.success) return 0;
+ *result_bits_ptr = result.data;
+ offset += result.used;
+ } else { // bytes
+ uint16_t data_used = IRrecv::matchBytes(data_ptr + offset, result_bytes_ptr,
+ remaining - offset, nbits / 8,
+ onemark, onespace,
+ zeromark, zerospace, tolerance,
+ excess, MSBfirst);
+ if (!data_used) return 0;
+ offset += data_used;
+ }
+ // Footer
+ if (footermark && !matchMark(*(data_ptr + offset++), footermark, tolerance,
+ excess))
+ return 0;
+ // If we have something still to match & haven't reached the end of the buffer
+ if (footerspace && offset < remaining) {
+ if (atleast) {
+ if (!matchAtLeast(*(data_ptr + offset), footerspace, tolerance, excess))
+ return 0;
+ } else {
+ if (!matchSpace(*(data_ptr + offset), footerspace, tolerance, excess))
+ return 0;
+ }
+ offset++;
+ }
+ return offset;
+}
+
+// Match & decode a generic/typical <= 64bit IR message.
+// The data is stored at result_ptr.
+// Values of 0 for hdrmark, hdrspace, footermark, or footerspace mean skip
+// that requirement.
+//
+// Args:
+// data_ptr: A pointer to where we are at in the capture buffer.
+// result_ptr: A pointer to where to start storing the bits we decoded.
+// remaining: The size of the capture buffer are remaining.
+// nbits: Nr. of data bits we expect.
+// hdrmark: Nr. of uSeconds for the expected header mark signal.
+// hdrspace: Nr. of uSeconds for the expected header space signal.
+// onemark: Nr. of uSeconds in an expected mark signal for a '1' bit.
+// onespace: Nr. of uSeconds in an expected space signal for a '1' bit.
+// zeromark: Nr. of uSeconds in an expected mark signal for a '0' bit.
+// zerospace: Nr. of uSeconds in an expected space signal for a '0' bit.
+// footermark: Nr. of uSeconds for the expected footer mark signal.
+// footerspace: Nr. of uSeconds for the expected footer space/gap signal.
+// atleast: Is the match on the footerspace a matchAtLeast or matchSpace?
+// tolerance: Percentage error margin to allow. (Def: kUseDefTol)
+// excess: Nr. of useconds. (Def: kMarkExcess)
+// MSBfirst: Bit order to save the data in. (Def: true)
+// Returns:
+// A uint16_t: If successful, how many buffer entries were used. Otherwise 0.
+uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
+ uint64_t *result_ptr,
+ const uint16_t remaining,
+ const uint16_t nbits,
+ const uint16_t hdrmark,
+ const uint32_t hdrspace,
+ const uint16_t onemark,
+ const uint32_t onespace,
+ const uint16_t zeromark,
+ const uint32_t zerospace,
+ const uint16_t footermark,
+ const uint32_t footerspace,
+ const bool atleast,
+ const uint8_t tolerance,
+ const int16_t excess,
+ const bool MSBfirst) {
+ return _matchGeneric(data_ptr, result_ptr, NULL, true, remaining, nbits,
+ hdrmark, hdrspace, onemark, onespace,
+ zeromark, zerospace, footermark, footerspace, atleast,
+ tolerance, excess, MSBfirst);
+}
+
+// Match & decode a generic/typical > 64bit IR message.
+// The bytes are stored at result_ptr. The first byte in the result equates to
+// the first byte encountered, and so on.
+// Values of 0 for hdrmark, hdrspace, footermark, or footerspace mean skip
+// that requirement.
+//
+// Args:
+// data_ptr: A pointer to where we are at in the capture buffer.
+// result_ptr: A pointer to where to start storing the bytes we decoded.
+// remaining: The size of the capture buffer are remaining.
+// nbits: Nr. of data bits we expect.
+// hdrmark: Nr. of uSeconds for the expected header mark signal.
+// hdrspace: Nr. of uSeconds for the expected header space signal.
+// onemark: Nr. of uSeconds in an expected mark signal for a '1' bit.
+// onespace: Nr. of uSeconds in an expected space signal for a '1' bit.
+// zeromark: Nr. of uSeconds in an expected mark signal for a '0' bit.
+// zerospace: Nr. of uSeconds in an expected space signal for a '0' bit.
+// footermark: Nr. of uSeconds for the expected footer mark signal.
+// footerspace: Nr. of uSeconds for the expected footer space/gap signal.
+// atleast: Is the match on the footerspace a matchAtLeast or matchSpace?
+// tolerance: Percentage error margin to allow. (Def: kUseDefTol)
+// excess: Nr. of useconds. (Def: kMarkExcess)
+// MSBfirst: Bit order to save the data in. (Def: true)
+// Returns:
+// A uint16_t: If successful, how many buffer entries were used. Otherwise 0.
+uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
+ uint8_t *result_ptr,
+ const uint16_t remaining,
+ const uint16_t nbits,
+ const uint16_t hdrmark,
+ const uint32_t hdrspace,
+ const uint16_t onemark,
+ const uint32_t onespace,
+ const uint16_t zeromark,
+ const uint32_t zerospace,
+ const uint16_t footermark,
+ const uint32_t footerspace,
+ const bool atleast,
+ const uint8_t tolerance,
+ const int16_t excess,
+ const bool MSBfirst) {
+ return _matchGeneric(data_ptr, NULL, result_ptr, false, remaining, nbits,
+ hdrmark, hdrspace, onemark, onespace,
+ zeromark, zerospace, footermark, footerspace, atleast,
+ tolerance, excess, MSBfirst);
+}
// End of IRrecv class -------------------
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRrecv.h b/lib/IRremoteESP8266-2.6.5/src/IRrecv.h
similarity index 54%
rename from lib/IRremoteESP8266-2.6.0/src/IRrecv.h
rename to lib/IRremoteESP8266-2.6.5/src/IRrecv.h
index 0659f093e..72c168269 100644
--- a/lib/IRremoteESP8266-2.6.0/src/IRrecv.h
+++ b/lib/IRremoteESP8266-2.6.5/src/IRrecv.h
@@ -32,8 +32,9 @@ const uint8_t kIdleState = 2;
const uint8_t kMarkState = 3;
const uint8_t kSpaceState = 4;
const uint8_t kStopState = 5;
-const uint8_t kTolerance = 25; // default percent tolerance in measurements.
-const uint16_t kRawTick = 2; // Capture tick to uSec factor.
+const uint8_t kTolerance = 25; // default percent tolerance in measurements.
+const uint8_t kUseDefTol = 255; // Indicate to use the class default tolerance.
+const uint16_t kRawTick = 2; // Capture tick to uSec factor.
#define RAWTICK kRawTick // Deprecated. For legacy user code support only.
// How long (ms) before we give up wait for more data?
// Don't exceed kMaxTimeoutMs without a good reason.
@@ -51,6 +52,9 @@ const uint16_t kMaxTimeoutMs = kRawTick * (UINT16_MAX / MS_TO_USEC(1));
const uint32_t kFnvPrime32 = 16777619UL;
const uint32_t kFnvBasis32 = 2166136261UL;
+// Which of the ESP32 timers to use by default. (0-3)
+const uint8_t kDefaultESP32Timer = 3;
+
#if DECODE_AC
// Hitachi AC is the current largest state size.
const uint16_t kStateSizeMax = kHitachiAc2StateLength;
@@ -108,54 +112,123 @@ class decode_results {
// main class for receiving IR
class IRrecv {
public:
- explicit IRrecv(uint16_t recvpin, uint16_t bufsize = kRawBuf,
- uint8_t timeout = kTimeoutMs,
- bool save_buffer = false); // Constructor
- ~IRrecv(); // Destructor
+#if defined(ESP32)
+ explicit IRrecv(const uint16_t recvpin, const uint16_t bufsize = kRawBuf,
+ const uint8_t timeout = kTimeoutMs,
+ const bool save_buffer = false,
+ const uint8_t timer_num = kDefaultESP32Timer); // Constructor
+#else // ESP32
+ explicit IRrecv(const uint16_t recvpin, const uint16_t bufsize = kRawBuf,
+ const uint8_t timeout = kTimeoutMs,
+ const bool save_buffer = false); // Constructor
+#endif // ESP32
+ ~IRrecv(void); // Destructor
+ void setTolerance(const uint8_t percent = kTolerance);
+ uint8_t getTolerance(void);
bool decode(decode_results *results, irparams_t *save = NULL);
- void enableIRIn();
- void disableIRIn();
- void resume();
- uint16_t getBufSize();
+ void enableIRIn(const bool pullup = false);
+ void disableIRIn(void);
+ void resume(void);
+ uint16_t getBufSize(void);
#if DECODE_HASH
- void setUnknownThreshold(uint16_t length);
+ void setUnknownThreshold(const uint16_t length);
#endif
- static bool match(uint32_t measured, uint32_t desired,
- uint8_t tolerance = kTolerance, uint16_t delta = 0);
- static bool matchMark(uint32_t measured, uint32_t desired,
- uint8_t tolerance = kTolerance,
- int16_t excess = kMarkExcess);
- static bool matchSpace(uint32_t measured, uint32_t desired,
- uint8_t tolerance = kTolerance,
- int16_t excess = kMarkExcess);
+ bool match(const uint32_t measured, const uint32_t desired,
+ const uint8_t tolerance = kUseDefTol,
+ const uint16_t delta = 0);
+ bool matchMark(const uint32_t measured, const uint32_t desired,
+ const uint8_t tolerance = kUseDefTol,
+ const int16_t excess = kMarkExcess);
+ bool matchSpace(const uint32_t measured, const uint32_t desired,
+ const uint8_t tolerance = kUseDefTol,
+ const int16_t excess = kMarkExcess);
#ifndef UNIT_TEST
private:
#endif
irparams_t *irparams_save;
+ uint8_t _tolerance;
+#if defined(ESP32)
+ uint8_t _timer_num;
+#endif // defined(ESP32)
#if DECODE_HASH
- uint16_t unknown_threshold;
+ uint16_t _unknown_threshold;
#endif
// These are called by decode
+ uint8_t _validTolerance(const uint8_t percentage);
void copyIrParams(volatile irparams_t *src, irparams_t *dst);
- int16_t compare(uint16_t oldval, uint16_t newval);
- static uint32_t ticksLow(uint32_t usecs, uint8_t tolerance = kTolerance,
- uint16_t delta = 0);
- static uint32_t ticksHigh(uint32_t usecs, uint8_t tolerance = kTolerance,
- uint16_t delta = 0);
- bool matchAtLeast(uint32_t measured, uint32_t desired,
- uint8_t tolerance = kTolerance, uint16_t delta = 0);
+ uint16_t compare(const uint16_t oldval, const uint16_t newval);
+ uint32_t ticksLow(const uint32_t usecs,
+ const uint8_t tolerance = kUseDefTol,
+ const uint16_t delta = 0);
+ uint32_t ticksHigh(const uint32_t usecs,
+ const uint8_t tolerance = kUseDefTol,
+ const uint16_t delta = 0);
+ bool matchAtLeast(const uint32_t measured, const uint32_t desired,
+ const uint8_t tolerance = kUseDefTol,
+ const uint16_t delta = 0);
+ uint16_t _matchGeneric(volatile uint16_t *data_ptr,
+ uint64_t *result_bits_ptr,
+ uint8_t *result_ptr,
+ const bool use_bits,
+ const uint16_t remaining,
+ const uint16_t required,
+ const uint16_t hdrmark,
+ const uint32_t hdrspace,
+ const uint16_t onemark,
+ const uint32_t onespace,
+ const uint16_t zeromark,
+ const uint32_t zerospace,
+ const uint16_t footermark,
+ const uint32_t footerspace,
+ const bool atleast = false,
+ const uint8_t tolerance = kUseDefTol,
+ const int16_t excess = kMarkExcess,
+ const bool MSBfirst = true);
match_result_t matchData(volatile uint16_t *data_ptr, const uint16_t nbits,
const uint16_t onemark, const uint32_t onespace,
const uint16_t zeromark, const uint32_t zerospace,
- const uint8_t tolerance = kTolerance,
+ const uint8_t tolerance = kUseDefTol,
const int16_t excess = kMarkExcess,
const bool MSBfirst = true);
+ uint16_t matchBytes(volatile uint16_t *data_ptr, uint8_t *result_ptr,
+ const uint16_t remaining, const uint16_t nbytes,
+ const uint16_t onemark, const uint32_t onespace,
+ const uint16_t zeromark, const uint32_t zerospace,
+ const uint8_t tolerance = kUseDefTol,
+ const int16_t excess = kMarkExcess,
+ const bool MSBfirst = true);
+ uint16_t matchGeneric(volatile uint16_t *data_ptr,
+ uint64_t *result_ptr,
+ const uint16_t remaining, const uint16_t nbits,
+ const uint16_t hdrmark, const uint32_t hdrspace,
+ const uint16_t onemark, const uint32_t onespace,
+ const uint16_t zeromark, const uint32_t zerospace,
+ const uint16_t footermark, const uint32_t footerspace,
+ const bool atleast = false,
+ const uint8_t tolerance = kUseDefTol,
+ const int16_t excess = kMarkExcess,
+ const bool MSBfirst = true);
+ uint16_t matchGeneric(volatile uint16_t *data_ptr, uint8_t *result_ptr,
+ const uint16_t remaining, const uint16_t nbits,
+ const uint16_t hdrmark, const uint32_t hdrspace,
+ const uint16_t onemark, const uint32_t onespace,
+ const uint16_t zeromark, const uint32_t zerospace,
+ const uint16_t footermark,
+ const uint32_t footerspace,
+ const bool atleast = false,
+ const uint8_t tolerance = kUseDefTol,
+ const int16_t excess = kMarkExcess,
+ const bool MSBfirst = true);
bool decodeHash(decode_results *results);
#if (DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || SEND_SANYO)
bool decodeNEC(decode_results *results, uint16_t nbits = kNECBits,
bool strict = true);
#endif
+#if DECODE_ARGO
+ bool decodeArgo(decode_results *results, const uint16_t nbits = kArgoBits,
+ const bool strict = true);
+#endif // DECODE_ARGO
#if DECODE_SONY
bool decodeSony(decode_results *results, uint16_t nbits = kSonyMinBits,
bool strict = false);
@@ -187,7 +260,7 @@ class IRrecv {
#endif
#if (DECODE_RC5 || DECODE_R6 || DECODE_LASERTAG || DECODE_MWM)
int16_t getRClevel(decode_results *results, uint16_t *offset, uint16_t *used,
- uint16_t bitTime, uint8_t tolerance = kTolerance,
+ uint16_t bitTime, uint8_t tolerance = kUseDefTol,
int16_t excess = kMarkExcess, uint16_t delta = 0,
uint8_t maxwidth = 3);
#endif
@@ -204,21 +277,27 @@ class IRrecv {
bool strict = false);
#endif
#if (DECODE_PANASONIC || DECODE_DENON)
- bool decodePanasonic(decode_results *results, uint16_t nbits = kPanasonicBits,
- bool strict = false,
- uint32_t manufacturer = kPanasonicManufacturer);
+ bool decodePanasonic(decode_results *results,
+ const uint16_t nbits = kPanasonicBits,
+ const bool strict = false,
+ const uint32_t manufacturer = kPanasonicManufacturer);
#endif
#if DECODE_LG
bool decodeLG(decode_results *results, uint16_t nbits = kLgBits,
bool strict = false);
#endif
+#if DECODE_INAX
+ bool decodeInax(decode_results *results, const uint16_t nbits = kInaxBits,
+ const bool strict = true);
+#endif // DECODE_INAX
#if DECODE_JVC
bool decodeJVC(decode_results *results, uint16_t nbits = kJvcBits,
bool strict = true);
#endif
#if DECODE_SAMSUNG
- bool decodeSAMSUNG(decode_results *results, uint16_t nbits = kSamsungBits,
- bool strict = true);
+ bool decodeSAMSUNG(decode_results *results,
+ const uint16_t nbits = kSamsungBits,
+ const bool strict = true);
#endif
#if DECODE_SAMSUNG
bool decodeSamsung36(decode_results *results,
@@ -226,8 +305,9 @@ class IRrecv {
const bool strict = true);
#endif
#if DECODE_SAMSUNG_AC
- bool decodeSamsungAC(decode_results *results, uint16_t nbits = kSamsungAcBits,
- bool strict = true);
+ bool decodeSamsungAC(decode_results *results,
+ const uint16_t nbits = kSamsungAcBits,
+ const bool strict = true);
#endif
#if DECODE_WHYNTER
bool decodeWhynter(decode_results *results, uint16_t nbits = kWhynterBits,
@@ -238,7 +318,7 @@ class IRrecv {
bool strict = true);
#endif
#if DECODE_DENON
- bool decodeDenon(decode_results *results, uint16_t nbits = DENON_BITS,
+ bool decodeDenon(decode_results *results, uint16_t nbits = kDenonBits,
bool strict = true);
#endif
#if DECODE_DISH
@@ -246,8 +326,13 @@ class IRrecv {
bool strict = true);
#endif
#if (DECODE_SHARP || DECODE_DENON)
- bool decodeSharp(decode_results *results, uint16_t nbits = kSharpBits,
- bool strict = true, bool expansion = true);
+ bool decodeSharp(decode_results *results, const uint16_t nbits = kSharpBits,
+ const bool strict = true, const bool expansion = true);
+#endif
+#if DECODE_SHARP_AC
+ bool decodeSharpAc(decode_results *results,
+ const uint16_t nbits = kSharpAcBits,
+ const bool strict = true);
#endif
#if DECODE_AIWA_RC_T501
bool decodeAiwaRCT501(decode_results *results,
@@ -269,6 +354,26 @@ class IRrecv {
bool decodeDaikin(decode_results *results, const uint16_t nbits = kDaikinBits,
const bool strict = true);
#endif
+#if DECODE_DAIKIN128
+ bool decodeDaikin128(decode_results *results,
+ const uint16_t nbits = kDaikin128Bits,
+ const bool strict = true);
+#endif // DECODE_DAIKIN128
+#if DECODE_DAIKIN152
+ bool decodeDaikin152(decode_results *results,
+ const uint16_t nbits = kDaikin152Bits,
+ const bool strict = true);
+#endif // DECODE_DAIKIN152
+#if DECODE_DAIKIN160
+ bool decodeDaikin160(decode_results *results,
+ const uint16_t nbits = kDaikin160Bits,
+ const bool strict = true);
+#endif // DECODE_DAIKIN160
+#if DECODE_DAIKIN176
+ bool decodeDaikin176(decode_results *results,
+ const uint16_t nbits = kDaikin176Bits,
+ const bool strict = true);
+#endif // DECODE_DAIKIN176
#if DECODE_DAIKIN2
bool decodeDaikin2(decode_results *results, uint16_t nbits = kDaikin2Bits,
bool strict = true);
@@ -280,8 +385,13 @@ class IRrecv {
#endif
#if DECODE_TOSHIBA_AC
bool decodeToshibaAC(decode_results *results,
- uint16_t nbytes = kToshibaACBits, bool strict = true);
+ const uint16_t nbytes = kToshibaACBits,
+ const bool strict = true);
#endif
+#if DECODE_TROTEC
+ bool decodeTrotec(decode_results *results, const uint16_t nbits = kTrotecBits,
+ const bool strict = true);
+#endif // DECODE_TROTEC
#if DECODE_MIDEA
bool decodeMidea(decode_results *results, uint16_t nbits = kMideaBits,
bool strict = true);
@@ -298,6 +408,11 @@ class IRrecv {
bool decodeCarrierAC(decode_results *results, uint16_t nbits = kCarrierAcBits,
bool strict = true);
#endif
+#if DECODE_GOODWEATHER
+ bool decodeGoodweather(decode_results *results,
+ const uint16_t nbits = kGoodweatherBits,
+ const bool strict = true);
+#endif // DECODE_GOODWEATHER
#if DECODE_GREE
bool decodeGree(decode_results *results, uint16_t nbits = kGreeBits,
bool strict = true);
@@ -312,12 +427,14 @@ class IRrecv {
bool strict = true);
#endif
#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC2)
- bool decodeHitachiAC(decode_results *results, uint16_t nbits = kHitachiAcBits,
- bool strict = true);
+ bool decodeHitachiAC(decode_results *results,
+ const uint16_t nbits = kHitachiAcBits,
+ const bool strict = true);
#endif
#if DECODE_HITACHI_AC1
bool decodeHitachiAC1(decode_results *results,
- uint16_t nbits = kHitachiAc1Bits, bool strict = true);
+ const uint16_t nbits = kHitachiAc1Bits,
+ const bool strict = true);
#endif
#if DECODE_GICABLE
bool decodeGICable(decode_results *results, uint16_t nbits = kGicableBits,
@@ -325,7 +442,8 @@ class IRrecv {
#endif
#if DECODE_WHIRLPOOL_AC
bool decodeWhirlpoolAC(decode_results *results,
- uint16_t nbits = kWhirlpoolAcBits, bool strict = true);
+ const uint16_t nbits = kWhirlpoolAcBits,
+ const bool strict = true);
#endif
#if DECODE_LUTRON
bool decodeLutron(decode_results *results, uint16_t nbits = kLutronBits,
@@ -337,7 +455,8 @@ class IRrecv {
#endif
#if DECODE_PANASONIC_AC
bool decodePanasonicAC(decode_results *results,
- uint16_t nbits = kPanasonicAcBits, bool strict = true);
+ const uint16_t nbits = kPanasonicAcBits,
+ const bool strict = true);
#endif
#if DECODE_PIONEER
bool decodePioneer(decode_results *results,
@@ -349,21 +468,33 @@ class IRrecv {
bool strict = true);
#endif
#if DECODE_VESTEL_AC
- bool decodeVestelAc(decode_results *results, uint16_t nbits = kVestelAcBits,
- bool strict = true);
+ bool decodeVestelAc(decode_results *results,
+ const uint16_t nbits = kVestelAcBits,
+ const bool strict = true);
#endif
#if DECODE_TCL112AC
- bool decodeTcl112Ac(decode_results *results, uint16_t nbits = kTcl112AcBits,
- bool strict = true);
+ bool decodeTcl112Ac(decode_results *results,
+ const uint16_t nbits = kTcl112AcBits,
+ const bool strict = true);
#endif
#if DECODE_TECO
- bool decodeTeco(decode_results *results, uint16_t nbits = kTecoBits,
- bool strict = false);
+ bool decodeTeco(decode_results *results, const uint16_t nbits = kTecoBits,
+ const bool strict = false);
#endif
#if DECODE_LEGOPF
bool decodeLegoPf(decode_results *results, const uint16_t nbits = kLegoPfBits,
const bool strict = true);
#endif
+#if DECODE_NEOCLIMA
+bool decodeNeoclima(decode_results *results,
+ const uint16_t nbits = kNeoclimaBits,
+ const bool strict = true);
+#endif // DECODE_NEOCLIMA
+#if DECODE_AMCOR
+bool decodeAmcor(decode_results *results,
+ const uint16_t nbits = kAmcorBits,
+ const bool strict = true);
+#endif // DECODE_AMCOR
};
#endif // IRRECV_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.6.5/src/IRremoteESP8266.h
similarity index 79%
rename from lib/IRremoteESP8266-2.6.0/src/IRremoteESP8266.h
rename to lib/IRremoteESP8266-2.6.5/src/IRremoteESP8266.h
index b532cb1c0..0e1f00fa3 100644
--- a/lib/IRremoteESP8266-2.6.0/src/IRremoteESP8266.h
+++ b/lib/IRremoteESP8266-2.6.5/src/IRremoteESP8266.h
@@ -26,7 +26,7 @@
* DISH decode by marcosamarinho
* Gree Heatpump sending added by Ville SkyttƤ (scop)
* (derived from https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp)
- * Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for sending IR code on ESP8266
+ * Updated by markszabo (https://github.com/crankyoldgit/IRremoteESP8266) for sending IR code on ESP8266
* Updated by Sebastien Warin (http://sebastien.warin.fr) for receiving IR code on ESP8266
*
* Updated by sillyfrog for Daikin, adopted from
@@ -47,16 +47,18 @@
#include
#ifdef UNIT_TEST
#include
-#endif
+#include
+#endif // UNIT_TEST
// Library Version
-#define _IRREMOTEESP8266_VERSION_ "2.6.0"
+#define _IRREMOTEESP8266_VERSION_ "2.6.5"
// Supported IR protocols
// Each protocol you include costs memory and, during decode, costs time
// Disable (set to false) all the protocols you do not need/want!
// The Air Conditioner protocols are the most expensive memory-wise.
//
-/*
+
+#ifdef USE_IR_REMOTE_FULL // full IR protocols
#define DECODE_HASH true // Semi-unique code for unknown messages
#define SEND_RAW true
@@ -118,6 +120,9 @@
#define DECODE_SHARP true
#define SEND_SHARP true
+#define DECODE_SHARP_AC true
+#define SEND_SHARP_AC true
+
#define DECODE_DENON true
#define SEND_DENON true
@@ -130,6 +135,9 @@
#define DECODE_FUJITSU_AC true
#define SEND_FUJITSU_AC true
+#define DECODE_INAX true
+#define SEND_INAX true
+
#define DECODE_DAIKIN true
#define SEND_DAIKIN true
@@ -139,16 +147,19 @@
#define DECODE_GLOBALCACHE false // Not written.
#define SEND_GLOBALCACHE true
+#define DECODE_GOODWEATHER true
+#define SEND_GOODWEATHER true
+
#define DECODE_GREE true
#define SEND_GREE true
#define DECODE_PRONTO false // Not written.
#define SEND_PRONTO true
-#define DECODE_ARGO false // Not written.
+#define DECODE_ARGO true // Experimental
#define SEND_ARGO true
-#define DECODE_TROTEC false // Not implemented.
+#define DECODE_TROTEC true
#define SEND_TROTEC true
#define DECODE_NIKAI true
@@ -225,7 +236,26 @@
#define DECODE_DAIKIN216 true
#define SEND_DAIKIN216 true
-*/
+
+#define DECODE_DAIKIN160 true
+#define SEND_DAIKIN160 true
+
+#define DECODE_NEOCLIMA true
+#define SEND_NEOCLIMA true
+
+#define DECODE_DAIKIN176 true
+#define SEND_DAIKIN176 true
+
+#define DECODE_DAIKIN128 true
+#define SEND_DAIKIN128 true
+
+#define DECODE_AMCOR true
+#define SEND_AMCOR true
+
+#define DECODE_DAIKIN152 true
+#define SEND_DAIKIN152 true
+
+#else // defined(FIRMWARE_IR) || defined(FIRMWARE_IR_CUSTOM) // full IR protocols
// Tasmota supported protocols (less protocols is less code size)
#define DECODE_HASH true // Semi-unique code for unknown messages
@@ -236,7 +266,7 @@
#define SEND_NEC true
#define DECODE_SHERWOOD false // Doesn't exist. Actually is DECODE_NEC
-#define SEND_SHERWOOD false
+#define SEND_SHERWOOD true
#define DECODE_RC5 true
#define SEND_RC5 true
@@ -245,7 +275,7 @@
#define SEND_RC6 true
#define DECODE_RCMM false
-#define SEND_RCMM false
+#define SEND_RCMM true
#define DECODE_SONY true
#define SEND_SONY true
@@ -260,40 +290,43 @@
#define SEND_SAMSUNG true
#define DECODE_SAMSUNG36 false
-#define SEND_SAMSUNG36 false
+#define SEND_SAMSUNG36 true
#define DECODE_SAMSUNG_AC false
-#define SEND_SAMSUNG_AC false
+#define SEND_SAMSUNG_AC true
#define DECODE_WHYNTER false
-#define SEND_WHYNTER false
+#define SEND_WHYNTER true
#define DECODE_AIWA_RC_T501 false
-#define SEND_AIWA_RC_T501 false
+#define SEND_AIWA_RC_T501 true
#define DECODE_LG true
#define SEND_LG true
#define DECODE_SANYO false
-#define SEND_SANYO false
+#define SEND_SANYO true
#define DECODE_MITSUBISHI false
-#define SEND_MITSUBISHI false
+#define SEND_MITSUBISHI true
#define DECODE_MITSUBISHI2 false
-#define SEND_MITSUBISHI2 false
+#define SEND_MITSUBISHI2 true
#define DECODE_DISH false
#define SEND_DISH true
#define DECODE_SHARP false
-#define SEND_SHARP false
+#define SEND_SHARP true
+
+#define DECODE_SHARP_AC false
+#define SEND_SHARP_AC true
#define DECODE_DENON false
-#define SEND_DENON false
+#define SEND_DENON true
#define DECODE_KELVINATOR false
-#define SEND_KELVINATOR false
+#define SEND_KELVINATOR true
#define DECODE_MITSUBISHI_AC false // Beta.
#define SEND_MITSUBISHI_AC true
@@ -301,101 +334,121 @@
#define DECODE_FUJITSU_AC false
#define SEND_FUJITSU_AC true
+#define DECODE_INAX false
+#define SEND_INAX true
+
#define DECODE_DAIKIN false
-#define SEND_DAIKIN false
+#define SEND_DAIKIN true
#define DECODE_COOLIX false
-#define SEND_COOLIX false
+#define SEND_COOLIX true
#define DECODE_GLOBALCACHE false // Not written.
-#define SEND_GLOBALCACHE false
+#define SEND_GLOBALCACHE true
+
+#define DECODE_GOODWEATHER false
+#define SEND_GOODWEATHER true
#define DECODE_GREE false
-#define SEND_GREE false
+#define SEND_GREE true
#define DECODE_PRONTO false // Not written.
-#define SEND_PRONTO false
+#define SEND_PRONTO true
-#define DECODE_ARGO false // Not written.
-#define SEND_ARGO false
+#define DECODE_ARGO false // Experimental
+#define SEND_ARGO true
-#define DECODE_TROTEC false // Not implemented.
-#define SEND_TROTEC false
+#define DECODE_TROTEC false
+#define SEND_TROTEC true
#define DECODE_NIKAI false
-#define SEND_NIKAI false
+#define SEND_NIKAI true
#define DECODE_TOSHIBA_AC false
-#define SEND_TOSHIBA_AC false
+#define SEND_TOSHIBA_AC true
#define DECODE_MAGIQUEST false
-#define SEND_MAGIQUEST false
+#define SEND_MAGIQUEST true
#define DECODE_MIDEA false
-#define SEND_MIDEA false
+#define SEND_MIDEA true
#define DECODE_LASERTAG false
-#define SEND_LASERTAG false
+#define SEND_LASERTAG true
#define DECODE_CARRIER_AC false
-#define SEND_CARRIER_AC false
+#define SEND_CARRIER_AC true
#define DECODE_HAIER_AC false
-#define SEND_HAIER_AC false
+#define SEND_HAIER_AC true
#define DECODE_HITACHI_AC false
-#define SEND_HITACHI_AC false
+#define SEND_HITACHI_AC true
#define DECODE_HITACHI_AC1 false
-#define SEND_HITACHI_AC1 false
+#define SEND_HITACHI_AC1 true
#define DECODE_HITACHI_AC2 false
-#define SEND_HITACHI_AC2 false
+#define SEND_HITACHI_AC2 true
#define DECODE_GICABLE false
-#define SEND_GICABLE false
+#define SEND_GICABLE true
#define DECODE_HAIER_AC_YRW02 false
-#define SEND_HAIER_AC_YRW02 false
+#define SEND_HAIER_AC_YRW02 true
#define DECODE_WHIRLPOOL_AC false
-#define SEND_WHIRLPOOL_AC false
+#define SEND_WHIRLPOOL_AC true
#define DECODE_LUTRON false
-#define SEND_LUTRON false
+#define SEND_LUTRON true
#define DECODE_ELECTRA_AC false
-#define SEND_ELECTRA_AC false
+#define SEND_ELECTRA_AC true
#define DECODE_PANASONIC_AC false
-#define SEND_PANASONIC_AC false
+#define SEND_PANASONIC_AC true
#define DECODE_MWM false
-#define SEND_MWM false
+#define SEND_MWM true
#define DECODE_PIONEER false
-#define SEND_PIONEER false
+#define SEND_PIONEER true
#define DECODE_DAIKIN2 false
-#define SEND_DAIKIN2 false
+#define SEND_DAIKIN2 true
#define DECODE_VESTEL_AC false
-#define SEND_VESTEL_AC false
+#define SEND_VESTEL_AC true
#define DECODE_TECO false
-#define SEND_TECO false
+#define SEND_TECO true
#define DECODE_TCL112AC false
-#define SEND_TCL112AC false
+#define SEND_TCL112AC true
#define DECODE_LEGOPF false
-#define SEND_LEGOPF false
+#define SEND_LEGOPF true
#define DECODE_MITSUBISHIHEAVY false
-#define SEND_MITSUBISHIHEAVY false
+#define SEND_MITSUBISHIHEAVY true
#define DECODE_DAIKIN216 false
-#define SEND_DAIKIN216 false
+#define SEND_DAIKIN216 true
+
+#define DECODE_DAIKIN160 false
+#define SEND_DAIKIN160 true
+
+#define DECODE_NEOCLIMA false
+#define SEND_NEOCLIMA true
+
+#define DECODE_DAIKIN176 false
+#define SEND_DAIKIN176 true
+
+#define DECODE_DAIKIN128 false
+#define SEND_DAIKIN128 true
+
+#endif // defined(FIRMWARE_IR) || defined(FIRMWARE_IR_CUSTOM) // full IR protocols
#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
@@ -404,7 +457,9 @@
DECODE_WHIRLPOOL_AC || DECODE_SAMSUNG_AC || DECODE_ELECTRA_AC || \
DECODE_PANASONIC_AC || DECODE_MWM || DECODE_DAIKIN2 || \
DECODE_VESTEL_AC || DECODE_TCL112AC || DECODE_MITSUBISHIHEAVY || \
- DECODE_DAIKIN216)
+ DECODE_DAIKIN216 || DECODE_SHARP_AC || DECODE_DAIKIN160 || \
+ DECODE_NEOCLIMA || DECODE_DAIKIN176 || DECODE_DAIKIN128 || \
+ DECODE_AMCOR || DECODE_DAIKIN152)
#define DECODE_AC true // We need some common infrastructure for decoding A/Cs.
#else
#define DECODE_AC false // We don't need that infrastructure.
@@ -413,7 +468,7 @@
// Use millisecond 'delay()' calls where we can to avoid tripping the WDT.
// Note: If you plan to send IR messages in the callbacks of the AsyncWebserver
// library, you need to set ALLOW_DELAY_CALLS to false.
-// Ref: https://github.com/markszabo/IRremoteESP8266/issues/430
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/430
#define ALLOW_DELAY_CALLS true
/*
@@ -485,8 +540,17 @@ enum decode_type_t {
MITSUBISHI_HEAVY_88,
MITSUBISHI_HEAVY_152, // 60
DAIKIN216,
+ SHARP_AC,
+ GOODWEATHER,
+ INAX,
+ DAIKIN160, // 65
+ NEOCLIMA,
+ DAIKIN176,
+ DAIKIN128,
+ AMCOR,
+ DAIKIN152, // 70
// Add new entries before this one, and update it to point to the last entry.
- kLastDecodeType = DAIKIN216,
+ kLastDecodeType = DAIKIN152,
};
// Message lengths & required repeat values
@@ -495,10 +559,14 @@ const uint16_t kSingleRepeat = 1;
const uint16_t kAiwaRcT501Bits = 15;
const uint16_t kAiwaRcT501MinRepeats = kSingleRepeat;
+const uint16_t kAmcorStateLength = 8;
+const uint16_t kAmcorBits = kAmcorStateLength * 8;
+const uint16_t kAmcorDefaultRepeat = kSingleRepeat;
const uint16_t kArgoStateLength = 12;
+const uint16_t kArgoBits = kArgoStateLength * 8;
const uint16_t kArgoDefaultRepeat = kNoRepeat;
const uint16_t kCoolixBits = 24;
-const uint16_t kCoolixDefaultRepeat = 1;
+const uint16_t kCoolixDefaultRepeat = kSingleRepeat;
const uint16_t kCarrierAcBits = 32;
const uint16_t kCarrierAcMinRepeat = kNoRepeat;
const uint16_t kDaikinStateLength = 35;
@@ -509,15 +577,29 @@ const uint16_t kDaikinDefaultRepeat = kNoRepeat;
const uint16_t kDaikin2StateLength = 39;
const uint16_t kDaikin2Bits = kDaikin2StateLength * 8;
const uint16_t kDaikin2DefaultRepeat = kNoRepeat;
+const uint16_t kDaikin160StateLength = 20;
+const uint16_t kDaikin160Bits = kDaikin160StateLength * 8;
+const uint16_t kDaikin160DefaultRepeat = kNoRepeat;
+const uint16_t kDaikin128StateLength = 16;
+const uint16_t kDaikin128Bits = kDaikin128StateLength * 8;
+const uint16_t kDaikin128DefaultRepeat = kNoRepeat;
+const uint16_t kDaikin152StateLength = 19;
+const uint16_t kDaikin152Bits = kDaikin152StateLength * 8;
+const uint16_t kDaikin152DefaultRepeat = kNoRepeat;
+const uint16_t kDaikin176StateLength = 22;
+const uint16_t kDaikin176Bits = kDaikin176StateLength * 8;
+const uint16_t kDaikin176DefaultRepeat = kNoRepeat;
const uint16_t kDaikin216StateLength = 27;
const uint16_t kDaikin216Bits = kDaikin216StateLength * 8;
const uint16_t kDaikin216DefaultRepeat = kNoRepeat;
const uint16_t kDenonBits = 15;
+const uint16_t kDenon48Bits = 48;
const uint16_t kDenonLegacyBits = 14;
const uint16_t kDishBits = 16;
const uint16_t kDishMinRepeat = 3;
const uint16_t kElectraAcStateLength = 13;
const uint16_t kElectraAcBits = kElectraAcStateLength * 8;
+const uint16_t kElectraAcMinRepeat = kNoRepeat;
const uint16_t kFujitsuAcMinRepeat = kNoRepeat;
const uint16_t kFujitsuAcStateLength = 16;
const uint16_t kFujitsuAcStateLengthShort = 7;
@@ -525,6 +607,8 @@ const uint16_t kFujitsuAcBits = kFujitsuAcStateLength * 8;
const uint16_t kFujitsuAcMinBits = (kFujitsuAcStateLengthShort - 1) * 8;
const uint16_t kGicableBits = 16;
const uint16_t kGicableMinRepeat = kSingleRepeat;
+const uint16_t kGoodweatherBits = 48;
+const uint16_t kGoodweatherMinRepeat = kNoRepeat;
const uint16_t kGreeStateLength = 8;
const uint16_t kGreeBits = kGreeStateLength * 8;
const uint16_t kGreeDefaultRepeat = kNoRepeat;
@@ -541,6 +625,8 @@ const uint16_t kHitachiAc1StateLength = 13;
const uint16_t kHitachiAc1Bits = kHitachiAc1StateLength * 8;
const uint16_t kHitachiAc2StateLength = 53;
const uint16_t kHitachiAc2Bits = kHitachiAc2StateLength * 8;
+const uint16_t kInaxBits = 24;
+const uint16_t kInaxMinRepeat = kSingleRepeat;
const uint16_t kJvcBits = 16;
const uint16_t kKelvinatorStateLength = 16;
const uint16_t kKelvinatorBits = kKelvinatorStateLength * 8;
@@ -570,6 +656,9 @@ const uint16_t kMitsubishiHeavy152Bits = kMitsubishiHeavy152StateLength * 8;
const uint16_t kMitsubishiHeavy152MinRepeat = kNoRepeat;
const uint16_t kNikaiBits = 24;
const uint16_t kNECBits = 32;
+const uint16_t kNeoclimaStateLength = 12;
+const uint16_t kNeoclimaBits = kNeoclimaStateLength * 8;
+const uint16_t kNeoclimaMinRepeat = kNoRepeat;
const uint16_t kPanasonicBits = 48;
const uint32_t kPanasonicManufacturer = 0x4004;
const uint16_t kPanasonicAcStateLength = 27;
@@ -600,6 +689,9 @@ const uint16_t kSanyoLC7461Bits = (kSanyoLC7461AddressBits +
const uint8_t kSharpAddressBits = 5;
const uint8_t kSharpCommandBits = 8;
const uint16_t kSharpBits = kSharpAddressBits + kSharpCommandBits + 2; // 15
+const uint16_t kSharpAcStateLength = 13;
+const uint16_t kSharpAcBits = kSharpAcStateLength * 8; // 104
+const uint16_t kSharpAcDefaultRepeat = kNoRepeat;
const uint8_t kSherwoodBits = kNECBits;
const uint16_t kSherwoodMinRepeat = kSingleRepeat;
const uint16_t kSony12Bits = 12;
@@ -616,6 +708,7 @@ const uint16_t kToshibaACStateLength = 9;
const uint16_t kToshibaACBits = kToshibaACStateLength * 8;
const uint16_t kToshibaACMinRepeat = kSingleRepeat;
const uint16_t kTrotecStateLength = 9;
+const uint16_t kTrotecBits = kTrotecStateLength * 8;
const uint16_t kTrotecDefaultRepeat = kNoRepeat;
const uint16_t kWhirlpoolAcStateLength = 21;
const uint16_t kWhirlpoolAcBits = kWhirlpoolAcStateLength * 8;
@@ -631,7 +724,7 @@ const uint8_t kVestelAcBits = 56;
#define CARRIER_AC_BITS kCarrierAcBits
#define DAIKIN_COMMAND_LENGTH kDaikinStateLength
#define DENON_BITS kDenonBits
-#define DENON_48_BITS kPanasonicBits
+#define DENON_48_BITS kDenon48Bits
#define DENON_LEGACY_BITS kDenonLegacyBits
#define DISH_BITS kDishBits
#define FUJITSU_AC_MIN_REPEAT kFujitsuAcMinRepeat
@@ -700,9 +793,10 @@ const uint8_t kVestelAcBits = 56;
// Create a no-op F() macro so the code base still compiles outside of the
// Arduino framework. Thus we can safely use the Arduino 'F()' macro through-out
// the code base. That macro stores constants in Flash (PROGMEM) memory.
-// See: https://github.com/markszabo/IRremoteESP8266/issues/667
+// See: https://github.com/crankyoldgit/IRremoteESP8266/issues/667
#define F(x) x
#endif // F
+typedef std::string String;
#endif // UNIT_TEST
#endif // IRREMOTEESP8266_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRsend.cpp b/lib/IRremoteESP8266-2.6.5/src/IRsend.cpp
similarity index 70%
rename from lib/IRremoteESP8266-2.6.0/src/IRsend.cpp
rename to lib/IRremoteESP8266-2.6.5/src/IRsend.cpp
index 22c0c874b..b094fdff5 100644
--- a/lib/IRremoteESP8266-2.6.0/src/IRsend.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/IRsend.cpp
@@ -16,7 +16,7 @@
#include "IRtimer.h"
// Originally from https://github.com/shirriff/Arduino-IRremote/
-// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for
+// Updated by markszabo (https://github.com/crankyoldgit/IRremoteESP8266) for
// sending IR code on ESP8266
// IRsend ----------------------------------------------------------------------
@@ -491,178 +491,341 @@ void IRsend::sendRaw(uint16_t buf[], uint16_t len, uint16_t hz) {
}
#endif // SEND_RAW
+// Get the minimum number of repeats for a given protocol.
+// Args:
+// protocol: Protocol number/type of the message you want to send.
+// Returns:
+// int16_t: The number of repeats required.
+uint16_t IRsend::minRepeats(const decode_type_t protocol) {
+ switch (protocol) {
+ // Single repeats
+ case AIWA_RC_T501:
+ case AMCOR:
+ case COOLIX:
+ case GICABLE:
+ case INAX:
+ case MITSUBISHI:
+ case MITSUBISHI2:
+ case MITSUBISHI_AC:
+ case SHERWOOD:
+ case TOSHIBA_AC:
+ return kSingleRepeat;
+ // Special
+ case DISH:
+ return kDishMinRepeat;
+ case SONY:
+ return kSonyMinRepeat;
+ default:
+ return kNoRepeat;
+ }
+}
+
+// Get the default number of bits for a given protocol.
+// Args:
+// protocol: Protocol number/type you want the default nr. of bits for.
+// Returns:
+// int16_t: The number of bits.
+uint16_t IRsend::defaultBits(const decode_type_t protocol) {
+ switch (protocol) {
+ case RC5:
+ return 12;
+ case LASERTAG:
+ case RC5X:
+ return 13;
+ case AIWA_RC_T501:
+ case DENON:
+ case SHARP:
+ return 15;
+ case DISH:
+ case GICABLE:
+ case JVC:
+ case LEGOPF:
+ case MITSUBISHI:
+ case MITSUBISHI2:
+ return 16;
+ case RC6:
+ case SONY:
+ return 20;
+ case COOLIX:
+ case INAX:
+ case NIKAI:
+ case RCMM:
+ return 24;
+ case LG:
+ case LG2:
+ return 28;
+ case CARRIER_AC:
+ case NEC:
+ case NEC_LIKE:
+ case SAMSUNG:
+ case SHERWOOD:
+ case WHYNTER:
+ return 32;
+ case LUTRON:
+ case TECO:
+ return 35;
+ case SAMSUNG36:
+ return 36;
+ case SANYO_LC7461:
+ return kSanyoLC7461Bits; // 42
+ case GOODWEATHER:
+ case MIDEA:
+ case PANASONIC:
+ return 48;
+ case MAGIQUEST:
+ case VESTEL_AC:
+ return 56;
+ case AMCOR:
+ case PIONEER:
+ return 64;
+ case ARGO:
+ return kArgoBits;
+ case DAIKIN:
+ return kDaikinBits;
+ case DAIKIN128:
+ return kDaikin128Bits;
+ case DAIKIN152:
+ return kDaikin152Bits;
+ case DAIKIN160:
+ return kDaikin160Bits;
+ case DAIKIN176:
+ return kDaikin176Bits;
+ case DAIKIN2:
+ return kDaikin2Bits;
+ case DAIKIN216:
+ return kDaikin216Bits;
+ case ELECTRA_AC:
+ return kElectraAcBits;
+ case GREE:
+ return kGreeBits;
+ case HAIER_AC:
+ return kHaierACBits;
+ case HAIER_AC_YRW02:
+ return kHaierACYRW02Bits;
+ case HITACHI_AC:
+ return kHitachiAcBits;
+ case HITACHI_AC1:
+ return kHitachiAc1Bits;
+ case HITACHI_AC2:
+ return kHitachiAc2Bits;
+ case KELVINATOR:
+ return kKelvinatorBits;
+ case MITSUBISHI_AC:
+ return kMitsubishiACBits;
+ case MITSUBISHI_HEAVY_152:
+ return kMitsubishiHeavy152Bits;
+ case MITSUBISHI_HEAVY_88:
+ return kMitsubishiHeavy88Bits;
+ case NEOCLIMA:
+ return kNeoclimaBits;
+ case PANASONIC_AC:
+ return kNeoclimaBits;
+ case SAMSUNG_AC:
+ return kSamsungAcBits;
+ case SHARP_AC:
+ return kSharpAcBits;
+ case TCL112AC:
+ return kTcl112AcBits;
+ case TOSHIBA_AC:
+ return kToshibaACBits;
+ case TROTEC:
+ return kTrotecBits;
+ case WHIRLPOOL_AC:
+ return kWhirlpoolAcBits;
+ // No default amount of bits.
+ case FUJITSU_AC:
+ case MWM:
+ default:
+ return 0;
+ }
+}
+
// Send a simple (up to 64 bits) IR message of a given type.
// An unknown/unsupported type will do nothing.
// Args:
// type: Protocol number/type of the message you want to send.
// data: The data you want to send (up to 64 bits).
// nbits: How many bits long the message is to be.
+// repeat: How many repeats to do?
// Returns:
// bool: True if it is a type we can attempt to send, false if not.
-bool IRsend::send(decode_type_t type, uint64_t data, uint16_t nbits) {
+bool IRsend::send(const decode_type_t type, const uint64_t data,
+ const uint16_t nbits, const uint16_t repeat) {
+ uint16_t min_repeat = std::max(IRsend::minRepeats(type), repeat);
switch (type) {
#if SEND_AIWA_RC_T501
case AIWA_RC_T501:
- sendAiwaRCT501(data, nbits);
+ sendAiwaRCT501(data, nbits, min_repeat);
break;
#endif
#if SEND_CARRIER_AC
case CARRIER_AC:
- sendCarrierAC(data, nbits);
+ sendCarrierAC(data, nbits, min_repeat);
break;
#endif
#if SEND_COOLIX
case COOLIX:
- sendCOOLIX(data, nbits);
+ sendCOOLIX(data, nbits, min_repeat);
break;
#endif
#if SEND_DENON
case DENON:
- sendDenon(data, nbits);
+ sendDenon(data, nbits, min_repeat);
break;
#endif
#if SEND_DISH
case DISH:
- sendDISH(data, nbits);
+ sendDISH(data, nbits, min_repeat);
break;
#endif
#if SEND_GICABLE
case GICABLE:
- sendGICable(data, nbits);
+ sendGICable(data, nbits, min_repeat);
+ break;
+#endif
+#if SEND_GOODWEATHER
+ case GOODWEATHER:
+ sendGoodweather(data, nbits, min_repeat);
break;
#endif
#if SEND_GREE
case GREE:
- sendGree(data, nbits);
+ sendGree(data, nbits, min_repeat);
break;
#endif
+#if SEND_INAX
+ case INAX:
+ sendInax(data, nbits, min_repeat);
+ break;
+#endif // SEND_INAX
#if SEND_JVC
case JVC:
- sendJVC(data, nbits);
+ sendJVC(data, nbits, min_repeat);
break;
#endif
#if SEND_LASERTAG
case LASERTAG:
- sendLasertag(data, nbits);
+ sendLasertag(data, nbits, min_repeat);
break;
#endif
#if SEND_LEGOPF
case LEGOPF:
- sendLegoPf(data, nbits);
+ sendLegoPf(data, nbits, min_repeat);
break;
#endif
#if SEND_LG
case LG:
- sendLG(data, nbits);
+ sendLG(data, nbits, min_repeat);
break;
case LG2:
- sendLG2(data, nbits);
+ sendLG2(data, nbits, min_repeat);
break;
#endif
#if SEND_LUTRON
case LUTRON:
- sendLutron(data, nbits);
+ sendLutron(data, nbits, min_repeat);
break;
#endif
#if SEND_MAGIQUEST
case MAGIQUEST:
- sendMagiQuest(data, nbits);
+ sendMagiQuest(data, nbits, min_repeat);
break;
#endif
#if SEND_MIDEA
case MIDEA:
- sendMidea(data, nbits);
+ sendMidea(data, nbits, min_repeat);
break;
#endif
#if SEND_MITSUBISHI
case MITSUBISHI:
- sendMitsubishi(data, nbits);
+ sendMitsubishi(data, nbits, min_repeat);
break;
#endif
#if SEND_MITSUBISHI2
case MITSUBISHI2:
- sendMitsubishi2(data, nbits);
+ sendMitsubishi2(data, nbits, min_repeat);
break;
#endif
#if SEND_NIKAI
case NIKAI:
- sendNikai(data, nbits);
+ sendNikai(data, nbits, min_repeat);
break;
#endif
#if SEND_NEC
case NEC:
case NEC_LIKE:
- sendNEC(data, nbits);
+ sendNEC(data, nbits, min_repeat);
break;
#endif
#if SEND_PANASONIC
case PANASONIC:
- sendPanasonic64(data, nbits);
+ sendPanasonic64(data, nbits, min_repeat);
break;
#endif
#if SEND_PIONEER
case PIONEER:
- sendPioneer(data, nbits);
+ sendPioneer(data, nbits, min_repeat);
break;
#endif
#if SEND_RC5
case RC5:
- sendRC5(data, nbits);
+ case RC5X:
+ sendRC5(data, nbits, min_repeat);
break;
#endif
#if SEND_RC6
case RC6:
- sendRC6(data, nbits);
+ sendRC6(data, nbits, min_repeat);
break;
#endif
#if SEND_RCMM
case RCMM:
- sendRCMM(data, nbits);
+ sendRCMM(data, nbits, min_repeat);
break;
#endif
#if SEND_SAMSUNG
case SAMSUNG:
- sendSAMSUNG(data, nbits);
+ sendSAMSUNG(data, nbits, min_repeat);
break;
#endif
#if SEND_SAMSUNG36
case SAMSUNG36:
- sendSamsung36(data, nbits);
+ sendSamsung36(data, nbits, min_repeat);
break;
#endif
#if SEND_SANYO
case SANYO_LC7461:
- sendSanyoLC7461(data, nbits);
+ sendSanyoLC7461(data, nbits, min_repeat);
break;
#endif
#if SEND_SHARP
case SHARP:
- sendSharpRaw(data, nbits);
+ sendSharpRaw(data, nbits, min_repeat);
break;
#endif
#if SEND_SHERWOOD
case SHERWOOD:
- sendSherwood(data, nbits);
+ sendSherwood(data, nbits, min_repeat);
break;
#endif
#if SEND_SONY
case SONY:
- sendSony(data, nbits);
+ sendSony(data, nbits, min_repeat);
break;
#endif
#if SEND_TECO
case TECO:
- sendTeco(data, nbits);
+ sendTeco(data, nbits, min_repeat);
break;
#endif
#if SEND_VESTEL_AC
case VESTEL_AC:
- sendVestelAc(data, nbits);
+ sendVestelAc(data, nbits, min_repeat);
break;
#endif
#if SEND_WHYNTER
case WHYNTER:
- sendWhynter(data, nbits);
+ sendWhynter(data, nbits, min_repeat);
break;
#endif
default:
@@ -670,3 +833,168 @@ bool IRsend::send(decode_type_t type, uint64_t data, uint16_t nbits) {
}
return true;
}
+
+// Send a complex (>= 64 bits) IR message of a given type.
+// An unknown/unsupported type will do nothing.
+// Args:
+// type: Protocol number/type of the message you want to send.
+// state: A pointer to the array of bytes that make up the state[].
+// nbytes: How many bytes are in the state.
+// Returns:
+// bool: True if it is a type we can attempt to send, false if not.
+bool IRsend::send(const decode_type_t type, const unsigned char *state,
+ const uint16_t nbytes) {
+ switch (type) {
+#if SEND_AMCOR
+ case AMCOR:
+ sendAmcor(state, nbytes);
+ break;
+#endif
+#if SEND_ARGO
+ case ARGO:
+ sendArgo(state, nbytes);
+ break;
+#endif // SEND_ARGO
+#if SEND_DAIKIN
+ case DAIKIN:
+ sendDaikin(state, nbytes);
+ break;
+#endif // SEND_DAIKIN
+#if SEND_DAIKIN128
+ case DAIKIN128:
+ sendDaikin128(state, nbytes);
+ break;
+#endif // SEND_DAIKIN128
+#if SEND_DAIKIN152
+ case DAIKIN152:
+ sendDaikin152(state, nbytes);
+ break;
+#endif // SEND_DAIKIN152
+#if SEND_DAIKIN160
+ case DAIKIN160:
+ sendDaikin160(state, nbytes);
+ break;
+#endif // SEND_DAIKIN160
+#if SEND_DAIKIN176
+ case DAIKIN176:
+ sendDaikin176(state, nbytes);
+ break;
+#endif // SEND_DAIKIN176
+#if SEND_DAIKIN2
+ case DAIKIN2:
+ sendDaikin2(state, nbytes);
+ break;
+#endif // SEND_DAIKIN2
+#if SEND_DAIKIN216
+ case DAIKIN216:
+ sendDaikin216(state, nbytes);
+ break;
+#endif // SEND_DAIKIN216
+#if SEND_ELECTRA_AC
+ case ELECTRA_AC:
+ sendElectraAC(state, nbytes);
+ break;
+#endif // SEND_ELECTRA_AC
+#if SEND_FUJITSU_AC
+ case FUJITSU_AC:
+ sendFujitsuAC(state, nbytes);
+ break;
+#endif // SEND_FUJITSU_AC
+#if SEND_GREE
+ case GREE:
+ sendGree(state, nbytes);
+ break;
+#endif // SEND_GREE
+#if SEND_HAIER_AC
+ case HAIER_AC:
+ sendHaierAC(state, nbytes);
+ break;
+#endif // SEND_HAIER_AC
+#if SEND_HAIER_AC_YRW02
+ case HAIER_AC_YRW02:
+ sendHaierACYRW02(state, nbytes);
+ break;
+#endif // SEND_HAIER_AC_YRW02
+#if SEND_HITACHI_AC
+ case HITACHI_AC:
+ sendHitachiAC(state, nbytes);
+ break;
+#endif // SEND_HITACHI_AC
+#if SEND_HITACHI_AC1
+ case HITACHI_AC1:
+ sendHitachiAC1(state, nbytes);
+ break;
+#endif // SEND_HITACHI_AC1
+#if SEND_HITACHI_AC2
+ case HITACHI_AC2:
+ sendHitachiAC2(state, nbytes);
+ break;
+#endif // SEND_HITACHI_AC2
+#if SEND_KELVINATOR
+ case KELVINATOR:
+ sendKelvinator(state, nbytes);
+ break;
+#endif // SEND_KELVINATOR
+#if SEND_MITSUBISHI_AC
+ case MITSUBISHI_AC:
+ sendMitsubishiAC(state, nbytes);
+ break;
+#endif // SEND_MITSUBISHI_AC
+#if SEND_MITSUBISHIHEAVY
+ case MITSUBISHI_HEAVY_88:
+ sendMitsubishiHeavy88(state, nbytes);
+ break;
+ case MITSUBISHI_HEAVY_152:
+ sendMitsubishiHeavy152(state, nbytes);
+ break;
+#endif // SEND_MITSUBISHIHEAVY
+#if SEND_MWM
+ case MWM:
+ sendMWM(state, nbytes);
+ break;
+#endif // SEND_MWM
+#if SEND_NEOCLIMA
+ case NEOCLIMA:
+ sendNeoclima(state, nbytes);
+ break;
+#endif // SEND_NEOCLIMA
+#if SEND_PANASONIC_AC
+ case PANASONIC_AC:
+ sendPanasonicAC(state, nbytes);
+ break;
+#endif // SEND_PANASONIC_AC
+#if SEND_SAMSUNG_AC
+ case SAMSUNG_AC:
+ sendSamsungAC(state, nbytes);
+ break;
+#endif // SEND_SAMSUNG_AC
+#if SEND_SHARP_AC
+ case SHARP_AC:
+ sendSharpAc(state, nbytes);
+ break;
+#endif // SEND_SHARP_AC
+#if SEND_TCL112AC
+ case TCL112AC:
+ sendTcl112Ac(state, nbytes);
+ break;
+#endif // SEND_TCL112AC
+#if SEND_TOSHIBA_AC
+ case TOSHIBA_AC:
+ sendToshibaAC(state, nbytes);
+ break;
+#endif // SEND_TOSHIBA_AC
+#if SEND_TROTEC
+ case TROTEC:
+ sendTrotec(state, nbytes);
+ break;
+#endif // SEND_TROTEC
+#if SEND_WHIRLPOOL_AC
+ case WHIRLPOOL_AC:
+ sendWhirlpoolAC(state, nbytes);
+ break;
+#endif // SEND_WHIRLPOOL_AC
+ default:
+ return false;
+ }
+ return true;
+}
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRsend.h b/lib/IRremoteESP8266-2.6.5/src/IRsend.h
similarity index 58%
rename from lib/IRremoteESP8266-2.6.0/src/IRsend.h
rename to lib/IRremoteESP8266-2.6.5/src/IRsend.h
index b065f6582..cbccee479 100644
--- a/lib/IRremoteESP8266-2.6.0/src/IRsend.h
+++ b/lib/IRremoteESP8266-2.6.5/src/IRsend.h
@@ -9,7 +9,7 @@
#include "IRremoteESP8266.h"
// Originally from https://github.com/shirriff/Arduino-IRremote/
-// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for
+// Updated by markszabo (https://github.com/crankyoldgit/IRremoteESP8266) for
// sending IR code on ESP8266
#if TEST || UNIT_TEST
@@ -21,8 +21,17 @@
// Constants
// Offset (in microseconds) to use in Period time calculations to account for
// code excution time in producing the software PWM signal.
-// Value was calculated on Wemos D1 mini using v2.4.1 with v2.4.0 ESP core
+#if defined(ESP32)
+// Calculated on a generic ESP-WROOM-32 board with v3.2-18 SDK @ 240MHz
+const int8_t kPeriodOffset = -2;
+#elif (defined(ESP8266) && F_CPU == 160000000L) // NOLINT(whitespace/parens)
+// Calculated on an ESP8266 NodeMCU v2 board using:
+// v2.6.0 with v2.5.2 ESP core @ 160MHz
+const int8_t kPeriodOffset = -2;
+#else // (defined(ESP8266) && F_CPU == 160000000L)
+// Calculated on ESP8266 Wemos D1 mini using v2.4.1 with v2.4.0 ESP core @ 40MHz
const int8_t kPeriodOffset = -5;
+#endif // (defined(ESP8266) && F_CPU == 160000000L)
const uint8_t kDutyDefault = 50; // Percentage
const uint8_t kDutyMax = 100; // Percentage
// delayMicroseconds() is only accurate to 16383us.
@@ -40,6 +49,8 @@ namespace stdAc {
kHeat = 2,
kDry = 3,
kFan = 4,
+ // Add new entries before this one, and update it to point to the last entry
+ kLastOpmodeEnum = kFan,
};
enum class fanspeed_t {
@@ -49,6 +60,8 @@ namespace stdAc {
kMedium = 3,
kHigh = 4,
kMax = 5,
+ // Add new entries before this one, and update it to point to the last entry
+ kLastFanspeedEnum = kMax,
};
enum class swingv_t {
@@ -59,6 +72,8 @@ namespace stdAc {
kMiddle = 3,
kLow = 4,
kLowest = 5,
+ // Add new entries before this one, and update it to point to the last entry
+ kLastSwingvEnum = kLowest,
};
enum class swingh_t {
@@ -69,7 +84,32 @@ namespace stdAc {
kMiddle = 3,
kRight = 4,
kRightMax = 5,
+ kWide = 6, // a.k.a. left & right at the same time.
+ // Add new entries before this one, and update it to point to the last entry
+ kLastSwinghEnum = kWide,
};
+
+ // Structure to hold a common A/C state.
+ typedef struct {
+ decode_type_t protocol;
+ int16_t model;
+ bool power;
+ stdAc::opmode_t mode;
+ float degrees;
+ bool celsius;
+ stdAc::fanspeed_t fanspeed;
+ stdAc::swingv_t swingv;
+ stdAc::swingh_t swingh;
+ bool quiet;
+ bool turbo;
+ bool econo;
+ bool light;
+ bool filter;
+ bool clean;
+ bool beep;
+ int16_t sleep;
+ int16_t clock;
+ } state_t;
}; // namespace stdAc
// Classes
@@ -109,7 +149,12 @@ class IRsend {
const uint8_t *dataptr, const uint16_t nbytes,
const uint16_t frequency, const bool MSBfirst,
const uint16_t repeat, const uint8_t dutycycle);
- bool send(decode_type_t type, uint64_t data, uint16_t nbits);
+ static uint16_t minRepeats(const decode_type_t protocol);
+ static uint16_t defaultBits(const decode_type_t protocol);
+ bool send(const decode_type_t type, const uint64_t data,
+ const uint16_t nbits, const uint16_t repeat = kNoRepeat);
+ bool send(const decode_type_t type, const uint8_t state[],
+ const uint16_t nbytes);
#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO)
void sendNEC(uint64_t data, uint16_t nbits = kNECBits,
uint16_t repeat = kNoRepeat);
@@ -131,9 +176,9 @@ class IRsend {
uint16_t repeat = kSherwoodMinRepeat);
#endif
#if SEND_SAMSUNG
- void sendSAMSUNG(uint64_t data, uint16_t nbits = kSamsungBits,
- uint16_t repeat = kNoRepeat);
- uint32_t encodeSAMSUNG(uint8_t customer, uint8_t command);
+ void sendSAMSUNG(const uint64_t data, const uint16_t nbits = kSamsungBits,
+ const uint16_t repeat = kNoRepeat);
+ uint32_t encodeSAMSUNG(const uint8_t customer, const uint8_t command);
#endif
#if SEND_SAMSUNG36
void sendSamsung36(const uint64_t data, const uint16_t nbits = kSamsung36Bits,
@@ -152,21 +197,27 @@ class IRsend {
uint32_t encodeLG(uint16_t address, uint16_t command);
#endif
#if (SEND_SHARP || SEND_DENON)
- uint32_t encodeSharp(uint16_t address, uint16_t command,
- uint16_t expansion = 1, uint16_t check = 0,
- bool MSBfirst = false);
- void sendSharp(uint16_t address, uint16_t command,
- uint16_t nbits = kSharpBits, uint16_t repeat = kNoRepeat);
- void sendSharpRaw(uint64_t data, uint16_t nbits = kSharpBits,
- uint16_t repeat = kNoRepeat);
+ uint32_t encodeSharp(const uint16_t address, const uint16_t command,
+ const uint16_t expansion = 1, const uint16_t check = 0,
+ const bool MSBfirst = false);
+ void sendSharp(const uint16_t address, const uint16_t command,
+ const uint16_t nbits = kSharpBits,
+ const uint16_t repeat = kNoRepeat);
+ void sendSharpRaw(const uint64_t data, const uint16_t nbits = kSharpBits,
+ const uint16_t repeat = kNoRepeat);
#endif
+#if SEND_SHARP_AC
+ void sendSharpAc(const unsigned char data[],
+ const uint16_t nbytes = kSharpAcStateLength,
+ const uint16_t repeat = kSharpAcDefaultRepeat);
+#endif // SEND_SHARP_AC
#if SEND_JVC
void sendJVC(uint64_t data, uint16_t nbits = kJvcBits,
uint16_t repeat = kNoRepeat);
uint16_t encodeJVC(uint8_t address, uint8_t command);
#endif
#if SEND_DENON
- void sendDenon(uint64_t data, uint16_t nbits = DENON_BITS,
+ void sendDenon(uint64_t data, uint16_t nbits = kDenonBits,
uint16_t repeat = kNoRepeat);
#endif
#if SEND_SANYO
@@ -183,13 +234,14 @@ class IRsend {
uint16_t repeat = kDishMinRepeat);
#endif
#if (SEND_PANASONIC || SEND_DENON)
- void sendPanasonic64(uint64_t data, uint16_t nbits = kPanasonicBits,
- uint16_t repeat = kNoRepeat);
- void sendPanasonic(uint16_t address, uint32_t data,
- uint16_t nbits = kPanasonicBits,
- uint16_t repeat = kNoRepeat);
- uint64_t encodePanasonic(uint16_t manufacturer, uint8_t device,
- uint8_t subdevice, uint8_t function);
+ void sendPanasonic64(const uint64_t data,
+ const uint16_t nbits = kPanasonicBits,
+ const uint16_t repeat = kNoRepeat);
+ void sendPanasonic(const uint16_t address, const uint32_t data,
+ const uint16_t nbits = kPanasonicBits,
+ const uint16_t repeat = kNoRepeat);
+ uint64_t encodePanasonic(const uint16_t manufacturer, const uint8_t device,
+ const uint8_t subdevice, const uint8_t function);
#endif
#if SEND_RC5
void sendRC5(uint64_t data, uint16_t nbits = kRC5XBits,
@@ -228,9 +280,9 @@ class IRsend {
uint16_t repeat = kMitsubishiMinRepeat);
#endif
#if SEND_MITSUBISHI_AC
- void sendMitsubishiAC(unsigned char data[],
- uint16_t nbytes = kMitsubishiACStateLength,
- uint16_t repeat = kMitsubishiACMinRepeat);
+ void sendMitsubishiAC(const unsigned char data[],
+ const uint16_t nbytes = kMitsubishiACStateLength,
+ const uint16_t repeat = kMitsubishiACMinRepeat);
#endif
#if SEND_MITSUBISHIHEAVY
void sendMitsubishiHeavy88(
@@ -243,25 +295,50 @@ class IRsend {
const uint16_t repeat = kMitsubishiHeavy152MinRepeat);
#endif
#if SEND_FUJITSU_AC
- void sendFujitsuAC(unsigned char data[], uint16_t nbytes,
- uint16_t repeat = kFujitsuAcMinRepeat);
+ void sendFujitsuAC(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat = kFujitsuAcMinRepeat);
#endif
+#if SEND_INAX
+ void sendInax(const uint64_t data, const uint16_t nbits = kInaxBits,
+ const uint16_t repeat = kInaxMinRepeat);
+#endif // SEND_INAX
#if SEND_GLOBALCACHE
void sendGC(uint16_t buf[], uint16_t len);
#endif
#if SEND_KELVINATOR
- void sendKelvinator(unsigned char data[],
- uint16_t nbytes = kKelvinatorStateLength,
- uint16_t repeat = kKelvinatorDefaultRepeat);
+ void sendKelvinator(const unsigned char data[],
+ const uint16_t nbytes = kKelvinatorStateLength,
+ const uint16_t repeat = kKelvinatorDefaultRepeat);
#endif
#if SEND_DAIKIN
void sendDaikin(const unsigned char data[],
const uint16_t nbytes = kDaikinStateLength,
const uint16_t repeat = kDaikinDefaultRepeat);
#endif
+#if SEND_DAIKIN128
+ void sendDaikin128(const unsigned char data[],
+ const uint16_t nbytes = kDaikin128StateLength,
+ const uint16_t repeat = kDaikin128DefaultRepeat);
+#endif // SEND_DAIKIN128
+#if SEND_DAIKIN152
+ void sendDaikin152(const unsigned char data[],
+ const uint16_t nbytes = kDaikin152StateLength,
+ const uint16_t repeat = kDaikin152DefaultRepeat);
+#endif // SEND_DAIKIN152
+#if SEND_DAIKIN160
+ void sendDaikin160(const unsigned char data[],
+ const uint16_t nbytes = kDaikin160StateLength,
+ const uint16_t repeat = kDaikin160DefaultRepeat);
+#endif // SEND_DAIKIN160
+#if SEND_DAIKIN176
+ void sendDaikin176(const unsigned char data[],
+ const uint16_t nbytes = kDaikin176StateLength,
+ const uint16_t repeat = kDaikin176DefaultRepeat);
+#endif // SEND_DAIKIN176
#if SEND_DAIKIN2
- void sendDaikin2(unsigned char data[], uint16_t nbytes = kDaikin2StateLength,
- uint16_t repeat = kDaikin2DefaultRepeat);
+ void sendDaikin2(const unsigned char data[],
+ const uint16_t nbytes = kDaikin2StateLength,
+ const uint16_t repeat = kDaikin2DefaultRepeat);
#endif
#if SEND_DAIKIN216
void sendDaikin216(const unsigned char data[],
@@ -273,30 +350,37 @@ class IRsend {
uint16_t repeat = kAiwaRcT501MinRepeats);
#endif
#if SEND_GREE
- void sendGree(uint64_t data, uint16_t nbits = kGreeBits,
- uint16_t repeat = kGreeDefaultRepeat);
- void sendGree(uint8_t data[], uint16_t nbytes = kGreeStateLength,
- uint16_t repeat = kGreeDefaultRepeat);
+ void sendGree(const uint64_t data, const uint16_t nbits = kGreeBits,
+ const uint16_t repeat = kGreeDefaultRepeat);
+ void sendGree(const uint8_t data[], const uint16_t nbytes = kGreeStateLength,
+ const uint16_t repeat = kGreeDefaultRepeat);
#endif
+#if SEND_GOODWEATHER
+ void sendGoodweather(const uint64_t data,
+ const uint16_t nbits = kGoodweatherBits,
+ const uint16_t repeat = kGoodweatherMinRepeat);
+#endif // SEND_GOODWEATHER
#if SEND_PRONTO
void sendPronto(uint16_t data[], uint16_t len, uint16_t repeat = kNoRepeat);
#endif
#if SEND_ARGO
- void sendArgo(unsigned char data[], uint16_t nbytes = kArgoStateLength,
- uint16_t repeat = kArgoDefaultRepeat);
+ void sendArgo(const unsigned char data[],
+ const uint16_t nbytes = kArgoStateLength,
+ const uint16_t repeat = kArgoDefaultRepeat);
#endif
#if SEND_TROTEC
- void sendTrotec(unsigned char data[], uint16_t nbytes = kTrotecStateLength,
- uint16_t repeat = kTrotecDefaultRepeat);
+ void sendTrotec(const unsigned char data[],
+ const uint16_t nbytes = kTrotecStateLength,
+ const uint16_t repeat = kTrotecDefaultRepeat);
#endif
#if SEND_NIKAI
void sendNikai(uint64_t data, uint16_t nbits = kNikaiBits,
uint16_t repeat = kNoRepeat);
#endif
#if SEND_TOSHIBA_AC
- void sendToshibaAC(unsigned char data[],
- uint16_t nbytes = kToshibaACStateLength,
- uint16_t repeat = kToshibaACMinRepeat);
+ void sendToshibaAC(const unsigned char data[],
+ const uint16_t nbytes = kToshibaACStateLength,
+ const uint16_t repeat = kToshibaACMinRepeat);
#endif
#if SEND_MIDEA
void sendMidea(uint64_t data, uint16_t nbits = kMideaBits,
@@ -316,51 +400,52 @@ class IRsend {
uint16_t repeat = kCarrierAcMinRepeat);
#endif
#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02)
- void sendHaierAC(unsigned char data[], uint16_t nbytes = kHaierACStateLength,
- uint16_t repeat = kHaierAcDefaultRepeat);
+ void sendHaierAC(const unsigned char data[],
+ const uint16_t nbytes = kHaierACStateLength,
+ const uint16_t repeat = kHaierAcDefaultRepeat);
#endif
#if SEND_HAIER_AC_YRW02
- void sendHaierACYRW02(unsigned char data[],
- uint16_t nbytes = kHaierACYRW02StateLength,
- uint16_t repeat = kHaierAcYrw02DefaultRepeat);
+ void sendHaierACYRW02(const unsigned char data[],
+ const uint16_t nbytes = kHaierACYRW02StateLength,
+ const uint16_t repeat = kHaierAcYrw02DefaultRepeat);
#endif
#if SEND_HITACHI_AC
- void sendHitachiAC(unsigned char data[],
- uint16_t nbytes = kHitachiAcStateLength,
- uint16_t repeat = kHitachiAcDefaultRepeat);
+ void sendHitachiAC(const unsigned char data[],
+ const uint16_t nbytes = kHitachiAcStateLength,
+ const uint16_t repeat = kHitachiAcDefaultRepeat);
#endif
#if SEND_HITACHI_AC1
- void sendHitachiAC1(unsigned char data[],
- uint16_t nbytes = kHitachiAc1StateLength,
- uint16_t repeat = kNoRepeat);
+ void sendHitachiAC1(const unsigned char data[],
+ const uint16_t nbytes = kHitachiAc1StateLength,
+ const uint16_t repeat = kNoRepeat);
#endif
#if SEND_HITACHI_AC2
- void sendHitachiAC2(unsigned char data[],
- uint16_t nbytes = kHitachiAc2StateLength,
- uint16_t repeat = kNoRepeat);
+ void sendHitachiAC2(const unsigned char data[],
+ const uint16_t nbytes = kHitachiAc2StateLength,
+ const uint16_t repeat = kNoRepeat);
#endif
#if SEND_GICABLE
void sendGICable(uint64_t data, uint16_t nbits = kGicableBits,
uint16_t repeat = kGicableMinRepeat);
#endif
#if SEND_WHIRLPOOL_AC
- void sendWhirlpoolAC(unsigned char data[],
- uint16_t nbytes = kWhirlpoolAcStateLength,
- uint16_t repeat = kWhirlpoolAcDefaultRepeat);
+ void sendWhirlpoolAC(const unsigned char data[],
+ const uint16_t nbytes = kWhirlpoolAcStateLength,
+ const uint16_t repeat = kWhirlpoolAcDefaultRepeat);
#endif
#if SEND_LUTRON
void sendLutron(uint64_t data, uint16_t nbits = kLutronBits,
uint16_t repeat = kNoRepeat);
#endif
#if SEND_ELECTRA_AC
- void sendElectraAC(unsigned char data[],
- uint16_t nbytes = kElectraAcStateLength,
- uint16_t repeat = kNoRepeat);
+ void sendElectraAC(const unsigned char data[],
+ const uint16_t nbytes = kElectraAcStateLength,
+ const uint16_t repeat = kNoRepeat);
#endif
#if SEND_PANASONIC_AC
- void sendPanasonicAC(unsigned char data[],
- uint16_t nbytes = kPanasonicAcStateLength,
- uint16_t repeat = kPanasonicAcDefaultRepeat);
+ void sendPanasonicAC(const unsigned char data[],
+ const uint16_t nbytes = kPanasonicAcStateLength,
+ const uint16_t repeat = kPanasonicAcDefaultRepeat);
#endif
#if SEND_PIONEER
void sendPioneer(const uint64_t data, const uint16_t nbits = kPioneerBits,
@@ -368,8 +453,8 @@ class IRsend {
uint64_t encodePioneer(uint16_t address, uint16_t command);
#endif
#if SEND_MWM
- void sendMWM(unsigned char data[], uint16_t nbytes,
- uint16_t repeat = kNoRepeat);
+ void sendMWM(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat = kNoRepeat);
#endif
#if SEND_VESTEL_AC
void sendVestelAc(const uint64_t data, const uint16_t nbits = kVestelAcBits,
@@ -381,13 +466,23 @@ class IRsend {
const uint16_t repeat = kTcl112AcDefaultRepeat);
#endif
#if SEND_TECO
- void sendTeco(uint64_t data, uint16_t nbits = kTecoBits,
- uint16_t repeat = kNoRepeat);
+ void sendTeco(const uint64_t data, const uint16_t nbits = kTecoBits,
+ const uint16_t repeat = kNoRepeat);
#endif
#if SEND_LEGOPF
void sendLegoPf(const uint64_t data, const uint16_t nbits = kLegoPfBits,
const uint16_t repeat = kLegoPfMinRepeat);
#endif
+#if SEND_NEOCLIMA
+ void sendNeoclima(const unsigned char data[],
+ const uint16_t nbytes = kNeoclimaStateLength,
+ const uint16_t repeat = kNeoclimaMinRepeat);
+#endif // SEND_NEOCLIMA
+#if SEND_AMCOR
+ void sendAmcor(const unsigned char data[],
+ const uint16_t nbytes = kAmcorStateLength,
+ const uint16_t repeat = kAmcorDefaultRepeat);
+#endif // SEND_AMCOR
protected:
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRtimer.cpp b/lib/IRremoteESP8266-2.6.5/src/IRtimer.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/src/IRtimer.cpp
rename to lib/IRremoteESP8266-2.6.5/src/IRtimer.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRtimer.h b/lib/IRremoteESP8266-2.6.5/src/IRtimer.h
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/src/IRtimer.h
rename to lib/IRremoteESP8266-2.6.5/src/IRtimer.h
diff --git a/lib/IRremoteESP8266-2.6.0/src/IRutils.cpp b/lib/IRremoteESP8266-2.6.5/src/IRutils.cpp
similarity index 55%
rename from lib/IRremoteESP8266-2.6.0/src/IRutils.cpp
rename to lib/IRremoteESP8266-2.6.5/src/IRutils.cpp
index d90925241..6f589aa3d 100644
--- a/lib/IRremoteESP8266-2.6.0/src/IRutils.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/IRutils.cpp
@@ -44,19 +44,19 @@ uint64_t reverseBits(uint64_t input, uint16_t nbits) {
// Returns:
// A string representation of the integer.
// Note: Based on Arduino's Print::printNumber()
-#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist.
String uint64ToString(uint64_t input, uint8_t base) {
String result = "";
-#else
-std::string uint64ToString(uint64_t input, uint8_t base) {
- std::string result = "";
-#endif
// prevent issues if called with base <= 1
if (base < 2) base = 10;
// Check we have a base that we can actually print.
// i.e. [0-9A-Z] == 36
if (base > 36) base = 10;
+ // Reserve some string space to reduce fragmentation.
+ // 16 bytes should store a uint64 in hex text which is the likely worst case.
+ // 64 bytes would be the worst case (base 2).
+ result.reserve(16);
+
do {
char c = input % base;
input /= base;
@@ -82,133 +82,157 @@ void serialPrintUint64(uint64_t input, uint8_t base) {
}
#endif
-// Convert a c-style str to a decode_type_t
-// Note: Assumes str is upper case.
+// Convert a C-style str to a decode_type_t
//
// Args:
-// str: An upper-case C-style string.
+// str: A C-style string containing a protocol name or number.
// Returns:
// A decode_type_t enum.
-decode_type_t strToDecodeType(const char *str) {
- if (!strcmp(str, "UNKNOWN"))
+decode_type_t strToDecodeType(const char * const str) {
+ if (!strcasecmp(str, "UNKNOWN"))
return decode_type_t::UNKNOWN;
- else if (!strcmp(str, "UNUSED"))
+ else if (!strcasecmp(str, "UNUSED"))
return decode_type_t::UNUSED;
- else if (!strcmp(str, "AIWA_RC_T501"))
+ else if (!strcasecmp(str, "AIWA_RC_T501"))
return decode_type_t::AIWA_RC_T501;
- else if (!strcmp(str, "ARGO"))
+ else if (!strcasecmp(str, "AMCOR"))
+ return decode_type_t::AMCOR;
+ else if (!strcasecmp(str, "ARGO"))
return decode_type_t::ARGO;
- else if (!strcmp(str, "CARRIER_AC"))
+ else if (!strcasecmp(str, "CARRIER_AC"))
return decode_type_t::CARRIER_AC;
- else if (!strcmp(str, "COOLIX"))
+ else if (!strcasecmp(str, "COOLIX"))
return decode_type_t::COOLIX;
- else if (!strcmp(str, "DAIKIN"))
+ else if (!strcasecmp(str, "DAIKIN"))
return decode_type_t::DAIKIN;
- else if (!strcmp(str, "DAIKIN2"))
+ else if (!strcasecmp(str, "DAIKIN128"))
+ return decode_type_t::DAIKIN128;
+ else if (!strcasecmp(str, "DAIKIN152"))
+ return decode_type_t::DAIKIN152;
+ else if (!strcasecmp(str, "DAIKIN160"))
+ return decode_type_t::DAIKIN160;
+ else if (!strcasecmp(str, "DAIKIN176"))
+ return decode_type_t::DAIKIN176;
+ else if (!strcasecmp(str, "DAIKIN2"))
return decode_type_t::DAIKIN2;
- else if (!strcmp(str, "DAIKIN216"))
+ else if (!strcasecmp(str, "DAIKIN216"))
return decode_type_t::DAIKIN216;
- else if (!strcmp(str, "DENON"))
+ else if (!strcasecmp(str, "DENON"))
return decode_type_t::DENON;
- else if (!strcmp(str, "DISH"))
+ else if (!strcasecmp(str, "DISH"))
return decode_type_t::DISH;
- else if (!strcmp(str, "ELECTRA_AC"))
+ else if (!strcasecmp(str, "ELECTRA_AC"))
return decode_type_t::ELECTRA_AC;
- else if (!strcmp(str, "FUJITSU_AC"))
+ else if (!strcasecmp(str, "FUJITSU_AC"))
return decode_type_t::FUJITSU_AC;
- else if (!strcmp(str, "GICABLE"))
+ else if (!strcasecmp(str, "GICABLE"))
return decode_type_t::GICABLE;
- else if (!strcmp(str, "GLOBALCACHE"))
+ else if (!strcasecmp(str, "GLOBALCACHE"))
return decode_type_t::GLOBALCACHE;
- else if (!strcmp(str, "GREE"))
+ else if (!strcasecmp(str, "GOODWEATHER"))
+ return decode_type_t::GOODWEATHER;
+ else if (!strcasecmp(str, "GREE"))
return decode_type_t::GREE;
- else if (!strcmp(str, "HAIER_AC"))
+ else if (!strcasecmp(str, "HAIER_AC"))
return decode_type_t::HAIER_AC;
- else if (!strcmp(str, "HAIER_AC_YRW02"))
+ else if (!strcasecmp(str, "HAIER_AC_YRW02"))
return decode_type_t::HAIER_AC_YRW02;
- else if (!strcmp(str, "HITACHI_AC"))
+ else if (!strcasecmp(str, "HITACHI_AC"))
return decode_type_t::HITACHI_AC;
- else if (!strcmp(str, "HITACHI_AC1"))
+ else if (!strcasecmp(str, "HITACHI_AC1"))
return decode_type_t::HITACHI_AC1;
- else if (!strcmp(str, "HITACHI_AC2"))
+ else if (!strcasecmp(str, "HITACHI_AC2"))
return decode_type_t::HITACHI_AC2;
- else if (!strcmp(str, "JVC"))
+ else if (!strcasecmp(str, "INAX"))
+ return decode_type_t::INAX;
+ else if (!strcasecmp(str, "JVC"))
return decode_type_t::JVC;
- else if (!strcmp(str, "KELVINATOR"))
+ else if (!strcasecmp(str, "KELVINATOR"))
return decode_type_t::KELVINATOR;
- else if (!strcmp(str, "LEGOPF"))
+ else if (!strcasecmp(str, "LEGOPF"))
return decode_type_t::LEGOPF;
- else if (!strcmp(str, "LG"))
+ else if (!strcasecmp(str, "LG"))
return decode_type_t::LG;
- else if (!strcmp(str, "LG2"))
+ else if (!strcasecmp(str, "LG2"))
return decode_type_t::LG2;
- else if (!strcmp(str, "LASERTAG"))
+ else if (!strcasecmp(str, "LASERTAG"))
return decode_type_t::LASERTAG;
- else if (!strcmp(str, "LUTRON"))
+ else if (!strcasecmp(str, "LUTRON"))
return decode_type_t::LUTRON;
- else if (!strcmp(str, "MAGIQUEST"))
+ else if (!strcasecmp(str, "MAGIQUEST"))
return decode_type_t::MAGIQUEST;
- else if (!strcmp(str, "MIDEA"))
+ else if (!strcasecmp(str, "MIDEA"))
return decode_type_t::MIDEA;
- else if (!strcmp(str, "MITSUBISHI"))
+ else if (!strcasecmp(str, "MITSUBISHI"))
return decode_type_t::MITSUBISHI;
- else if (!strcmp(str, "MITSUBISHI2"))
+ else if (!strcasecmp(str, "MITSUBISHI2"))
return decode_type_t::MITSUBISHI2;
- else if (!strcmp(str, "MITSUBISHI_AC"))
+ else if (!strcasecmp(str, "MITSUBISHI_AC"))
return decode_type_t::MITSUBISHI_AC;
- else if (!strcmp(str, "MWM"))
+ else if (!strcasecmp(str, "MITSUBISHI_HEAVY_88"))
+ return decode_type_t::MITSUBISHI_HEAVY_88;
+ else if (!strcasecmp(str, "MITSUBISHI_HEAVY_152"))
+ return decode_type_t::MITSUBISHI_HEAVY_152;
+ else if (!strcasecmp(str, "MWM"))
return decode_type_t::MWM;
- else if (!strcmp(str, "NEC") || !strcmp(str, "NEC (NON-STRICT"))
+ else if (!strcasecmp(str, "NEOCLIMA"))
+ return decode_type_t::NEOCLIMA;
+ else if (!strcasecmp(str, "NEC"))
return decode_type_t::NEC;
- else if (!strcmp(str, "NIKAI"))
+ else if (!strcasecmp(str, "NEC_LIKE") ||
+ !strcasecmp(str, "NEC (NON-STRICT)"))
+ return decode_type_t::NEC_LIKE;
+ else if (!strcasecmp(str, "NIKAI"))
return decode_type_t::NIKAI;
- else if (!strcmp(str, "PANASONIC"))
+ else if (!strcasecmp(str, "PANASONIC"))
return decode_type_t::PANASONIC;
- else if (!strcmp(str, "PANASONIC_AC"))
+ else if (!strcasecmp(str, "PANASONIC_AC"))
return decode_type_t::PANASONIC_AC;
- else if (!strcmp(str, "PIONEER"))
+ else if (!strcasecmp(str, "PIONEER"))
return decode_type_t::PIONEER;
- else if (!strcmp(str, "PRONTO"))
+ else if (!strcasecmp(str, "PRONTO"))
return decode_type_t::PRONTO;
- else if (!strcmp(str, "RAW"))
+ else if (!strcasecmp(str, "RAW"))
return decode_type_t::RAW;
- else if (!strcmp(str, "RC5"))
+ else if (!strcasecmp(str, "RC5"))
return decode_type_t::RC5;
- else if (!strcmp(str, "RC5X"))
+ else if (!strcasecmp(str, "RC5X"))
return decode_type_t::RC5X;
- else if (!strcmp(str, "RC6"))
+ else if (!strcasecmp(str, "RC6"))
return decode_type_t::RC6;
- else if (!strcmp(str, "RCMM"))
+ else if (!strcasecmp(str, "RCMM"))
return decode_type_t::RCMM;
- else if (!strcmp(str, "SAMSUNG"))
+ else if (!strcasecmp(str, "SAMSUNG"))
return decode_type_t::SAMSUNG;
- else if (!strcmp(str, "SAMSUNG36"))
+ else if (!strcasecmp(str, "SAMSUNG36"))
return decode_type_t::SAMSUNG36;
- else if (!strcmp(str, "SAMSUNG_AC"))
+ else if (!strcasecmp(str, "SAMSUNG_AC"))
return decode_type_t::SAMSUNG_AC;
- else if (!strcmp(str, "SANYO"))
+ else if (!strcasecmp(str, "SANYO"))
return decode_type_t::SANYO;
- else if (!strcmp(str, "SANYO_LC7461"))
+ else if (!strcasecmp(str, "SANYO_LC7461"))
return decode_type_t::SANYO_LC7461;
- else if (!strcmp(str, "SHARP"))
+ else if (!strcasecmp(str, "SHARP"))
return decode_type_t::SHARP;
- else if (!strcmp(str, "SHERWOOD"))
+ else if (!strcasecmp(str, "SHARP_AC"))
+ return decode_type_t::SHARP_AC;
+ else if (!strcasecmp(str, "SHERWOOD"))
return decode_type_t::SHERWOOD;
- else if (!strcmp(str, "SONY"))
+ else if (!strcasecmp(str, "SONY"))
return decode_type_t::SONY;
- else if (!strcmp(str, "TCL112AC"))
+ else if (!strcasecmp(str, "TCL112AC"))
return decode_type_t::TCL112AC;
- else if (!strcmp(str, "TECO"))
+ else if (!strcasecmp(str, "TECO"))
return decode_type_t::TECO;
- else if (!strcmp(str, "TOSHIBA_AC"))
+ else if (!strcasecmp(str, "TOSHIBA_AC"))
return decode_type_t::TOSHIBA_AC;
- else if (!strcmp(str, "TROTEC"))
+ else if (!strcasecmp(str, "TROTEC"))
return decode_type_t::TROTEC;
- else if (!strcmp(str, "VESTEL_AC"))
+ else if (!strcasecmp(str, "VESTEL_AC"))
return decode_type_t::VESTEL_AC;
- else if (!strcmp(str, "WHIRLPOOL_AC"))
+ else if (!strcasecmp(str, "WHIRLPOOL_AC"))
return decode_type_t::WHIRLPOOL_AC;
- else if (!strcmp(str, "WHYNTER"))
+ else if (!strcasecmp(str, "WHYNTER"))
return decode_type_t::WHYNTER;
// Handle integer values of the type by converting to a string and back again.
decode_type_t result = strToDecodeType(
@@ -219,86 +243,14 @@ decode_type_t strToDecodeType(const char *str) {
return decode_type_t::UNKNOWN;
}
-// Escape any special HTML (unsafe) characters in a string. e.g. anti-XSS.
-// Args:
-// unescaped: A string containing text to make HTML safe.
-// Returns:
-// A string that is HTML safe.
-#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist.
-String htmlEscape(const String unescaped) {
- String result = "";
-#else
-std::string htmlEscape(const std::string unescaped) {
- std::string result = "";
-#endif
- uint16_t ulen = unescaped.length();
- result.reserve(ulen); // The result will be at least the size of input.
- for (size_t i = 0; i < ulen; i++) {
- char c = unescaped[i];
- switch (c) {
- // ';!-"<>={}() are all unsafe.
- case '\'':
- result += F("'");
- break;
- case ';':
- result += F(";");
- break;
- case '!':
- result += F("!");
- break;
- case '-':
- result += F("‐");
- break;
- case '\"':
- result += F(""");
- break;
- case '<':
- result += F("<");
- break;
- case '>':
- result += F(">");
- break;
- case '=':
- result += F("equals;");
- break;
- case '&':
- result += F("&");
- break;
- case '#':
- result += F("#");
- break;
- case '{':
- result += F("{");
- break;
- case '}':
- result += F("}");
- break;
- case '(':
- result += F("(");
- break;
- case ')':
- result += F(")");
- break;
- default:
- result += c;
- }
- }
- return result;
-}
-
// Convert a protocol type (enum etc) to a human readable string.
// Args:
// protocol: Nr. (enum) of the protocol.
// isRepeat: A flag indicating if it is a repeat message of the protocol.
// Returns:
// A string containing the protocol name.
-#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist.
String typeToString(const decode_type_t protocol, const bool isRepeat) {
String result = "";
-#else
-std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
- std::string result = "";
-#endif
switch (protocol) {
case UNUSED:
result = F("UNUSED");
@@ -306,6 +258,9 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
case AIWA_RC_T501:
result = F("AIWA_RC_T501");
break;
+ case AMCOR:
+ result = F("AMCOR");
+ break;
case ARGO:
result = F("ARGO");
break;
@@ -318,6 +273,18 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
case DAIKIN:
result = F("DAIKIN");
break;
+ case DAIKIN128:
+ result = F("DAIKIN128");
+ break;
+ case DAIKIN152:
+ result = F("DAIKIN152");
+ break;
+ case DAIKIN160:
+ result = F("DAIKIN160");
+ break;
+ case DAIKIN176:
+ result = F("DAIKIN176");
+ break;
case DAIKIN2:
result = F("DAIKIN2");
break;
@@ -342,6 +309,9 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
case GLOBALCACHE:
result = F("GLOBALCACHE");
break;
+ case GOODWEATHER:
+ result = F("GOODWEATHER");
+ break;
case GREE:
result = F("GREE");
break;
@@ -360,6 +330,9 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
case HITACHI_AC2:
result = F("HITACHI_AC2");
break;
+ case INAX:
+ result = F("INAX");
+ break;
case JVC:
result = F("JVC");
break;
@@ -405,6 +378,9 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
case MWM:
result = F("MWM");
break;
+ case NEOCLIMA:
+ result = F("NEOCLIMA");
+ break;
case NEC:
result = F("NEC");
break;
@@ -459,6 +435,9 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
case SHARP:
result = F("SHARP");
break;
+ case SHARP_AC:
+ result = F("SHARP_AC");
+ break;
case SHERWOOD:
result = F("SHERWOOD");
break;
@@ -498,7 +477,13 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
// Does the given protocol use a complex state as part of the decode?
bool hasACState(const decode_type_t protocol) {
switch (protocol) {
+ case AMCOR:
+ case ARGO:
case DAIKIN:
+ case DAIKIN128:
+ case DAIKIN152:
+ case DAIKIN160:
+ case DAIKIN176:
case DAIKIN2:
case DAIKIN216:
case ELECTRA_AC:
@@ -514,10 +499,13 @@ bool hasACState(const decode_type_t protocol) {
case MITSUBISHI_HEAVY_88:
case MITSUBISHI_HEAVY_152:
case MWM:
+ case NEOCLIMA:
case PANASONIC_AC:
case SAMSUNG_AC:
+ case SHARP_AC:
case TCL112AC:
case TOSHIBA_AC:
+ case TROTEC:
case WHIRLPOOL_AC:
return true;
default:
@@ -531,7 +519,7 @@ bool hasACState(const decode_type_t protocol) {
// results: A ptr to a decode result.
// Returns:
// A uint16_t containing the length.
-uint16_t getCorrectedRawLength(const decode_results *results) {
+uint16_t getCorrectedRawLength(const decode_results * const results) {
uint16_t extended_length = results->rawlen - 1;
for (uint16_t i = 0; i < results->rawlen - 1; i++) {
uint32_t usecs = results->rawbuf[i] * kRawTick;
@@ -543,13 +531,10 @@ uint16_t getCorrectedRawLength(const decode_results *results) {
// Return a string containing the key values of a decode_results structure
// in a C/C++ code style format.
-#ifdef ARDUINO
-String resultToSourceCode(const decode_results *results) {
+String resultToSourceCode(const decode_results * const results) {
String output = "";
-#else
-std::string resultToSourceCode(const decode_results *results) {
- std::string output = "";
-#endif
+ // Reserve some space for the string to reduce heap fragmentation.
+ output.reserve(1536); // 1.5KB should cover most cases.
// Start declaration
output += F("uint16_t "); // variable type
output += F("rawData["); // array name
@@ -625,15 +610,12 @@ std::string resultToSourceCode(const decode_results *results) {
// Dump out the decode_results structure.
//
-#ifdef ARDUINO
-String resultToTimingInfo(const decode_results *results) {
+String resultToTimingInfo(const decode_results * const results) {
String output = "";
String value = "";
-#else
-std::string resultToTimingInfo(const decode_results *results) {
- std::string output = "";
- std::string value = "";
-#endif
+ // Reserve some space for the string to reduce heap fragmentation.
+ output.reserve(2048); // 2KB should cover most cases.
+ value.reserve(6); // Max value should be 2^17 = 131072
output += F("Raw Timing[");
output += uint64ToString(results->rawlen - 1, 10);
output += F("]:\n");
@@ -657,13 +639,10 @@ std::string resultToTimingInfo(const decode_results *results) {
// Convert the decode_results structure's value/state to simple hexadecimal.
//
-#ifdef ARDUINO
-String resultToHexidecimal(const decode_results *result) {
+String resultToHexidecimal(const decode_results * const result) {
String output = "";
-#else
-std::string resultToHexidecimal(const decode_results *result) {
- std::string output = "";
-#endif
+ // Reserve some space for the string to reduce heap fragmentation.
+ output.reserve(2 * kStateSizeMax); // Should cover worst cases.
if (hasACState(result->decode_type)) {
#if DECODE_AC
for (uint16_t i = 0; result->bits > i * 8; i++) {
@@ -679,13 +658,10 @@ std::string resultToHexidecimal(const decode_results *result) {
// Dump out the decode_results structure.
//
-#ifdef ARDUINO
-String resultToHumanReadableBasic(const decode_results *results) {
+String resultToHumanReadableBasic(const decode_results * const results) {
String output = "";
-#else
-std::string resultToHumanReadableBasic(const decode_results *results) {
- std::string output = "";
-#endif
+ // Reserve some space for the string to reduce heap fragmentation.
+ output.reserve(2 * kStateSizeMax + 50); // Should cover most cases.
// Show Encoding standard
output += F("Encoding : ");
output += typeToString(results->decode_type, results->repeat);
@@ -700,16 +676,43 @@ std::string resultToHumanReadableBasic(const decode_results *results) {
return output;
}
-uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init) {
+// Convert a decode_results into an array suitable for `sendRaw()`.
+// Args:
+// decode: A pointer to an IR decode_results structure that contains a mesg.
+// Returns:
+// A pointer to a dynamically allocated uint16_t sendRaw compatible array.
+// Note:
+// Result needs to be delete[]'ed/free()'ed (deallocated) after use by caller.
+uint16_t* resultToRawArray(const decode_results * const decode) {
+ uint16_t *result = new uint16_t[getCorrectedRawLength(decode)];
+ if (result != NULL) { // The memory was allocated successfully.
+ // Convert the decode data.
+ uint16_t pos = 0;
+ for (uint16_t i = 1; i < decode->rawlen; i++) {
+ uint32_t usecs = decode->rawbuf[i] * kRawTick;
+ while (usecs > UINT16_MAX) { // Keep truncating till it fits.
+ result[pos++] = UINT16_MAX;
+ result[pos++] = 0; // A 0 in a sendRaw() array basically means skip.
+ usecs -= UINT16_MAX;
+ }
+ result[pos++] = usecs;
+ }
+ }
+ return result;
+}
+
+uint8_t sumBytes(const uint8_t * const start, const uint16_t length,
+ const uint8_t init) {
uint8_t checksum = init;
- uint8_t *ptr;
+ const uint8_t *ptr;
for (ptr = start; ptr - start < length; ptr++) checksum += *ptr;
return checksum;
}
-uint8_t xorBytes(uint8_t *start, const uint16_t length, const uint8_t init) {
+uint8_t xorBytes(const uint8_t * const start, const uint16_t length,
+ const uint8_t init) {
uint8_t checksum = init;
- uint8_t *ptr;
+ const uint8_t *ptr;
for (ptr = start; ptr - start < length; ptr++) checksum ^= *ptr;
return checksum;
}
@@ -722,8 +725,8 @@ uint8_t xorBytes(uint8_t *start, const uint16_t length, const uint8_t init) {
// init: Start the counting from this value.
// Returns:
// Nr. of bits found.
-uint16_t countBits(const uint8_t *start, const uint16_t length, const bool ones,
- const uint16_t init) {
+uint16_t countBits(const uint8_t * const start, const uint16_t length,
+ const bool ones, const uint16_t init) {
uint16_t count = init;
for (uint16_t offset = 0; offset < length; offset++)
for (uint8_t currentbyte = *(start + offset);
@@ -766,3 +769,196 @@ uint64_t invertBits(const uint64_t data, const uint16_t nbits) {
// Mask off any unwanted bits and return the result.
return (result & ((1ULL << nbits) - 1));
}
+
+float celsiusToFahrenheit(const float deg) { return (deg * 9.0) / 5.0 + 32.0; }
+
+float fahrenheitToCelsius(const float deg) { return (deg - 32.0) * 5.0 / 9.0; }
+
+namespace irutils {
+ String addLabeledString(const String value, const String label,
+ const bool precomma) {
+ String result = "";
+ if (precomma) result += F(", ");
+ result += label;
+ result += F(": ");
+ return result + value;
+ }
+
+ String addBoolToString(const bool value, const String label,
+ const bool precomma) {
+ return addLabeledString((value ? F("On") : F("Off")), label, precomma);
+ }
+
+ String addIntToString(const uint16_t value, const String label,
+ const bool precomma) {
+ return addLabeledString(uint64ToString(value), label, precomma);
+ }
+
+ String addTempToString(const uint16_t degrees, const bool celsius,
+ const bool precomma) {
+ String result = addIntToString(degrees, F("Temp"), precomma);
+ result += celsius ? 'C' : 'F';
+ return result;
+ }
+
+ String addModeToString(const uint8_t mode, const uint8_t automatic,
+ const uint8_t cool, const uint8_t heat,
+ const uint8_t dry, const uint8_t fan) {
+ String result = addIntToString(mode, F("Mode"));
+ result += F(" (");
+ if (mode == automatic) result += F("AUTO");
+ else if (mode == cool) result += F("COOL");
+ else if (mode == heat) result += F("HEAT");
+ else if (mode == dry) result += F("DRY");
+ else if (mode == fan) result += F("FAN");
+ else
+ result += F("UNKNOWN");
+ return result + ')';
+ }
+
+ String addFanToString(const uint8_t speed, const uint8_t high,
+ const uint8_t low, const uint8_t automatic,
+ const uint8_t quiet, const uint8_t medium) {
+ String result = addIntToString(speed, F("Fan"));
+ result += F(" (");
+ if (speed == high) result += F("High");
+ else if (speed == low) result += F("Low");
+ else if (speed == automatic) result += F("Auto");
+ else if (speed == quiet) result += F("Quiet");
+ else if (speed == medium) result += F("Medium");
+ else
+ result += F("UNKNOWN");
+ return result + ')';
+ }
+
+ // Escape any special HTML (unsafe) characters in a string. e.g. anti-XSS.
+ // Args:
+ // unescaped: A string containing text to make HTML safe.
+ // Returns:
+ // A string that is HTML safe.
+ String htmlEscape(const String unescaped) {
+ String result = "";
+ uint16_t ulen = unescaped.length();
+ result.reserve(ulen); // The result will be at least the size of input.
+ for (size_t i = 0; i < ulen; i++) {
+ char c = unescaped[i];
+ switch (c) {
+ // ';!-"<>={}() are all unsafe.
+ case '\'':
+ result += F("'");
+ break;
+ case ';':
+ result += F(";");
+ break;
+ case '!':
+ result += F("!");
+ break;
+ case '-':
+ result += F("‐");
+ break;
+ case '\"':
+ result += F(""");
+ break;
+ case '<':
+ result += F("<");
+ break;
+ case '>':
+ result += F(">");
+ break;
+ case '=':
+ result += F("equals;");
+ break;
+ case '&':
+ result += F("&");
+ break;
+ case '#':
+ result += F("#");
+ break;
+ case '{':
+ result += F("{");
+ break;
+ case '}':
+ result += F("}");
+ break;
+ case '(':
+ result += F("(");
+ break;
+ case ')':
+ result += F(")");
+ break;
+ default:
+ result += c;
+ }
+ }
+ return result;
+ }
+
+ String msToString(uint32_t const msecs) {
+ uint32_t totalseconds = msecs / 1000;
+ if (totalseconds == 0) return F("Now");
+
+ // Note: uint32_t can only hold up to 45 days, so uint8_t is safe.
+ uint8_t days = totalseconds / (60 * 60 * 24);
+ uint8_t hours = (totalseconds / (60 * 60)) % 24;
+ uint8_t minutes = (totalseconds / 60) % 60;
+ uint8_t seconds = totalseconds % 60;
+
+ String result = "";
+ if (days) {
+ result += uint64ToString(days) + F(" day");
+ if (days > 1) result += 's';
+ }
+ if (hours) {
+ if (result.length()) result += ' ';
+ result += uint64ToString(hours) + F(" hour");
+ if (hours > 1) result += 's';
+ }
+ if (minutes) {
+ if (result.length()) result += ' ';
+ result += uint64ToString(minutes) + F(" minute");
+ if (minutes > 1) result += 's';
+ }
+ if (seconds) {
+ if (result.length()) result += ' ';
+ result += uint64ToString(seconds) + F(" second");
+ if (seconds > 1) result += 's';
+ }
+ return result;
+ }
+
+ String minsToString(const uint16_t mins) {
+ String result = "";
+ result.reserve(5); // 23:59 is the typical worst case.
+ if (mins / 60 < 10) result += '0'; // Zero pad the hours
+ result += uint64ToString(mins / 60) + ':';
+ if (mins % 60 < 10) result += '0'; // Zero pad the minutes.
+ result += uint64ToString(mins % 60);
+ return result;
+ }
+
+ // Sum all the nibbles together in a series of bytes.
+ // Args:
+ // start: PTR to the start of the bytes.
+ // length: Nr of bytes to sum the nibbles of.
+ // init: Starting value of the sum.
+ // Returns:
+ // A uint8_t sum of all the nibbles inc the init.
+ uint8_t sumNibbles(const uint8_t * const start, const uint16_t length,
+ const uint8_t init) {
+ uint8_t sum = init;
+ const uint8_t *ptr;
+ for (ptr = start; ptr - start < length; ptr++)
+ sum += (*ptr >> 4) + (*ptr & 0xF);
+ return sum;
+ }
+
+ uint8_t bcdToUint8(const uint8_t bcd) {
+ if (bcd > 0x99) return 255; // Too big.
+ return (bcd >> 4) * 10 + (bcd & 0xF);
+ }
+
+ uint8_t uint8ToBcd(const uint8_t integer) {
+ if (integer > 99) return 255; // Too big.
+ return ((integer / 10) << 4) + (integer % 10);
+ }
+} // namespace irutils
diff --git a/lib/IRremoteESP8266-2.6.5/src/IRutils.h b/lib/IRremoteESP8266-2.6.5/src/IRutils.h
new file mode 100644
index 000000000..8d4226577
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/IRutils.h
@@ -0,0 +1,64 @@
+#ifndef IRUTILS_H_
+#define IRUTILS_H_
+
+// Copyright 2017 David Conran
+
+#ifndef UNIT_TEST
+#include
+#endif
+#define __STDC_LIMIT_MACROS
+#include
+#ifndef ARDUINO
+#include
+#endif
+#include "IRremoteESP8266.h"
+#include "IRrecv.h"
+
+uint64_t reverseBits(uint64_t input, uint16_t nbits);
+String uint64ToString(uint64_t input, uint8_t base = 10);
+String typeToString(const decode_type_t protocol,
+ const bool isRepeat = false);
+void serialPrintUint64(uint64_t input, uint8_t base = 10);
+String resultToSourceCode(const decode_results * const results);
+String resultToTimingInfo(const decode_results * const results);
+String resultToHumanReadableBasic(const decode_results * const results);
+String resultToHexidecimal(const decode_results * const result);
+bool hasACState(const decode_type_t protocol);
+uint16_t getCorrectedRawLength(const decode_results * const results);
+uint16_t *resultToRawArray(const decode_results * const decode);
+uint8_t sumBytes(const uint8_t * const start, const uint16_t length,
+ const uint8_t init = 0);
+uint8_t xorBytes(const uint8_t * const start, const uint16_t length,
+ const uint8_t init = 0);
+uint16_t countBits(const uint8_t * const start, const uint16_t length,
+ const bool ones = true, const uint16_t init = 0);
+uint16_t countBits(const uint64_t data, const uint8_t length,
+ const bool ones = true, const uint16_t init = 0);
+uint64_t invertBits(const uint64_t data, const uint16_t nbits);
+decode_type_t strToDecodeType(const char *str);
+float celsiusToFahrenheit(const float deg);
+float fahrenheitToCelsius(const float deg);
+namespace irutils {
+ String addBoolToString(const bool value, const String label,
+ const bool precomma = true);
+ String addIntToString(const uint16_t value, const String label,
+ const bool precomma = true);
+ String addLabeledString(const String value, const String label,
+ const bool precomma = true);
+ String addTempToString(const uint16_t degrees, const bool celsius = true,
+ const bool precomma = true);
+ String addModeToString(const uint8_t mode, const uint8_t automatic,
+ const uint8_t cool, const uint8_t heat,
+ const uint8_t dry, const uint8_t fan);
+ String addFanToString(const uint8_t speed, const uint8_t high,
+ const uint8_t low, const uint8_t automatic,
+ const uint8_t quiet, const uint8_t medium);
+ String htmlEscape(const String unescaped);
+ String msToString(uint32_t const msecs);
+ String minsToString(const uint16_t mins);
+ uint8_t sumNibbles(const uint8_t * const start, const uint16_t length,
+ const uint8_t init = 0);
+ uint8_t bcdToUint8(const uint8_t bcd);
+ uint8_t uint8ToBcd(const uint8_t integer);
+} // namespace irutils
+#endif // IRUTILS_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Aiwa.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Aiwa.cpp
similarity index 98%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Aiwa.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Aiwa.cpp
index 617711a99..70dbc85b2 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Aiwa.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Aiwa.cpp
@@ -12,6 +12,8 @@
// Based off the RC-T501 RCU
// Added by David Conran. (Inspired by IRremoteESP8266's implementation:
// https://github.com/z3t0/Arduino-IRremote)
+// Supports:
+// Brand: Aiwa, Model: RC-T501 RCU
const uint16_t kAiwaRcT501PreBits = 26;
const uint16_t kAiwaRcT501PostBits = 1;
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.cpp
new file mode 100644
index 000000000..8c0b73c8c
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.cpp
@@ -0,0 +1,326 @@
+// Copyright 2019 David Conran
+
+// Supports:
+// Brand: Amcor, Model: ADR-853H A/C
+// Brand: Amcor, Model: TAC-495 remote
+// Brand: Amcor, Model: TAC-444 remote
+
+#include "ir_Amcor.h"
+#include
+#include "IRrecv.h"
+#include "IRsend.h"
+#include "IRutils.h"
+
+// Constants
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/385
+const uint16_t kAmcorHdrMark = 8200;
+const uint16_t kAmcorHdrSpace = 4200;
+const uint16_t kAmcorOneMark = 1500;
+const uint16_t kAmcorZeroMark = 600;
+const uint16_t kAmcorOneSpace = kAmcorZeroMark;
+const uint16_t kAmcorZeroSpace = kAmcorOneMark;
+const uint16_t kAmcorFooterMark = 1900;
+const uint16_t kAmcorGap = 34300;
+const uint8_t kAmcorTolerance = 40;
+
+using irutils::addBoolToString;
+using irutils::addModeToString;
+using irutils::addFanToString;
+using irutils::addTempToString;
+
+#if SEND_AMCOR
+// Send a Amcor HVAC formatted message.
+//
+// Args:
+// data: The message to be sent.
+// nbytes: The byte size of the array being sent. typically kAmcorStateLength.
+// repeat: The number of times the message is to be repeated.
+//
+// Status: STABLE / Reported as working.
+//
+void IRsend::sendAmcor(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ // Check if we have enough bytes to send a proper message.
+ if (nbytes < kAmcorStateLength) return;
+ sendGeneric(kAmcorHdrMark, kAmcorHdrSpace, kAmcorOneMark, kAmcorOneSpace,
+ kAmcorZeroMark, kAmcorZeroSpace, kAmcorFooterMark, kAmcorGap,
+ data, nbytes, 38, false, repeat, kDutyDefault);
+}
+#endif
+
+#if DECODE_AMCOR
+// Decode the supplied Amcor HVAC message.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion.
+// Typically kAmcorBits.
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: STABLE / Reported as working.
+//
+bool IRrecv::decodeAmcor(decode_results *results, uint16_t nbits,
+ bool strict) {
+ if (results->rawlen < 2 * nbits + kHeader - 1)
+ return false; // Can't possibly be a valid Amcor message.
+ if (strict && nbits != kAmcorBits)
+ return false; // We expect Amcor to be 64 bits of message.
+
+ uint16_t offset = kStartOffset;
+
+ uint16_t used;
+ // Header + Data Block (64 bits) + Footer
+ used = matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, 64,
+ kAmcorHdrMark, kAmcorHdrSpace,
+ kAmcorOneMark, kAmcorOneSpace,
+ kAmcorZeroMark, kAmcorZeroSpace,
+ kAmcorFooterMark, kAmcorGap, true,
+ kAmcorTolerance, 0, false);
+ if (!used) return false;
+ offset += used;
+
+ if (strict) {
+ if (!IRAmcorAc::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->bits = nbits;
+ results->decode_type = AMCOR;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif
+
+IRAmcorAc::IRAmcorAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
+
+void IRAmcorAc::begin(void) { _irsend.begin(); }
+
+#if SEND_AMCOR
+void IRAmcorAc::send(const uint16_t repeat) {
+ this->checksum(); // Create valid checksum before sending
+ _irsend.sendAmcor(remote_state, kAmcorStateLength, repeat);
+}
+#endif // SEND_AMCOR
+
+uint8_t IRAmcorAc::calcChecksum(const uint8_t state[], const uint16_t length) {
+ return irutils::sumNibbles(state, length - 1);
+}
+
+bool IRAmcorAc::validChecksum(const uint8_t state[], const uint16_t length) {
+ return (state[length - 1] == IRAmcorAc::calcChecksum(state, length));
+}
+
+void IRAmcorAc::checksum(void) {
+ remote_state[kAmcorChecksumByte] = IRAmcorAc::calcChecksum(remote_state,
+ kAmcorStateLength);
+}
+
+void IRAmcorAc::stateReset(void) {
+ for (uint8_t i = 1; i < kAmcorStateLength; i++) remote_state[i] = 0x0;
+ remote_state[0] = 0x01;
+ setFan(kAmcorFanAuto);
+ setMode(kAmcorAuto);
+ setTemp(25); // 25C
+}
+
+uint8_t* IRAmcorAc::getRaw(void) {
+ this->checksum(); // Ensure correct bit array before returning
+ return remote_state;
+}
+
+void IRAmcorAc::setRaw(const uint8_t state[]) {
+ for (uint8_t i = 0; i < kAmcorStateLength; i++) remote_state[i] = state[i];
+}
+
+void IRAmcorAc::on(void) { setPower(true); }
+
+void IRAmcorAc::off(void) { setPower(false); }
+
+void IRAmcorAc::setPower(const bool on) {
+ remote_state[kAmcorPowerByte] &= ~kAmcorPowerMask;
+ remote_state[kAmcorPowerByte] |= (on ? kAmcorPowerOn : kAmcorPowerOff);
+}
+
+bool IRAmcorAc::getPower(void) {
+ return ((remote_state[kAmcorPowerByte] & kAmcorPowerMask) == kAmcorPowerOn);
+}
+
+// Set the temp in deg C
+void IRAmcorAc::setTemp(const uint8_t degrees) {
+ uint8_t temp = std::max(kAmcorMinTemp, degrees);
+ temp = std::min(kAmcorMaxTemp, temp);
+
+ temp <<= 1;
+ remote_state[kAmcorTempByte] &= ~kAmcorTempMask;
+ remote_state[kAmcorTempByte] |= temp;
+}
+
+uint8_t IRAmcorAc::getTemp(void) {
+ return (remote_state[kAmcorTempByte] & kAmcorTempMask) >> 1;
+}
+
+// Maximum Cooling or Hearing
+void IRAmcorAc::setMax(const bool on) {
+ if (on) {
+ switch (getMode()) {
+ case kAmcorCool:
+ setTemp(kAmcorMinTemp);
+ break;
+ case kAmcorHeat:
+ setTemp(kAmcorMaxTemp);
+ break;
+ default: // Not allowed in all other operating modes.
+ return;
+ }
+ remote_state[kAmcorSpecialByte] |= kAmcorMaxMask;
+ } else {
+ remote_state[kAmcorSpecialByte] &= ~kAmcorMaxMask;
+ }
+}
+
+bool IRAmcorAc::getMax(void) {
+ return ((remote_state[kAmcorSpecialByte] & kAmcorMaxMask) == kAmcorMaxMask);
+}
+
+// Set the speed of the fan
+void IRAmcorAc::setFan(const uint8_t speed) {
+ switch (speed) {
+ case kAmcorFanAuto:
+ case kAmcorFanMin:
+ case kAmcorFanMed:
+ case kAmcorFanMax:
+ remote_state[kAmcorModeFanByte] &= ~kAmcorFanMask;
+ remote_state[kAmcorModeFanByte] |= speed << 4;
+ break;
+ default:
+ setFan(kAmcorFanAuto);
+ }
+}
+
+uint8_t IRAmcorAc::getFan(void) {
+ return (remote_state[kAmcorModeFanByte] & kAmcorFanMask) >> 4;
+}
+
+uint8_t IRAmcorAc::getMode(void) {
+ return remote_state[kAmcorModeFanByte] & kAmcorModeMask;
+}
+
+void IRAmcorAc::setMode(const uint8_t mode) {
+ remote_state[kAmcorSpecialByte] &= ~kAmcorVentMask; // Clear the vent setting
+ switch (mode) {
+ case kAmcorFan:
+ remote_state[kAmcorSpecialByte] |= kAmcorVentMask; // Set the vent option
+ // FALL-THRU
+ case kAmcorCool:
+ case kAmcorHeat:
+ case kAmcorDry:
+ case kAmcorAuto:
+ // Mask out bits
+ remote_state[kAmcorModeFanByte] &= ~kAmcorModeMask;
+ // Set the mode at bit positions
+ remote_state[kAmcorModeFanByte] |= mode;
+ return;
+ default:
+ this->setMode(kAmcorAuto);
+ }
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRAmcorAc::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kAmcorCool;
+ case stdAc::opmode_t::kHeat:
+ return kAmcorHeat;
+ case stdAc::opmode_t::kDry:
+ return kAmcorDry;
+ case stdAc::opmode_t::kFan:
+ return kAmcorFan;
+ default:
+ return kAmcorAuto;
+ }
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRAmcorAc::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ case stdAc::fanspeed_t::kLow:
+ return kAmcorFanMin;
+ case stdAc::fanspeed_t::kMedium:
+ return kAmcorFanMed;
+ case stdAc::fanspeed_t::kHigh:
+ case stdAc::fanspeed_t::kMax:
+ return kAmcorFanMax;
+ default:
+ return kAmcorFanAuto;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRAmcorAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kAmcorCool: return stdAc::opmode_t::kCool;
+ case kAmcorHeat: return stdAc::opmode_t::kHeat;
+ case kAmcorDry: return stdAc::opmode_t::kDry;
+ case kAmcorFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRAmcorAc::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kAmcorFanMax: return stdAc::fanspeed_t::kMax;
+ case kAmcorFanMed: return stdAc::fanspeed_t::kMedium;
+ case kAmcorFanMin: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRAmcorAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::AMCOR;
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ // Not supported.
+ result.model = -1;
+ result.turbo = false;
+ result.swingv = stdAc::swingv_t::kOff;
+ result.swingh = stdAc::swingh_t::kOff;
+ result.light = false;
+ result.filter = false;
+ result.econo = false;
+ result.quiet = false;
+ result.clean = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRAmcorAc::toString() {
+ String result = "";
+ result.reserve(70); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kAmcorAuto, kAmcorCool,
+ kAmcorHeat, kAmcorDry, kAmcorFan);
+ result += addFanToString(getFan(), kAmcorFanMax, kAmcorFanMin,
+ kAmcorFanAuto, kAmcorFanAuto,
+ kAmcorFanMed);
+ result += addTempToString(getTemp());
+ result += addBoolToString(getMax(), F("Max"));
+ return result;
+}
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.h b/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.h
new file mode 100644
index 000000000..73beb27a7
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.h
@@ -0,0 +1,118 @@
+// Amcor A/C
+//
+// Copyright 2019 David Conran
+
+#ifndef IR_AMCOR_H_
+#define IR_AMCOR_H_
+
+#define __STDC_LIMIT_MACROS
+#include
+#ifndef UNIT_TEST
+#include
+#endif
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#ifdef UNIT_TEST
+#include "IRsend_test.h"
+#endif
+
+// Supports:
+// Brand: Amcor, Model: ADR-853H A/C
+// Brand: Amcor, Model: TAC-495 remote
+// Brand: Amcor, Model: TAC-444 remote
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/834
+// Kudos:
+// ldellus: For the breakdown and mapping of the bit values.
+
+// Constants
+
+
+// state[1]
+const uint8_t kAmcorModeFanByte = 1;
+// Fan Control
+const uint8_t kAmcorFanMin = 0b001;
+const uint8_t kAmcorFanMed = 0b010;
+const uint8_t kAmcorFanMax = 0b011;
+const uint8_t kAmcorFanAuto = 0b100;
+const uint8_t kAmcorFanMask = 0b01110000;
+// Modes
+const uint8_t kAmcorCool = 0b001;
+const uint8_t kAmcorHeat = 0b010;
+const uint8_t kAmcorFan = 0b011; // Aka "Vent"
+const uint8_t kAmcorDry = 0b100;
+const uint8_t kAmcorAuto = 0b101;
+const uint8_t kAmcorModeMask = 0b00000111;
+
+// state[2]
+const uint8_t kAmcorTempByte = 2;
+// Temperature
+const uint8_t kAmcorMinTemp = 12; // Celsius
+const uint8_t kAmcorMaxTemp = 32; // Celsius
+const uint8_t kAmcorTempMask = 0b01111110;
+
+// state[5]
+// Power
+const uint8_t kAmcorPowerByte = 5;
+const uint8_t kAmcorPowerMask = 0b11110000;
+const uint8_t kAmcorPowerOn = 0b00110000; // 0x30
+const uint8_t kAmcorPowerOff = 0b11000000; // 0xC0
+
+// state[6]
+const uint8_t kAmcorSpecialByte = 6;
+// Max Mode (aka "Lo" in Cool and "Hi" in Heat)
+const uint8_t kAmcorMaxMask = 0b00000011; // 0x03
+// "Vent" Mode
+const uint8_t kAmcorVentMask = 0b11000000; // 0xC0
+
+// state[7]
+// Checksum byte.
+const uint8_t kAmcorChecksumByte = kAmcorStateLength - 1;
+
+// Classes
+class IRAmcorAc {
+ public:
+ explicit IRAmcorAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+ void stateReset();
+#if SEND_AMCOR
+ void send(const uint16_t repeat = kAmcorDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif // SEND_AMCOR
+ void begin();
+ static uint8_t calcChecksum(const uint8_t state[],
+ const uint16_t length = kAmcorStateLength);
+ static bool validChecksum(const uint8_t state[],
+ const uint16_t length = kAmcorStateLength);
+ void setPower(const bool state);
+ bool getPower();
+ void on();
+ void off();
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp();
+ void setMax(const bool on);
+ bool getMax(void);
+ void setFan(const uint8_t speed);
+ uint8_t getFan();
+ void setMode(const uint8_t mode);
+ uint8_t getMode();
+ uint8_t* getRaw();
+ void setRaw(const uint8_t state[]);
+ uint8_t convertMode(const stdAc::opmode_t mode);
+ uint8_t convertFan(const stdAc::fanspeed_t speed);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString();
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ uint8_t remote_state[kAmcorStateLength]; // The state of the IR remote.
+ void checksum(void);
+};
+#endif // IR_AMCOR_H_
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Argo.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Argo.cpp
new file mode 100644
index 000000000..522ede7e6
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Argo.cpp
@@ -0,0 +1,438 @@
+/*
+Node MCU/ESP8266 Sketch to emulate Argo Ulisse 13 DCI remote
+Controls Argo Ulisse 13 DCI A/C
+Copyright 2017 Schmolders
+Copyright 2019 crankyoldgit
+*/
+
+#include "ir_Argo.h"
+#include
+#ifndef UNIT_TEST
+#include
+#endif // UNIT_TEST
+#include "IRremoteESP8266.h"
+#include "IRutils.h"
+
+// Constants
+// using SPACE modulation. MARK is always const 400u
+const uint16_t kArgoHdrMark = 6400;
+const uint16_t kArgoHdrSpace = 3300;
+const uint16_t kArgoBitMark = 400;
+const uint16_t kArgoOneSpace = 2200;
+const uint16_t kArgoZeroSpace = 900;
+const uint32_t kArgoGap = kDefaultMessageGap; // Made up value. Complete guess.
+
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
+#if SEND_ARGO
+// Send an Argo A/C message.
+//
+// Args:
+// data: An array of kArgoStateLength bytes containing the IR command.
+//
+// Status: ALPHA / Untested.
+
+void IRsend::sendArgo(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ // Check if we have enough bytes to send a proper message.
+ if (nbytes < kArgoStateLength) return;
+ // TODO(kaschmo): validate
+ sendGeneric(kArgoHdrMark, kArgoHdrSpace, kArgoBitMark, kArgoOneSpace,
+ kArgoBitMark, kArgoZeroSpace, 0, 0, // No Footer.
+ data, nbytes, 38, false, repeat, kDutyDefault);
+}
+#endif // SEND_ARGO
+
+IRArgoAC::IRArgoAC(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
+
+void IRArgoAC::begin(void) { _irsend.begin(); }
+
+#if SEND_ARGO
+void IRArgoAC::send(const uint16_t repeat) {
+ this->checksum(); // Create valid checksum before sending
+ _irsend.sendArgo(argo, kArgoStateLength, repeat);
+}
+#endif // SEND_ARGO
+
+uint8_t IRArgoAC::calcChecksum(const uint8_t state[], const uint16_t length) {
+ // Corresponds to byte 11 being constant 0b01
+ // Only add up bytes to 9. byte 10 is 0b01 constant anyway.
+ // Assume that argo array is MSB first (left)
+ return sumBytes(state, length - 2, 2);
+}
+
+bool IRArgoAC::validChecksum(const uint8_t state[], const uint16_t length) {
+ return ((state[length - 2] >> 2) + (state[length - 1] << 6)) ==
+ IRArgoAC::calcChecksum(state, length);
+}
+
+void IRArgoAC::checksum(void) {
+ uint8_t sum = IRArgoAC::calcChecksum(argo, kArgoStateLength);
+ // Append sum to end of array
+ // Set const part of checksum bit 10
+ argo[10] = 0b00000010;
+ argo[10] += sum << 2; // Shift up 2 bits and append to byte 10
+ argo[11] = sum >> 6; // Shift down 6 bits and add in two LSBs of bit 11
+}
+
+void IRArgoAC::stateReset(void) {
+ for (uint8_t i = 0; i < kArgoStateLength; i++) argo[i] = 0x0;
+
+ // Argo Message. Store MSB left.
+ // Default message:
+ argo[0] = 0b10101100; // LSB first (as sent) 0b00110101; //const preamble
+ argo[1] = 0b11110101; // LSB first: 0b10101111; //const preamble
+ // Keep payload 2-9 at zero
+ argo[10] = 0b00000010; // Const 01, checksum 6bit
+ argo[11] = 0b00000000; // Checksum 2bit
+
+ this->off();
+ this->setTemp(20);
+ this->setRoomTemp(25);
+ this->setMode(kArgoAuto);
+ this->setFan(kArgoFanAuto);
+}
+
+uint8_t* IRArgoAC::getRaw(void) {
+ this->checksum(); // Ensure correct bit array before returning
+ return argo;
+}
+
+void IRArgoAC::setRaw(const uint8_t state[]) {
+ for (uint8_t i = 0; i < kArgoStateLength; i++) argo[i] = state[i];
+}
+
+void IRArgoAC::on(void) {
+ // Bit 5 of byte 9 is on/off
+ // in MSB first
+ argo[9]|= kArgoPowerBit; // Set ON/OFF bit to 1
+}
+
+void IRArgoAC::off(void) {
+ // in MSB first
+ // bit 5 of byte 9 to off
+ argo[9] &= ~kArgoPowerBit; // Set on/off bit to 0
+}
+
+void IRArgoAC::setPower(const bool on) {
+ if (on)
+ this->on();
+ else
+ this->off();
+}
+
+bool IRArgoAC::getPower(void) { return argo[9] & kArgoPowerBit; }
+
+void IRArgoAC::setMax(const bool on) {
+ if (on)
+ argo[9] |= kArgoMaxBit;
+ else
+ argo[9] &= ~kArgoMaxBit;
+}
+
+bool IRArgoAC::getMax(void) { return argo[9] & kArgoMaxBit; }
+
+// Set the temp in deg C
+// Sending 0 equals +4
+void IRArgoAC::setTemp(const uint8_t degrees) {
+ uint8_t temp = std::max(kArgoMinTemp, degrees);
+ temp = std::min(kArgoMaxTemp, temp);
+
+ // offset 4 degrees. "If I want 12 degrees, I need to send 8"
+ temp -= kArgoTempOffset;
+ // Settemp = Bit 6,7 of byte 2, and bit 0-2 of byte 3
+ // mask out bits
+ // argo[13] & 0x00000100; // mask out ON/OFF Bit
+ argo[2] &= ~kArgoTempLowMask;
+ argo[3] &= ~kArgoTempHighMask;
+
+ // append to bit 6,7
+ argo[2] += temp << 6;
+ // remove lowest to bits and append in 0-2
+ argo[3] += ((temp >> 2) & kArgoTempHighMask);
+}
+
+uint8_t IRArgoAC::getTemp(void) {
+ return (((argo[3] & kArgoTempHighMask) << 2 ) | (argo[2] >> 6)) +
+ kArgoTempOffset;
+}
+
+// Set the speed of the fan
+void IRArgoAC::setFan(const uint8_t fan) {
+ // Mask out bits
+ argo[3] &= ~kArgoFanMask;
+ // Set fan mode at bit positions
+ argo[3] |= (std::min(fan, kArgoFan3) << 3);
+}
+
+uint8_t IRArgoAC::getFan(void) { return (argo[3] & kArgoFanMask) >> 3; }
+
+void IRArgoAC::setFlap(const uint8_t flap) {
+ flap_mode = flap;
+ // TODO(kaschmo): set correct bits for flap mode
+}
+
+uint8_t IRArgoAC::getFlap(void) { return flap_mode; }
+
+uint8_t IRArgoAC::getMode(void) {
+ return (argo[2] & kArgoModeMask) >> 3;
+}
+
+void IRArgoAC::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kArgoCool:
+ case kArgoDry:
+ case kArgoAuto:
+ case kArgoOff:
+ case kArgoHeat:
+ case kArgoHeatAuto:
+ // Mask out bits
+ argo[2] &= ~kArgoModeMask;
+ // Set the mode at bit positions
+ argo[2] |= ((mode << 3) & kArgoModeMask);
+ return;
+ default:
+ this->setMode(kArgoAuto);
+ }
+}
+
+void IRArgoAC::setNight(const bool on) {
+ if (on)
+ // Set bit at night position: bit 2
+ argo[9] |= kArgoNightBit;
+ else
+ argo[9] &= ~kArgoNightBit;
+}
+
+bool IRArgoAC::getNight(void) { return argo[9] & kArgoNightBit; }
+
+void IRArgoAC::setiFeel(const bool on) {
+ if (on)
+ // Set bit at iFeel position: bit 7
+ argo[9] |= kArgoIFeelBit;
+ else
+ argo[9] &= ~kArgoIFeelBit;
+}
+
+bool IRArgoAC::getiFeel(void) { return argo[9] & kArgoIFeelBit; }
+
+void IRArgoAC::setTime(void) {
+ // TODO(kaschmo): use function call from checksum to set time first
+}
+
+void IRArgoAC::setRoomTemp(const uint8_t degrees) {
+ uint8_t temp = std::min(degrees, kArgoMaxRoomTemp);
+ temp = std::max(temp, kArgoTempOffset);
+ temp -= kArgoTempOffset;;
+ // Mask out bits
+ argo[3] &= ~kArgoRoomTempLowMask;
+ argo[4] &= ~kArgoRoomTempHighMask;
+
+ argo[3] += temp << 5; // Append to bit 5,6,7
+ argo[4] += temp >> 3; // Remove lowest 3 bits and append in 0,1
+}
+
+uint8_t IRArgoAC::getRoomTemp(void) {
+ return ((argo[4] & kArgoRoomTempHighMask) << 3 | (argo[3] >> 5)) +
+ kArgoTempOffset;
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRArgoAC::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kArgoCool;
+ case stdAc::opmode_t::kHeat:
+ return kArgoHeat;
+ case stdAc::opmode_t::kDry:
+ return kArgoDry;
+ case stdAc::opmode_t::kOff:
+ return kArgoOff;
+ // No fan mode.
+ default:
+ return kArgoAuto;
+ }
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRArgoAC::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ case stdAc::fanspeed_t::kLow:
+ return kArgoFan1;
+ case stdAc::fanspeed_t::kMedium:
+ return kArgoFan2;
+ case stdAc::fanspeed_t::kHigh:
+ case stdAc::fanspeed_t::kMax:
+ return kArgoFan3;
+ default:
+ return kArgoFanAuto;
+ }
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRArgoAC::convertSwingV(const stdAc::swingv_t position) {
+ switch (position) {
+ case stdAc::swingv_t::kHighest:
+ return kArgoFlapFull;
+ case stdAc::swingv_t::kHigh:
+ return kArgoFlap5;
+ case stdAc::swingv_t::kMiddle:
+ return kArgoFlap4;
+ case stdAc::swingv_t::kLow:
+ return kArgoFlap3;
+ case stdAc::swingv_t::kLowest:
+ return kArgoFlap1;
+ default:
+ return kArgoFlapAuto;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRArgoAC::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kArgoCool: return stdAc::opmode_t::kCool;
+ case kArgoHeat: return stdAc::opmode_t::kHeat;
+ case kArgoDry: return stdAc::opmode_t::kDry;
+ // No fan mode.
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRArgoAC::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kArgoFan3: return stdAc::fanspeed_t::kMax;
+ case kArgoFan2: return stdAc::fanspeed_t::kMedium;
+ case kArgoFan1: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRArgoAC::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::ARGO;
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.turbo = this->getMax();
+ result.sleep = this->getNight() ? 0 : -1;
+ // Not supported.
+ result.model = -1; // Not supported.
+ result.swingv = stdAc::swingv_t::kOff;
+ result.swingh = stdAc::swingh_t::kOff;
+ result.light = false;
+ result.filter = false;
+ result.econo = false;
+ result.quiet = false;
+ result.clean = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRArgoAC::toString() {
+ String result = "";
+ result.reserve(100); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addIntToString(getMode(), F("Mode"));
+ switch (getMode()) {
+ case kArgoAuto:
+ result += F(" (AUTO)");
+ break;
+ case kArgoCool:
+ result += F(" (COOL)");
+ break;
+ case kArgoHeat:
+ result += F(" (HEAT)");
+ break;
+ case kArgoDry:
+ result += F(" (DRY)");
+ break;
+ case kArgoHeatAuto:
+ result += F(" (HEATAUTO)");
+ break;
+ case kArgoOff:
+ result += F(" (OFF)");
+ break;
+ default:
+ result += F(" (UNKNOWN)");
+ }
+ result += addIntToString(getFan(), F("Fan"));
+ switch (getFan()) {
+ case kArgoFanAuto:
+ result += F(" (AUTO)");
+ break;
+ case kArgoFan3:
+ result += F(" (MAX)");
+ break;
+ case kArgoFan1:
+ result += F(" (MIN)");
+ break;
+ case kArgoFan2:
+ result += F(" (MED)");
+ break;
+ default:
+ result += F(" (UNKNOWN)");
+ }
+ result += addTempToString(getTemp());
+ result += F(", Room ");
+ result += addTempToString(getRoomTemp(), true, false);
+ result += addBoolToString(getMax(), F("Max"));
+ result += addBoolToString(getiFeel(), F("iFeel"));
+ result += addBoolToString(getNight(), F("Night"));
+ return result;
+}
+
+#if DECODE_ARGO
+// Decode the supplied Argo message.
+//
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: The number of data bits to expect. Typically kArgoBits.
+// strict: Flag indicating if we should perform strict matching.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: ALPHA / Probably doesn't work.
+//
+// Note:
+// This decoder is based soley off sendArgo(). We have no actual captures
+// to test this against. If you have one of these units, please let us know.
+bool IRrecv::decodeArgo(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ if (strict && nbits != kArgoBits) return false;
+
+ uint16_t offset = kStartOffset;
+
+ // Match Header + Data
+ if (!matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kArgoHdrMark, kArgoHdrSpace,
+ kArgoBitMark, kArgoOneSpace,
+ kArgoBitMark, kArgoZeroSpace,
+ 0, 0, // Footer (None, allegedly. This seems very wrong.)
+ true, _tolerance, 0, false)) return false;
+
+ // Compliance
+ // Verify we got a valid checksum.
+ if (strict && !IRArgoAC::validChecksum(results->state)) return false;
+ // Success
+ results->decode_type = decode_type_t::ARGO;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_ARGO
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Argo.h b/lib/IRremoteESP8266-2.6.5/src/ir_Argo.h
similarity index 52%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Argo.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Argo.h
index 883c2ddfd..49c8c42e5 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Argo.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Argo.h
@@ -1,9 +1,15 @@
-/* Copyright 2017 Schmolders
+// Copyright 2017 Schmolders
// Adds support for Argo Ulisse 13 DCI Mobile Split ACs.
-*/
+
+// Supports:
+// Brand: Argo, Model: Ulisse 13 DCI Mobile Split A/C
+
#ifndef IR_ARGO_H_
#define IR_ARGO_H_
+#ifndef UNIT_TEST
+#include
+#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
#ifdef UNIT_TEST
@@ -33,19 +39,42 @@
// Constants. Store MSB left.
-const uint8_t kArgoCoolOn = 0; // 0b000
-const uint8_t kArgoCoolOff = 3; // 0b110
-const uint8_t kArgoCoolAuto = 2; // 0b010
-const uint8_t kArgoCoolHum = 1; // 0b100
-const uint8_t kArgoHeatOn = 0; // 0b001
-const uint8_t kArgoHeatAuto = 1; // 0b101
-const uint8_t kArgoHeatBlink = 2; // 0b011 // ??no idea what mode that is
-const uint8_t kArgoMinTemp = 10; // Celsius offset +4
-const uint8_t kArgoMaxTemp = 32; // Celsius
+// byte[2]
+const uint8_t kArgoHeatBit = 0b00100000;
+const uint8_t kArgoModeMask = 0b00111000;
+const uint8_t kArgoTempLowMask = 0b11000000;
+const uint8_t kArgoCool = 0b000; // 0b000 (LSB) 0
+const uint8_t kArgoDry = 0b001; // 0b100 (LSB) 1
+const uint8_t kArgoAuto = 0b010; // 0b010 (LSB) 2
+const uint8_t kArgoOff = 0b011; // 0b110 (LSB) 3
+const uint8_t kArgoHeat = 0b100; // 0b001 (LSB) 4
+const uint8_t kArgoHeatAuto = 0b101; // 0b101 (LSB) 5
+// ?no idea what mode that is
+const uint8_t kArgoHeatBlink = 0b110; // 0b011 (LSB) 6
+
+// byte[3]
+const uint8_t kArgoTempHighMask = 0b00000111;
+const uint8_t kArgoFanMask = 0b00011000;
+const uint8_t kArgoRoomTempLowMask = 0b11100000;
const uint8_t kArgoFanAuto = 0; // 0b00
const uint8_t kArgoFan3 = 3; // 0b11
const uint8_t kArgoFan2 = 2; // 0b01
const uint8_t kArgoFan1 = 1; // 0b10
+
+// byte[4]
+const uint8_t kArgoRoomTempHighMask = 0b00000011;
+const uint8_t kArgoTempOffset = 4;
+const uint8_t kArgoMaxRoomTemp = ((1 << 5) - 1) + kArgoTempOffset; // 35C
+
+// byte[9]
+const uint8_t kArgoPowerBit = 0b00100000;
+const uint8_t kArgoMaxBit = 0b00001000;
+const uint8_t kArgoNightBit = 0b00000100;
+const uint8_t kArgoIFeelBit = 0b10000000;
+
+const uint8_t kArgoMinTemp = 10; // Celsius offset +4
+const uint8_t kArgoMaxTemp = 32; // Celsius
+
const uint8_t kArgoFlapAuto = 0; // 0b000
const uint8_t kArgoFlap1 = 1; // 0b100
const uint8_t kArgoFlap2 = 2; // 0b010
@@ -81,49 +110,58 @@ const uint8_t kArgoFlapFull = 7; // 0b111
class IRArgoAC {
public:
- explicit IRArgoAC(uint16_t pin);
+ explicit IRArgoAC(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
#if SEND_ARGO
void send(const uint16_t repeat = kArgoDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_ARGO
- void begin();
- void on();
- void off();
+ void begin(void);
+ void on(void);
+ void off(void);
- void setPower(bool state);
- uint8_t getPower();
+ void setPower(const bool on);
+ bool getPower(void);
- void setTemp(uint8_t temp);
- uint8_t getTemp();
+ void setTemp(const uint8_t degrees);
+ uint8_t getTemp(void);
- void setFan(uint8_t fan);
- uint8_t getFan();
+ void setFan(const uint8_t fan);
+ uint8_t getFan(void);
- void setFlap(uint8_t flap);
- uint8_t getFlap();
+ void setFlap(const uint8_t flap);
+ uint8_t getFlap(void);
- void setCoolMode(uint8_t mode);
- uint8_t getCoolMode();
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
- void setHeatMode(uint8_t mode);
- uint8_t getHeatMode();
- uint8_t getMode();
+ void setMax(const bool on);
+ bool getMax(void);
- void setMax(bool state);
- bool getMax();
+ void setNight(const bool on);
+ bool getNight(void);
- void setNight(bool state);
- bool getNight();
+ void setiFeel(const bool on);
+ bool getiFeel(void);
- void setiFeel(bool state);
- bool getiFeel();
+ void setTime(void);
+ void setRoomTemp(const uint8_t degrees);
+ uint8_t getRoomTemp(void);
- void setTime();
- void setRoomTemp(uint8_t temp);
-
- uint8_t* getRaw();
- uint8_t convertFan(const stdAc::fanspeed_t speed);
- uint8_t convertSwingV(const stdAc::swingv_t position);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t state[]);
+ static uint8_t calcChecksum(const uint8_t state[],
+ const uint16_t length = kArgoStateLength);
+ static bool validChecksum(const uint8_t state[],
+ const uint16_t length = kArgoStateLength);
+ static uint8_t convertMode(const stdAc::opmode_t mode);
+ static uint8_t convertFan(const stdAc::fanspeed_t speed);
+ static uint8_t convertSwingV(const stdAc::swingv_t position);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString();
#ifndef UNIT_TEST
private:
@@ -133,20 +171,13 @@ class IRArgoAC {
#endif
// # of bytes per command
uint8_t argo[kArgoStateLength]; // Defined in IRremoteESP8266.h
- void stateReset();
- void checksum();
+ void stateReset(void);
+ void checksum(void);
// Attributes
- uint8_t set_temp;
- uint8_t fan_mode;
uint8_t flap_mode;
- uint8_t ac_state;
- uint8_t ac_mode; // heat 1, cool 0
uint8_t heat_mode;
uint8_t cool_mode;
- uint8_t night_mode; // on/off
- uint8_t max_mode; // on/off
- uint8_t ifeel_mode; // on/off
};
#endif // IR_ARGO_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Carrier.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Carrier.cpp
similarity index 67%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Carrier.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Carrier.cpp
index 350d61cc1..e31ddd55f 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Carrier.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Carrier.cpp
@@ -1,23 +1,20 @@
// Copyright 2018 David Conran
+// Supports:
+// Brand: Carrier/Surrey, Model: 42QG5A55970 remote
+// Brand: Carrier/Surrey, Model: 619EGX0090E0 A/C
+// Brand: Carrier/Surrey, Model: 619EGX0120E0 A/C
+// Brand: Carrier/Surrey, Model: 619EGX0180E0 A/C
+// Brand: Carrier/Surrey, Model: 619EGX0220E0 A/C
+// Brand: Carrier/Surrey, Model: 53NGK009/012 Inverter
+
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
-// CCCCC AAA RRRRRR RRRRRR IIIII EEEEEEE RRRRRR
-// CC C AAAAA RR RR RR RR III EE RR RR
-// CC AA AA RRRRRR RRRRRR III EEEEE RRRRRR
-// CC C AAAAAAA RR RR RR RR III EE RR RR
-// CCCCC AA AA RR RR RR RR IIIII EEEEEEE RR RR
-
-// Suits Carrier/Surrey HVAC models:
-// 42QG5A55970 (remote)
-// 619EGX0090E0 / 619EGX0120E0 / 619EGX0180E0 / 619EGX0220E0 (indoor units)
-// 53NGK009/012 (inverter)
-
// Constants
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/385
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/385
const uint16_t kCarrierAcHdrMark = 8532;
const uint16_t kCarrierAcHdrSpace = 4228;
const uint16_t kCarrierAcBitMark = 628;
@@ -77,22 +74,16 @@ bool IRrecv::decodeCarrierAC(decode_results *results, uint16_t nbits,
for (uint8_t i = 0; i < 3; i++) {
prev_data = data;
- // Header
- if (!matchMark(results->rawbuf[offset++], kCarrierAcHdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kCarrierAcHdrSpace))
- return false;
- // Data
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits, kCarrierAcBitMark,
- kCarrierAcOneSpace, kCarrierAcBitMark, kCarrierAcZeroSpace);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
- // Footer
- if (!matchMark(results->rawbuf[offset++], kCarrierAcBitMark)) return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kCarrierAcGap))
- return false;
+ // Match Header + Data + Footer
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kCarrierAcHdrMark, kCarrierAcHdrSpace,
+ kCarrierAcBitMark, kCarrierAcOneSpace,
+ kCarrierAcBitMark, kCarrierAcZeroSpace,
+ kCarrierAcBitMark, kCarrierAcGap, true);
+ if (!used) return false;
+ offset += used;
// Compliance.
if (strict) {
// Check if the data is an inverted copy of the previous data.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Coolix.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Coolix.cpp
similarity index 71%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Coolix.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Coolix.cpp
index 2659a1d88..616b417ce 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Coolix.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Coolix.cpp
@@ -1,5 +1,5 @@
// Copyright bakrus
-// Copyright 2017 David Conran
+// Copyright 2017,2019 David Conran
#include "ir_Coolix.h"
#include
@@ -10,18 +10,16 @@
#include "IRsend.h"
#include "IRutils.h"
-// CCCCC OOOOO OOOOO LL IIIII XX XX
-// CC C OO OO OO OO LL III XX XX
-// CC OO OO OO OO LL III XXXX
-// CC C OO OO OO OO LL III XX XX
-// CCCCC OOOO0 OOOO0 LLLLLLL IIIII XX XX
-
// Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit
//
// Supports:
-// RG57K7(B)/BGEF remote control for Beko BINR 070/071 split-type aircon.
+// Brand: Beko, Model: RG57K7(B)/BGEF Remote
+// Brand: Beko, Model: BINR 070/071 split-type A/C
+// Brand: Midea, Model: RG52D/BGE Remote
+// Brand: Midea, Model: MS12FU-10HRDN1-QRD0GW(B) A/C
+// Brand: Midea, Model: MSABAU-07HRFN1-QRD0GW A/C (circa 2016)
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/484
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/484
// Constants
// Pulse parms are *50-100 for the Mark and *50+100 for the space
@@ -41,6 +39,12 @@ const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick;
const uint16_t kCoolixMinGapTicks = kCoolixHdrMarkTicks + kCoolixZeroSpaceTicks;
const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick;
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
#if SEND_COOLIX
// Send a Coolix message
//
@@ -83,6 +87,7 @@ void IRsend::sendCOOLIX(uint64_t data, uint16_t nbits, uint16_t repeat) {
mark(kCoolixBitMark);
space(kCoolixMinGap); // Pause before repeating
}
+ space(kDefaultMessageGap);
}
#endif
@@ -90,8 +95,10 @@ void IRsend::sendCOOLIX(uint64_t data, uint16_t nbits, uint16_t repeat) {
// Supports:
// RG57K7(B)/BGEF remote control for Beko BINR 070/071 split-type aircon.
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/484
-IRCoolixAC::IRCoolixAC(uint16_t pin) : _irsend(pin) { stateReset(); }
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/484
+IRCoolixAC::IRCoolixAC(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
void IRCoolixAC::stateReset() { setRaw(kCoolixDefaultState); }
@@ -200,6 +207,14 @@ void IRCoolixAC::setPower(const bool power) {
}
}
+void IRCoolixAC::on(void) {
+ this->setPower(true);
+}
+
+void IRCoolixAC::off(void) {
+ this->setPower(false);
+}
+
bool IRCoolixAC::getSwing() { return remote_state == kCoolixSwing; }
void IRCoolixAC::setSwing() {
@@ -260,18 +275,30 @@ void IRCoolixAC::clearSensorTemp() {
void IRCoolixAC::setMode(const uint8_t mode) {
uint32_t actualmode = mode;
+ switch (actualmode) {
+ case kCoolixAuto:
+ case kCoolixDry:
+ if (this->getFan() == kCoolixFanAuto)
+ // No kCoolixFanAuto in Dry/Auto mode.
+ this->setFan(kCoolixFanAuto0, false);
+ break;
+ case kCoolixCool:
+ case kCoolixHeat:
+ case kCoolixFan:
+ if (this->getFan() == kCoolixFanAuto0)
+ // kCoolixFanAuto0 only in Dry/Auto mode.
+ this->setFan(kCoolixFanAuto, false);
+ break;
+ default: // Anything else, go with Auto mode.
+ this->setMode(kCoolixAuto);
+ return;
+ }
// Fan mode is a special case of Dry.
if (mode == kCoolixFan) actualmode = kCoolixDry;
- switch (actualmode) {
- case kCoolixCool:
- case kCoolixAuto:
- case kCoolixHeat:
- case kCoolixDry:
- recoverSavedState();
- remote_state = (remote_state & ~kCoolixModeMask) | (actualmode << 2);
- // Force the temp into a known-good state.
- setTemp(getTemp());
- }
+ recoverSavedState();
+ remote_state = (remote_state & ~kCoolixModeMask) | (actualmode << 2);
+ // Force the temp into a known-good state.
+ setTemp(getTemp());
if (mode == kCoolixFan) setTempRaw(kCoolixFanTempCode);
}
@@ -286,15 +313,33 @@ uint8_t IRCoolixAC::getFan() {
return (getNormalState() & kCoolixFanMask) >> 13;
}
-void IRCoolixAC::setFan(const uint8_t speed) {
+void IRCoolixAC::setFan(const uint8_t speed, const bool modecheck) {
recoverSavedState();
uint8_t newspeed = speed;
switch (speed) {
+ case kCoolixFanAuto: // Dry & Auto mode can't have this speed.
+ if (modecheck) {
+ switch (this->getMode()) {
+ case kCoolixAuto:
+ case kCoolixDry:
+ newspeed = kCoolixFanAuto0;
+ }
+ }
+ break;
+ case kCoolixFanAuto0: // Only Dry & Auto mode can have this speed.
+ if (modecheck) {
+ switch (this->getMode()) {
+ case kCoolixAuto:
+ case kCoolixDry:
+ break;
+ default:
+ newspeed = kCoolixFanAuto;
+ }
+ }
+ break;
case kCoolixFanMin:
case kCoolixFanMed:
case kCoolixFanMax:
- case kCoolixFanAuto:
- case kCoolixFanAuto0:
case kCoolixFanZoneFollow:
case kCoolixFanFixed:
break;
@@ -337,21 +382,88 @@ uint8_t IRCoolixAC::convertFan(const stdAc::fanspeed_t speed) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRCoolixAC::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kCoolixCool: return stdAc::opmode_t::kCool;
+ case kCoolixHeat: return stdAc::opmode_t::kHeat;
+ case kCoolixDry: return stdAc::opmode_t::kDry;
+ case kCoolixFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRCoolixAC::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kCoolixFanMax: return stdAc::fanspeed_t::kMax;
+ case kCoolixFanMed: return stdAc::fanspeed_t::kMedium;
+ case kCoolixFanMin: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent. Utilise the previous
+// state if supplied.
+stdAc::state_t IRCoolixAC::toCommon(const stdAc::state_t *prev) {
+ stdAc::state_t result;
+ // Start with the previous state if given it.
+ if (prev != NULL) {
+ result = *prev;
+ } else {
+ // Set defaults for non-zero values that are not implicitly set for when
+ // there is no previous state.
+ result.swingv = stdAc::swingv_t::kOff;
+ result.sleep = -1;
+ }
+ // Not supported.
+ result.model = -1; // No models used.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.quiet = false;
+ result.econo = false;
+ result.filter = false;
+ result.beep = false;
+ result.clock = -1;
+
+ // Supported.
+ result.protocol = decode_type_t::COOLIX;
+ result.celsius = true;
+ result.power = this->getPower();
+ // Power off state no other state info. Use the previous state if we have it.
+ if (!result.power) return result;
+ // Handle the special single command (Swing/Turbo/Light/Clean/Sleep) toggle
+ // messages. These have no other state info so use the rest of the previous
+ // state if we have it for them.
+ if (this->getSwing()) {
+ result.swingv = result.swingv != stdAc::swingv_t::kOff ?
+ stdAc::swingv_t::kOff : stdAc::swingv_t::kAuto; // Invert swing.
+ return result;
+ } else if (this->getTurbo()) {
+ result.turbo = !result.turbo;
+ return result;
+ } else if (this->getLed()) {
+ result.light = !result.light;
+ return result;
+ } else if (this->getClean()) {
+ result.clean = !result.clean;
+ return result;
+ } else if (this->getSleep()) {
+ result.sleep = result.sleep >= 0 ? -1 : 0; // Invert sleep.
+ return result;
+ }
+ // Back to "normal" stateful messages.
+ result.mode = this->toCommonMode(this->getMode());
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
String IRCoolixAC::toString() {
String result = "";
-#else
-std::string IRCoolixAC::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower()) {
- result += F("On");
- } else {
- result += F("Off");
- return result; // If it's off, there is no other info.
- }
+ result.reserve(100); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ if (!getPower()) return result; // If it's off, there is no other info.
// Special modes.
if (getSwing()) {
result += F(", Swing: Toggle");
@@ -373,29 +485,10 @@ std::string IRCoolixAC::toString() {
result += F(", Clean: Toggle");
return result;
}
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kCoolixAuto:
- result += F(" (AUTO)");
- break;
- case kCoolixCool:
- result += F(" (COOL)");
- break;
- case kCoolixHeat:
- result += F(" (HEAT)");
- break;
- case kCoolixDry:
- result += F(" (DRY)");
- break;
- case kCoolixFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Fan: ");
- result += uint64ToString(getFan());
+ result += addModeToString(getMode(), kCoolixAuto,
+ kCoolixCool, kCoolixHeat,
+ kCoolixDry, kCoolixFan);
+ result += addIntToString(getFan(), F("Fan"));
switch (getFan()) {
case kCoolixFanAuto:
result += F(" (AUTO)");
@@ -421,16 +514,9 @@ std::string IRCoolixAC::toString() {
default:
result += F(" (UNKNOWN)");
}
- if (getMode() != kCoolixFan) { // Fan mode doesn't have a temperature.
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += 'C';
- }
- result += F(", Zone Follow: ");
- if (getZoneFollow())
- result += F("On");
- else
- result += F("Off");
+ // Fan mode doesn't have a temperature.
+ if (getMode() != kCoolixFan) result += addTempToString(getTemp());
+ result += addBoolToString(getZoneFollow(), F("Zone Follow"));
result += F(", Sensor Temp: ");
if (getSensorTemp() > kCoolixSensorTempMax)
result += F("Ignored");
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Coolix.h b/lib/IRremoteESP8266-2.6.5/src/ir_Coolix.h
similarity index 84%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Coolix.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Coolix.h
index d85db98d7..0c2e44676 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Coolix.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Coolix.h
@@ -9,8 +9,6 @@
#include
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -18,16 +16,14 @@
#include "IRsend_test.h"
#endif
-// CCCCC OOOOO OOOOO LL IIIII XX XX
-// CC C OO OO OO OO LL III XX XX
-// CC OO OO OO OO LL III XXXX
-// CC C OO OO OO OO LL III XX XX
-// CCCCC OOOO0 OOOO0 LLLLLLL IIIII XX XX
-
// Supports:
-// RG57K7(B)/BGEF remote control for Beko BINR 070/071 split-type aircon.
+// Brand: Beko, Model: RG57K7(B)/BGEF Remote
+// Brand: Beko, Model: BINR 070/071 split-type A/C
+// Brand: Midea, Model: RG52D/BGE Remote
+// Brand: Midea, Model: MS12FU-10HRDN1-QRD0GW(B) A/C
+// Brand: Midea, Model: MSABAU-07HRFN1-QRD0GW A/C (circa 2016)
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/484
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/484
// Kudos:
// Hamper: For the breakdown and mapping of the bit values.
@@ -90,11 +86,13 @@ const uint32_t kCoolixDefaultState = 0b101100101011111111001000; // 0xB2BFC8
// Classes
class IRCoolixAC {
public:
- explicit IRCoolixAC(uint16_t pin);
+ explicit IRCoolixAC(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
void stateReset();
#if SEND_COOLIX
void send(const uint16_t repeat = kCoolixDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_COOLIX
void begin();
void on();
@@ -106,7 +104,7 @@ class IRCoolixAC {
void setSensorTemp(const uint8_t desired);
uint8_t getSensorTemp();
void clearSensorTemp();
- void setFan(const uint8_t fan);
+ void setFan(const uint8_t speed, const bool modecheck = true);
uint8_t getFan();
void setMode(const uint8_t mode);
uint8_t getMode();
@@ -125,11 +123,10 @@ class IRCoolixAC {
void setRaw(const uint32_t new_code);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(const stdAc::state_t *prev = NULL);
String toString();
-#else
- std::string toString();
-#endif
#ifndef UNIT_TEST
private:
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.cpp
new file mode 100644
index 000000000..317526f5e
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.cpp
@@ -0,0 +1,3069 @@
+/*
+An Arduino sketch to emulate IR Daikin ARC433** & ARC477A1 remote control unit
+Read more at:
+http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/
+
+Copyright 2016 sillyfrog
+Copyright 2017 sillyfrog, crankyoldgit
+Copyright 2018-2019 crankyoldgit
+Copyright 2019 pasna (IRDaikin160 class / Daikin176 class)
+*/
+
+#include "ir_Daikin.h"
+#include
+#ifndef ARDUINO
+#include
+#endif
+#include "IRrecv.h"
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#ifdef UNIT_TEST
+#include "IRsend_test.h"
+#endif
+#include "IRutils.h"
+
+// Constants
+// Ref:
+// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
+// http://rdlab.cdmt.vn/project-2013/daikin-ir-protocol
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/582
+
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+using irutils::addFanToString;
+using irutils::bcdToUint8;
+using irutils::minsToString;
+using irutils::sumNibbles;
+using irutils::uint8ToBcd;
+
+
+#if SEND_DAIKIN
+// Send a Daikin A/C message.
+//
+// Args:
+// data: An array of kDaikinStateLength bytes containing the IR command.
+//
+// Status: STABLE
+//
+// Ref:
+// IRDaikinESP.cpp
+// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
+// https://github.com/blafois/Daikin-IR-Reverse
+void IRsend::sendDaikin(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ if (nbytes < kDaikinStateLengthShort)
+ return; // Not enough bytes to send a proper message.
+
+ for (uint16_t r = 0; r <= repeat; r++) {
+ uint16_t offset = 0;
+ // Send the header, 0b00000
+ sendGeneric(0, 0, // No header for the header
+ kDaikinBitMark, kDaikinOneSpace, kDaikinBitMark,
+ kDaikinZeroSpace, kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
+ (uint64_t)0b00000, kDaikinHeaderLength, 38, false, 0, 50);
+ // Data #1
+ if (nbytes < kDaikinStateLength) { // Are we using the legacy size?
+ // Do this as a constant to save RAM and keep in flash memory
+ sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
+ kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
+ kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
+ kDaikinFirstHeader64, 64, 38, false, 0, 50);
+ } else { // We are using the newer/more correct size.
+ sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
+ kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
+ kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
+ data, kDaikinSection1Length, 38, false, 0, 50);
+ offset += kDaikinSection1Length;
+ }
+ // Data #2
+ sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
+ kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
+ kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
+ data + offset, kDaikinSection2Length, 38, false, 0, 50);
+ offset += kDaikinSection2Length;
+ // Data #3
+ sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
+ kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
+ kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
+ data + offset, nbytes - offset, 38, false, 0, 50);
+ }
+}
+#endif // SEND_DAIKIN
+
+IRDaikinESP::IRDaikinESP(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
+
+void IRDaikinESP::begin(void) { _irsend.begin(); }
+
+#if SEND_DAIKIN
+void IRDaikinESP::send(const uint16_t repeat) {
+ this->checksum();
+ _irsend.sendDaikin(remote, kDaikinStateLength, repeat);
+}
+#endif // SEND_DAIKIN
+
+// Verify the checksums are valid for a given state.
+// Args:
+// state: The array to verify the checksums of.
+// length: The size of the state.
+// Returns:
+// A boolean.
+bool IRDaikinESP::validChecksum(uint8_t state[], const uint16_t length) {
+ // Data #1
+ if (length < kDaikinSection1Length ||
+ state[kDaikinByteChecksum1] != sumBytes(state, kDaikinSection1Length - 1))
+ return false;
+ // Data #2
+ if (length < kDaikinSection1Length + kDaikinSection2Length ||
+ state[kDaikinByteChecksum2] != sumBytes(state + kDaikinSection1Length,
+ kDaikinSection2Length - 1))
+ return false;
+ // Data #3
+ if (length < kDaikinSection1Length + kDaikinSection2Length + 2 ||
+ state[length - 1] != sumBytes(state + kDaikinSection1Length +
+ kDaikinSection2Length,
+ length - (kDaikinSection1Length +
+ kDaikinSection2Length) - 1))
+ return false;
+ return true;
+}
+
+// Calculate and set the checksum values for the internal state.
+void IRDaikinESP::checksum(void) {
+ remote[kDaikinByteChecksum1] = sumBytes(remote, kDaikinSection1Length - 1);
+ remote[kDaikinByteChecksum2] = sumBytes(remote + kDaikinSection1Length,
+ kDaikinSection2Length - 1);
+ remote[kDaikinByteChecksum3] = sumBytes(remote + kDaikinSection1Length +
+ kDaikinSection2Length,
+ kDaikinSection3Length - 1);
+}
+
+void IRDaikinESP::stateReset(void) {
+ for (uint8_t i = 0; i < kDaikinStateLength; i++) remote[i] = 0x0;
+
+ remote[0] = 0x11;
+ remote[1] = 0xDA;
+ remote[2] = 0x27;
+ remote[4] = 0xC5;
+ // remote[7] is a checksum byte, it will be set by checksum().
+
+ remote[8] = 0x11;
+ remote[9] = 0xDA;
+ remote[10] = 0x27;
+ remote[12] = 0x42;
+ // remote[15] is a checksum byte, it will be set by checksum().
+ remote[16] = 0x11;
+ remote[17] = 0xDA;
+ remote[18] = 0x27;
+ remote[21] = 0x49;
+ remote[22] = 0x1E;
+ remote[24] = 0xB0;
+ remote[27] = 0x06;
+ remote[28] = 0x60;
+ remote[31] = 0xC0;
+ // remote[34] is a checksum byte, it will be set by checksum().
+ this->checksum();
+}
+
+uint8_t *IRDaikinESP::getRaw(void) {
+ this->checksum(); // Ensure correct settings before sending.
+ return remote;
+}
+
+void IRDaikinESP::setRaw(const uint8_t new_code[], const uint16_t length) {
+ uint8_t offset = 0;
+ if (length == kDaikinStateLengthShort) { // Handle the "short" length case.
+ offset = kDaikinStateLength - kDaikinStateLengthShort;
+ this->stateReset();
+ }
+ for (uint8_t i = 0; i < length && i < kDaikinStateLength; i++)
+ remote[i + offset] = new_code[i];
+}
+
+void IRDaikinESP::on(void) { remote[kDaikinBytePower] |= kDaikinBitPower; }
+
+void IRDaikinESP::off(void) { remote[kDaikinBytePower] &= ~kDaikinBitPower; }
+
+void IRDaikinESP::setPower(const bool on) {
+ if (on)
+ this->on();
+ else
+ this->off();
+}
+
+bool IRDaikinESP::getPower(void) {
+ return remote[kDaikinBytePower] & kDaikinBitPower;
+}
+
+// Set the temp in deg C
+void IRDaikinESP::setTemp(const uint8_t temp) {
+ uint8_t degrees = std::max(temp, kDaikinMinTemp);
+ degrees = std::min(degrees, kDaikinMaxTemp);
+ remote[kDaikinByteTemp] = degrees << 1;
+}
+
+uint8_t IRDaikinESP::getTemp(void) { return remote[kDaikinByteTemp] >> 1; }
+
+// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet
+void IRDaikinESP::setFan(const uint8_t fan) {
+ // Set the fan speed bits, leave low 4 bits alone
+ uint8_t fanset;
+ if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto)
+ fanset = fan;
+ else if (fan < kDaikinFanMin || fan > kDaikinFanMax)
+ fanset = kDaikinFanAuto;
+ else
+ fanset = 2 + fan;
+ remote[kDaikinByteFan] &= 0x0F;
+ remote[kDaikinByteFan] |= (fanset << 4);
+}
+
+uint8_t IRDaikinESP::getFan(void) {
+ uint8_t fan = remote[kDaikinByteFan] >> 4;
+ if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2;
+ return fan;
+}
+
+uint8_t IRDaikinESP::getMode(void) { return remote[kDaikinBytePower] >> 4; }
+
+void IRDaikinESP::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kDaikinAuto:
+ case kDaikinCool:
+ case kDaikinHeat:
+ case kDaikinFan:
+ case kDaikinDry:
+ remote[kDaikinBytePower] &= 0b10001111;
+ remote[kDaikinBytePower] |= (mode << 4);
+ break;
+ default:
+ this->setMode(kDaikinAuto);
+ }
+}
+
+void IRDaikinESP::setSwingVertical(const bool on) {
+ if (on)
+ remote[kDaikinByteFan] |= 0x0F;
+ else
+ remote[kDaikinByteFan] &= 0xF0;
+}
+
+bool IRDaikinESP::getSwingVertical(void) {
+ return remote[kDaikinByteFan] & 0x0F;
+}
+
+void IRDaikinESP::setSwingHorizontal(const bool on) {
+ if (on)
+ remote[kDaikinByteSwingH] |= 0x0F;
+ else
+ remote[kDaikinByteSwingH] &= 0xF0;
+}
+
+bool IRDaikinESP::getSwingHorizontal(void) {
+ return remote[kDaikinByteSwingH] & 0x0F;
+}
+
+void IRDaikinESP::setQuiet(const bool on) {
+ if (on) {
+ remote[kDaikinByteSilent] |= kDaikinBitSilent;
+ // Powerful & Quiet mode being on are mutually exclusive.
+ this->setPowerful(false);
+ } else {
+ remote[kDaikinByteSilent] &= ~kDaikinBitSilent;
+ }
+}
+
+bool IRDaikinESP::getQuiet(void) {
+ return remote[kDaikinByteSilent] & kDaikinBitSilent;
+}
+
+void IRDaikinESP::setPowerful(const bool on) {
+ if (on) {
+ remote[kDaikinBytePowerful] |= kDaikinBitPowerful;
+ // Powerful, Quiet, & Econo mode being on are mutually exclusive.
+ this->setQuiet(false);
+ this->setEcono(false);
+ } else {
+ remote[kDaikinBytePowerful] &= ~kDaikinBitPowerful;
+ }
+}
+
+bool IRDaikinESP::getPowerful(void) {
+ return remote[kDaikinBytePowerful] & kDaikinBitPowerful;
+}
+
+void IRDaikinESP::setSensor(const bool on) {
+ if (on)
+ remote[kDaikinByteSensor] |= kDaikinBitSensor;
+ else
+ remote[kDaikinByteSensor] &= ~kDaikinBitSensor;
+}
+
+bool IRDaikinESP::getSensor(void) {
+ return remote[kDaikinByteSensor] & kDaikinBitSensor;
+}
+
+void IRDaikinESP::setEcono(const bool on) {
+ if (on) {
+ remote[kDaikinByteEcono] |= kDaikinBitEcono;
+ // Powerful & Econo mode being on are mutually exclusive.
+ this->setPowerful(false);
+ } else {
+ remote[kDaikinByteEcono] &= ~kDaikinBitEcono;
+ }
+}
+
+bool IRDaikinESP::getEcono(void) {
+ return remote[kDaikinByteEcono] & kDaikinBitEcono;
+}
+
+void IRDaikinESP::setMold(const bool on) {
+ if (on)
+ remote[kDaikinByteMold] |= kDaikinBitMold;
+ else
+ remote[kDaikinByteMold] &= ~kDaikinBitMold;
+}
+
+bool IRDaikinESP::getMold(void) {
+ return remote[kDaikinByteMold] & kDaikinBitMold;
+}
+
+void IRDaikinESP::setComfort(const bool on) {
+ if (on)
+ remote[kDaikinByteComfort] |= kDaikinBitComfort;
+ else
+ remote[kDaikinByteComfort] &= ~kDaikinBitComfort;
+}
+
+bool IRDaikinESP::getComfort(void) {
+ return remote[kDaikinByteComfort] & kDaikinBitComfort;
+}
+
+// starttime: Number of minutes after midnight.
+void IRDaikinESP::enableOnTimer(const uint16_t starttime) {
+ remote[kDaikinByteOnTimer] |= kDaikinBitOnTimer;
+ remote[kDaikinByteOnTimerMinsLow] = starttime;
+ // only keep 4 bits
+ remote[kDaikinByteOnTimerMinsHigh] &= 0xF0;
+ remote[kDaikinByteOnTimerMinsHigh] |= ((starttime >> 8) & 0x0F);
+}
+
+void IRDaikinESP::disableOnTimer(void) {
+ this->enableOnTimer(kDaikinUnusedTime);
+ remote[kDaikinByteOnTimer] &= ~kDaikinBitOnTimer;
+}
+
+uint16_t IRDaikinESP::getOnTime(void) {
+ return ((remote[kDaikinByteOnTimerMinsHigh] & 0x0F) << 8) +
+ remote[kDaikinByteOnTimerMinsLow];
+}
+
+bool IRDaikinESP::getOnTimerEnabled(void) {
+ return remote[kDaikinByteOnTimer] & kDaikinBitOnTimer;
+}
+
+// endtime: Number of minutes after midnight.
+void IRDaikinESP::enableOffTimer(const uint16_t endtime) {
+ remote[kDaikinByteOffTimer] |= kDaikinBitOffTimer;
+ remote[kDaikinByteOffTimerMinsHigh] = endtime >> 4;
+ remote[kDaikinByteOffTimerMinsLow] &= 0x0F;
+ remote[kDaikinByteOffTimerMinsLow] |= ((endtime & 0x0F) << 4);
+}
+
+void IRDaikinESP::disableOffTimer(void) {
+ this->enableOffTimer(kDaikinUnusedTime);
+ remote[kDaikinByteOffTimer] &= ~kDaikinBitOffTimer;
+}
+
+uint16_t IRDaikinESP::getOffTime(void) {
+ return (remote[kDaikinByteOffTimerMinsHigh] << 4) +
+ ((remote[kDaikinByteOffTimerMinsLow] & 0xF0) >> 4);
+}
+
+bool IRDaikinESP::getOffTimerEnabled(void) {
+ return remote[kDaikinByteOffTimer] & kDaikinBitOffTimer;
+}
+
+void IRDaikinESP::setCurrentTime(const uint16_t mins_since_midnight) {
+ uint16_t mins = mins_since_midnight;
+ if (mins > 24 * 60) mins = 0; // If > 23:59, set to 00:00
+ remote[kDaikinByteClockMinsLow] = mins;
+ // only keep 3 bits
+ remote[kDaikinByteClockMinsHigh] &= 0xF8;
+ remote[kDaikinByteClockMinsHigh] |= ((mins >> 8) & 0x07);
+}
+
+uint16_t IRDaikinESP::getCurrentTime(void) {
+ return ((remote[kDaikinByteClockMinsHigh] & 0x07) << 8) +
+ remote[kDaikinByteClockMinsLow];
+}
+
+void IRDaikinESP::setCurrentDay(const uint8_t day_of_week) {
+ // 1 is SUN, 2 is MON, ..., 7 is SAT
+ uint8_t days = day_of_week;
+ if (days > 7) days = 0; // Enforce the limit
+ // Update bits 5-3
+ remote[kDaikinByteClockMinsHigh] &= 0xc7;
+ remote[kDaikinByteClockMinsHigh] |= days << 3;
+}
+
+uint8_t IRDaikinESP::getCurrentDay(void) {
+ return ((remote[kDaikinByteClockMinsHigh] & 0x38) >> 3);
+}
+
+void IRDaikinESP::setWeeklyTimerEnable(const bool on) {
+ if (on)
+ remote[kDaikinByteWeeklyTimer] &= ~kDaikinBitWeeklyTimer; // Clear the bit.
+ else
+ remote[kDaikinByteWeeklyTimer] |= kDaikinBitWeeklyTimer; // Set the bit.
+}
+
+bool IRDaikinESP::getWeeklyTimerEnable(void) {
+ return !(remote[kDaikinByteWeeklyTimer] & kDaikinBitWeeklyTimer);
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRDaikinESP::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kDaikinCool;
+ case stdAc::opmode_t::kHeat:
+ return kDaikinHeat;
+ case stdAc::opmode_t::kDry:
+ return kDaikinDry;
+ case stdAc::opmode_t::kFan:
+ return kDaikinFan;
+ default:
+ return kDaikinAuto;
+ }
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRDaikinESP::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ return kDaikinFanQuiet;
+ case stdAc::fanspeed_t::kLow:
+ return kDaikinFanMin;
+ case stdAc::fanspeed_t::kMedium:
+ return kDaikinFanMin + 1;
+ case stdAc::fanspeed_t::kHigh:
+ return kDaikinFanMax - 1;
+ case stdAc::fanspeed_t::kMax:
+ return kDaikinFanMax;
+ default:
+ return kDaikinFanAuto;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRDaikinESP::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kDaikinCool: return stdAc::opmode_t::kCool;
+ case kDaikinHeat: return stdAc::opmode_t::kHeat;
+ case kDaikinDry: return stdAc::opmode_t::kDry;
+ case kDaikinFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRDaikinESP::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kDaikinFanMax: return stdAc::fanspeed_t::kMax;
+ case kDaikinFanMax - 1: return stdAc::fanspeed_t::kHigh;
+ case kDaikinFanMin + 1: return stdAc::fanspeed_t::kMedium;
+ case kDaikinFanMin: return stdAc::fanspeed_t::kLow;
+ case kDaikinFanQuiet: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRDaikinESP::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::DAIKIN;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwingVertical() ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.swingh = this->getSwingHorizontal() ? stdAc::swingh_t::kAuto :
+ stdAc::swingh_t::kOff;
+ result.quiet = this->getQuiet();
+ result.turbo = this->getPowerful();
+ result.clean = this->getMold();
+ result.econo = this->getEcono();
+ // Not supported.
+ result.filter = false;
+ result.light = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRDaikinESP::toString(void) {
+ String result = "";
+ result.reserve(230); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kDaikinAuto, kDaikinCool, kDaikinHeat,
+ kDaikinDry, kDaikinFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kDaikinFanMax, kDaikinFanMin,
+ kDaikinFanAuto, kDaikinFanQuiet, kDaikinFanMed);
+ result += addBoolToString(getPowerful(), F("Powerful"));
+ result += addBoolToString(getQuiet(), F("Quiet"));
+ result += addBoolToString(getSensor(), F("Sensor"));
+ result += addBoolToString(getMold(), F("Mold"));
+ result += addBoolToString(getComfort(), F("Comfort"));
+ result += addBoolToString(getSwingHorizontal(), F("Swing (Horizontal)"));
+ result += addBoolToString(getSwingVertical(), F("Swing (Vertical)"));
+ result += addLabeledString(minsToString(this->getCurrentTime()),
+ F("Current Time"));
+ result += F(", Current Day: ");
+ switch (this->getCurrentDay()) {
+ case 1:
+ result +=F("SUN"); break;
+ case 2:
+ result +=F("MON"); break;
+ case 3:
+ result +=F("TUE"); break;
+ case 4:
+ result +=F("WED"); break;
+ case 5:
+ result +=F("THU"); break;
+ case 6:
+ result +=F("FRI"); break;
+ case 7:
+ result +=F("SAT"); break;
+ default:
+ result +=F("(UNKNOWN)"); break;
+ }
+ result += addLabeledString(getOnTimerEnabled()
+ ? minsToString(this->getOnTime()) : F("Off"),
+ F("On Time"));
+ result += addLabeledString(getOffTimerEnabled()
+ ? minsToString(this->getOffTime()) : F("Off"),
+ F("Off Time"));
+ result += addBoolToString(getWeeklyTimerEnable(), F("Weekly Timer"));
+ return result;
+}
+
+#if DECODE_DAIKIN
+// Decode the supplied Daikin A/C message.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion. (kDaikinBits)
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: BETA / Should be working.
+//
+// Ref:
+// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
+bool IRrecv::decodeDaikin(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ // Is there enough data to match successfully?
+ if (results->rawlen < (2 * (nbits + kDaikinHeaderLength) +
+ kDaikinSections * (kHeader + kFooter) + kFooter - 1))
+ return false;
+
+ // Compliance
+ if (strict && nbits != kDaikinBits) return false;
+
+ uint16_t offset = kStartOffset;
+ match_result_t data_result;
+
+ // Header #1 - Doesn't count as data.
+ data_result = matchData(&(results->rawbuf[offset]), kDaikinHeaderLength,
+ kDaikinBitMark, kDaikinOneSpace,
+ kDaikinBitMark, kDaikinZeroSpace,
+ kDaikinTolerance, kDaikinMarkExcess, false);
+ offset += data_result.used;
+ if (data_result.success == false) return false; // Fail
+ if (data_result.data) return false; // The header bits should be zero.
+ // Footer
+ if (!matchMark(results->rawbuf[offset++], kDaikinBitMark,
+ kDaikinTolerance, kDaikinMarkExcess)) return false;
+ if (!matchSpace(results->rawbuf[offset++], kDaikinZeroSpace + kDaikinGap,
+ kDaikinTolerance, kDaikinMarkExcess)) return false;
+ // Sections
+ const uint8_t ksectionSize[kDaikinSections] = {
+ kDaikinSection1Length, kDaikinSection2Length, kDaikinSection3Length};
+ uint16_t pos = 0;
+ for (uint8_t section = 0; section < kDaikinSections; section++) {
+ uint16_t used;
+ // Section Header + Section Data (7 bytes) + Section Footer
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, ksectionSize[section] * 8,
+ kDaikinHdrMark, kDaikinHdrSpace,
+ kDaikinBitMark, kDaikinOneSpace,
+ kDaikinBitMark, kDaikinZeroSpace,
+ kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
+ section >= kDaikinSections - 1,
+ kDaikinTolerance, kDaikinMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
+ pos += ksectionSize[section];
+ }
+ // Compliance
+ if (strict) {
+ // Re-check we got the correct size/length due to the way we read the data.
+ if (pos * 8 != kDaikinBits) return false;
+ // Validate the checksum.
+ if (!IRDaikinESP::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->decode_type = DAIKIN;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_DAIKIN
+
+#if SEND_DAIKIN2
+// Send a Daikin2 A/C message.
+//
+// Args:
+// data: An array of kDaikin2StateLength bytes containing the IR command.
+//
+// Status: BETA/Appears to work.
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/582
+void IRsend::sendDaikin2(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ if (nbytes < kDaikin2Section1Length)
+ return; // Not enough bytes to send a partial message.
+
+ for (uint16_t r = 0; r <= repeat; r++) {
+ // Leader
+ sendGeneric(kDaikin2LeaderMark, kDaikin2LeaderSpace,
+ 0, 0, 0, 0, 0, 0, (uint64_t) 0, // No data payload.
+ 0, kDaikin2Freq, false, 0, 50);
+ // Section #1
+ sendGeneric(kDaikin2HdrMark, kDaikin2HdrSpace, kDaikin2BitMark,
+ kDaikin2OneSpace, kDaikin2BitMark, kDaikin2ZeroSpace,
+ kDaikin2BitMark, kDaikin2Gap, data, kDaikin2Section1Length,
+ kDaikin2Freq, false, 0, 50);
+ // Section #2
+ sendGeneric(kDaikin2HdrMark, kDaikin2HdrSpace, kDaikin2BitMark,
+ kDaikin2OneSpace, kDaikin2BitMark, kDaikin2ZeroSpace,
+ kDaikin2BitMark, kDaikin2Gap, data + kDaikin2Section1Length,
+ nbytes - kDaikin2Section1Length,
+ kDaikin2Freq, false, 0, 50);
+ }
+}
+#endif // SEND_DAIKIN2
+
+// Class for handling Daikin2 A/C messages.
+//
+// Code by crankyoldgit, Reverse engineering analysis by sheppy99
+//
+// Supported Remotes: Daikin ARC477A1 remote
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/582
+// https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit?usp=sharing
+// https://www.daikin.co.nz/sites/default/files/daikin-split-system-US7-FTXZ25-50NV1B.pdf
+IRDaikin2::IRDaikin2(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
+
+void IRDaikin2::begin() { _irsend.begin(); }
+
+#if SEND_DAIKIN2
+void IRDaikin2::send(const uint16_t repeat) {
+ checksum();
+ _irsend.sendDaikin2(remote_state, kDaikin2StateLength, repeat);
+}
+#endif // SEND_DAIKIN2
+
+// Verify the checksum is valid for a given state.
+// Args:
+// state: The array to verify the checksum of.
+// length: The size of the state.
+// Returns:
+// A boolean.
+bool IRDaikin2::validChecksum(uint8_t state[], const uint16_t length) {
+ // Validate the checksum of section #1.
+ if (length <= kDaikin2Section1Length - 1 ||
+ state[kDaikin2Section1Length - 1] != sumBytes(state,
+ kDaikin2Section1Length - 1))
+ return false;
+ // Validate the checksum of section #2 (a.k.a. the rest)
+ if (length <= kDaikin2Section1Length + 1 ||
+ state[length - 1] != sumBytes(state + kDaikin2Section1Length,
+ length - kDaikin2Section1Length - 1))
+ return false;
+ return true;
+}
+
+// Calculate and set the checksum values for the internal state.
+void IRDaikin2::checksum() {
+ remote_state[kDaikin2Section1Length - 1] = sumBytes(
+ remote_state, kDaikin2Section1Length - 1);
+ remote_state[kDaikin2StateLength -1 ] = sumBytes(
+ remote_state + kDaikin2Section1Length, kDaikin2Section2Length - 1);
+}
+
+void IRDaikin2::stateReset() {
+ for (uint8_t i = 0; i < kDaikin2StateLength; i++) remote_state[i] = 0x0;
+
+ remote_state[0] = 0x11;
+ remote_state[1] = 0xDA;
+ remote_state[2] = 0x27;
+ remote_state[4] = 0x01;
+ remote_state[6] = 0xC0;
+ remote_state[7] = 0x70;
+ remote_state[8] = 0x08;
+ remote_state[9] = 0x0C;
+ remote_state[10] = 0x80;
+ remote_state[11] = 0x04;
+ remote_state[12] = 0xB0;
+ remote_state[13] = 0x16;
+ remote_state[14] = 0x24;
+ remote_state[17] = 0xBE;
+ remote_state[18] = 0xD0;
+ // remote_state[19] is a checksum byte, it will be set by checksum().
+ remote_state[20] = 0x11;
+ remote_state[21] = 0xDA;
+ remote_state[22] = 0x27;
+ remote_state[25] = 0x08;
+ remote_state[28] = 0xA0;
+ remote_state[35] = 0xC1;
+ remote_state[36] = 0x80;
+ remote_state[37] = 0x60;
+ // remote_state[38] is a checksum byte, it will be set by checksum().
+ disableOnTimer();
+ disableOffTimer();
+ disableSleepTimer();
+ checksum();
+}
+
+uint8_t *IRDaikin2::getRaw() {
+ checksum(); // Ensure correct settings before sending.
+ return remote_state;
+}
+
+void IRDaikin2::setRaw(const uint8_t new_code[]) {
+ for (uint8_t i = 0; i < kDaikin2StateLength; i++)
+ remote_state[i] = new_code[i];
+}
+
+void IRDaikin2::on() {
+ remote_state[25] |= kDaikinBitPower;
+ remote_state[6] &= ~kDaikin2BitPower;
+}
+
+void IRDaikin2::off() {
+ remote_state[25] &= ~kDaikinBitPower;
+ remote_state[6] |= kDaikin2BitPower;
+}
+
+void IRDaikin2::setPower(const bool state) {
+ if (state)
+ on();
+ else
+ off();
+}
+
+bool IRDaikin2::getPower() {
+ return (remote_state[25] & kDaikinBitPower) &&
+ !(remote_state[6] & kDaikin2BitPower);
+}
+
+uint8_t IRDaikin2::getMode() { return remote_state[25] >> 4; }
+
+void IRDaikin2::setMode(const uint8_t desired_mode) {
+ uint8_t mode = desired_mode;
+ switch (mode) {
+ case kDaikinCool:
+ case kDaikinHeat:
+ case kDaikinFan:
+ case kDaikinDry:
+ break;
+ default:
+ mode = kDaikinAuto;
+ }
+ remote_state[25] &= 0b10001111;
+ remote_state[25] |= (mode << 4);
+ // Redo the temp setting as Cool mode has a different min temp.
+ if (mode == kDaikinCool) this->setTemp(this->getTemp());
+}
+
+// Set the temp in deg C
+void IRDaikin2::setTemp(const uint8_t desired) {
+ // The A/C has a different min temp if in cool mode.
+ uint8_t temp = std::max(
+ (this->getMode() == kDaikinCool) ? kDaikin2MinCoolTemp : kDaikinMinTemp,
+ desired);
+ temp = std::min(kDaikinMaxTemp, temp);
+ remote_state[26] = temp * 2;
+}
+
+// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet
+void IRDaikin2::setFan(const uint8_t fan) {
+ // Set the fan speed bits, leave low 4 bits alone
+ uint8_t fanset;
+ if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto)
+ fanset = fan;
+ else if (fan < kDaikinFanMin || fan > kDaikinFanMax)
+ fanset = kDaikinFanAuto;
+ else
+ fanset = 2 + fan;
+ remote_state[28] &= 0x0F;
+ remote_state[28] |= (fanset << 4);
+}
+
+uint8_t IRDaikin2::getFan() {
+ uint8_t fan = remote_state[28] >> 4;
+ if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2;
+ return fan;
+}
+
+uint8_t IRDaikin2::getTemp() { return remote_state[26] / 2; }
+
+void IRDaikin2::setSwingVertical(const uint8_t position) {
+ switch (position) {
+ case kDaikin2SwingVHigh:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case kDaikin2SwingVLow:
+ case kDaikin2SwingVBreeze:
+ case kDaikin2SwingVCirculate:
+ case kDaikin2SwingVAuto:
+ remote_state[18] &= 0xF0;
+ remote_state[18] |= (position & 0x0F);
+ }
+}
+
+uint8_t IRDaikin2::getSwingVertical() { return remote_state[18] & 0x0F; }
+
+void IRDaikin2::setSwingHorizontal(const uint8_t position) {
+ remote_state[17] = position;
+}
+
+uint8_t IRDaikin2::getSwingHorizontal() { return remote_state[17]; }
+
+void IRDaikin2::setCurrentTime(const uint16_t numMins) {
+ uint16_t mins = numMins;
+ if (numMins > 24 * 60) mins = 0; // If > 23:59, set to 00:00
+ remote_state[5] = (uint8_t)(mins & 0xFF);
+ // only keep 4 bits
+ remote_state[6] &= 0xF0;
+ remote_state[6] |= (uint8_t)((mins >> 8) & 0x0F);
+}
+
+uint16_t IRDaikin2::getCurrentTime() {
+ return ((remote_state[6] & 0x0F) << 8) + remote_state[5];
+}
+
+// starttime: Number of minutes after midnight.
+// Note: Timer location is shared with sleep timer.
+void IRDaikin2::enableOnTimer(const uint16_t starttime) {
+ clearSleepTimerFlag();
+ remote_state[25] |= kDaikinBitOnTimer; // Set the On Timer flag.
+ remote_state[30] = (uint8_t)(starttime & 0xFF);
+ // only keep 4 bits
+ remote_state[31] &= 0xF0;
+ remote_state[31] |= (uint8_t)((starttime >> 8) & 0x0F);
+}
+
+void IRDaikin2::clearOnTimerFlag() {
+ remote_state[25] &= ~kDaikinBitOnTimer;
+}
+
+void IRDaikin2::disableOnTimer() {
+ enableOnTimer(kDaikinUnusedTime);
+ clearOnTimerFlag();
+ clearSleepTimerFlag();
+}
+
+uint16_t IRDaikin2::getOnTime() {
+ return ((remote_state[31] & 0x0F) << 8) + remote_state[30];
+}
+
+bool IRDaikin2::getOnTimerEnabled() {
+ return remote_state[25] & kDaikinBitOnTimer;
+}
+
+// endtime: Number of minutes after midnight.
+void IRDaikin2::enableOffTimer(const uint16_t endtime) {
+ remote_state[25] |= kDaikinBitOffTimer; // Set the Off Timer flag.
+ remote_state[32] = (uint8_t)((endtime >> 4) & 0xFF);
+ remote_state[31] &= 0x0F;
+ remote_state[31] |= (uint8_t)((endtime & 0xF) << 4);
+}
+
+void IRDaikin2::disableOffTimer() {
+ enableOffTimer(kDaikinUnusedTime);
+ remote_state[25] &= ~kDaikinBitOffTimer; // Clear the Off Timer flag.
+}
+
+uint16_t IRDaikin2::getOffTime() {
+ return (remote_state[32] << 4) + (remote_state[31] >> 4);
+}
+
+bool IRDaikin2::getOffTimerEnabled() {
+ return remote_state[25] & kDaikinBitOffTimer;
+}
+
+uint8_t IRDaikin2::getBeep() {
+ return remote_state[7] >> 6;
+}
+
+void IRDaikin2::setBeep(const uint8_t beep) {
+ remote_state[7] &= ~kDaikin2BeepMask;
+ remote_state[7] |= ((beep << 6) & kDaikin2BeepMask);
+}
+
+uint8_t IRDaikin2::getLight() {
+ return (remote_state[7] & kDaikin2LightMask) >> 4;
+}
+
+void IRDaikin2::setLight(const uint8_t light) {
+ remote_state[7] &= ~kDaikin2LightMask;
+ remote_state[7] |= ((light << 4) & kDaikin2LightMask);
+}
+
+void IRDaikin2::setMold(const bool on) {
+ if (on)
+ remote_state[8] |= kDaikin2BitMold;
+ else
+ remote_state[8] &= ~kDaikin2BitMold;
+}
+
+bool IRDaikin2::getMold() {
+ return remote_state[8] & kDaikin2BitMold;
+}
+
+// Auto clean setting.
+void IRDaikin2::setClean(const bool on) {
+ if (on)
+ remote_state[8] |= kDaikin2BitClean;
+ else
+ remote_state[8] &= ~kDaikin2BitClean;
+}
+
+bool IRDaikin2::getClean() {
+ return remote_state[8] & kDaikin2BitClean;
+}
+
+// Fresh Air settings.
+void IRDaikin2::setFreshAir(const bool on) {
+ if (on)
+ remote_state[8] |= kDaikin2BitFreshAir;
+ else
+ remote_state[8] &= ~kDaikin2BitFreshAir;
+}
+
+bool IRDaikin2::getFreshAir() {
+ return remote_state[8] & kDaikin2BitFreshAir;
+}
+
+void IRDaikin2::setFreshAirHigh(const bool on) {
+ if (on)
+ remote_state[8] |= kDaikin2BitFreshAirHigh;
+ else
+ remote_state[8] &= ~kDaikin2BitFreshAirHigh;
+}
+
+bool IRDaikin2::getFreshAirHigh() {
+ return remote_state[8] & kDaikin2BitFreshAirHigh;
+}
+
+void IRDaikin2::setEyeAuto(bool on) {
+ if (on)
+ remote_state[13] |= kDaikin2BitEyeAuto;
+ else
+ remote_state[13] &= ~kDaikin2BitEyeAuto;
+}
+
+bool IRDaikin2::getEyeAuto() {
+ return remote_state[13] & kDaikin2BitEyeAuto;
+}
+
+void IRDaikin2::setEye(bool on) {
+ if (on)
+ remote_state[36] |= kDaikin2BitEye;
+ else
+ remote_state[36] &= ~kDaikin2BitEye;
+}
+
+bool IRDaikin2::getEye() {
+ return remote_state[36] & kDaikin2BitEye;
+}
+
+void IRDaikin2::setEcono(bool on) {
+ if (on)
+ remote_state[36] |= kDaikinBitEcono;
+ else
+ remote_state[36] &= ~kDaikinBitEcono;
+}
+
+bool IRDaikin2::getEcono() {
+ return remote_state[36] & kDaikinBitEcono;
+}
+
+// sleeptime: Number of minutes.
+// Note: Timer location is shared with On Timer.
+void IRDaikin2::enableSleepTimer(const uint16_t sleeptime) {
+ enableOnTimer(sleeptime);
+ clearOnTimerFlag();
+ remote_state[36] |= kDaikin2BitSleepTimer; // Set the Sleep Timer flag.
+}
+
+void IRDaikin2::clearSleepTimerFlag() {
+ remote_state[36] &= ~kDaikin2BitSleepTimer;
+}
+
+void IRDaikin2::disableSleepTimer() {
+ disableOnTimer();
+}
+
+uint16_t IRDaikin2::getSleepTime() {
+ return getOnTime();
+}
+
+bool IRDaikin2::getSleepTimerEnabled() {
+ return remote_state[36] & kDaikin2BitSleepTimer;
+}
+
+void IRDaikin2::setQuiet(const bool on) {
+ if (on) {
+ remote_state[33] |= kDaikinBitSilent;
+ // Powerful & Quiet mode being on are mutually exclusive.
+ setPowerful(false);
+ } else {
+ remote_state[33] &= ~kDaikinBitSilent;
+ }
+}
+
+bool IRDaikin2::getQuiet() { return remote_state[33] & kDaikinBitSilent; }
+
+void IRDaikin2::setPowerful(const bool on) {
+ if (on) {
+ remote_state[33] |= kDaikinBitPowerful;
+ // Powerful & Quiet mode being on are mutually exclusive.
+ setQuiet(false);
+ } else {
+ remote_state[33] &= ~kDaikinBitPowerful;
+ }
+}
+
+bool IRDaikin2::getPowerful() { return remote_state[33] & kDaikinBitPowerful; }
+
+void IRDaikin2::setPurify(const bool on) {
+ if (on)
+ remote_state[36] |= kDaikin2BitPurify;
+ else
+ remote_state[36] &= ~kDaikin2BitPurify;
+}
+
+bool IRDaikin2::getPurify() { return remote_state[36] & kDaikin2BitPurify; }
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRDaikin2::convertMode(const stdAc::opmode_t mode) {
+ return IRDaikinESP::convertMode(mode);
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRDaikin2::convertFan(const stdAc::fanspeed_t speed) {
+ return IRDaikinESP::convertFan(speed);
+}
+
+// Convert a standard A/C vertical swing into its native version.
+uint8_t IRDaikin2::convertSwingV(const stdAc::swingv_t position) {
+ switch (position) {
+ case stdAc::swingv_t::kHighest:
+ case stdAc::swingv_t::kHigh:
+ case stdAc::swingv_t::kMiddle:
+ case stdAc::swingv_t::kLow:
+ case stdAc::swingv_t::kLowest:
+ return (uint8_t)position + kDaikin2SwingVHigh;
+ default:
+ return kDaikin2SwingVAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingv_t IRDaikin2::toCommonSwingV(const uint8_t setting) {
+ switch (setting) {
+ case kDaikin2SwingVHigh: return stdAc::swingv_t::kHighest;
+ case kDaikin2SwingVHigh + 1: return stdAc::swingv_t::kHigh;
+ case kDaikin2SwingVHigh + 2:
+ case kDaikin2SwingVHigh + 3: return stdAc::swingv_t::kMiddle;
+ case kDaikin2SwingVLow - 1: return stdAc::swingv_t::kLow;
+ case kDaikin2SwingVLow: return stdAc::swingv_t::kLowest;
+ default: return stdAc::swingv_t::kAuto;
+ }
+}
+
+// Convert a native horizontal swing to it's common equivalent.
+stdAc::swingh_t IRDaikin2::toCommonSwingH(const uint8_t setting) {
+ switch (setting) {
+ case kDaikin2SwingHSwing:
+ case kDaikin2SwingHAuto: return stdAc::swingh_t::kAuto;
+ default: return stdAc::swingh_t::kOff;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRDaikin2::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::DAIKIN2;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = IRDaikinESP::toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = IRDaikinESP::toCommonFanSpeed(this->getFan());
+ result.swingv = this->toCommonSwingV(this->getSwingVertical());
+ result.swingh = this->toCommonSwingH(this->getSwingHorizontal());
+ result.quiet = this->getQuiet();
+ result.light = this->getLight();
+ result.turbo = this->getPowerful();
+ result.clean = this->getMold();
+ result.econo = this->getEcono();
+ result.filter = this->getPurify();
+ result.beep = this->getBeep();
+ result.sleep = this->getSleepTimerEnabled() ? this->getSleepTime() : -1;
+ // Not supported.
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRDaikin2::toString() {
+ String result = "";
+ result.reserve(310); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kDaikinAuto, kDaikinCool, kDaikinHeat,
+ kDaikinDry, kDaikinFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kDaikinFanMax, kDaikinFanMin,
+ kDaikinFanAuto, kDaikinFanQuiet, kDaikinFanMed);
+ result += addIntToString(getSwingVertical(), F("Swing (V)"));
+ switch (getSwingVertical()) {
+ case kDaikin2SwingVHigh:
+ result += F(" (Highest)");
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ break;
+ case kDaikin2SwingVLow:
+ result += F(" (Lowest)");
+ break;
+ case kDaikin2SwingVBreeze:
+ result += F(" (Breeze)");
+ break;
+ case kDaikin2SwingVCirculate:
+ result += F(" (Circulate)");
+ break;
+ case kDaikin2SwingVAuto:
+ result += F(" (Auto)");
+ break;
+ default:
+ result += F(" (Unknown)");
+ }
+ result += addIntToString(getSwingHorizontal(), F("Swing (H)"));
+ switch (getSwingHorizontal()) {
+ case kDaikin2SwingHAuto:
+ result += F(" (Auto)");
+ break;
+ case kDaikin2SwingHSwing:
+ result += F(" (Swing)");
+ break;
+ }
+ result += addLabeledString(minsToString(getCurrentTime()), F("Clock"));
+ result += addLabeledString(
+ getOnTimerEnabled() ? minsToString(getOnTime()) : F("Off"), F("On Time"));
+ result += addLabeledString(
+ getOffTimerEnabled() ? minsToString(getOffTime()) : F("Off"),
+ F("Off Time"));
+ result += addLabeledString(
+ getSleepTimerEnabled() ? minsToString(getSleepTime()) : F("Off"),
+ F("Sleep Time"));
+ result += addIntToString(getBeep(), F("Beep"));
+ switch (getBeep()) {
+ case kDaikinBeepLoud:
+ result += F(" (Loud)");
+ break;
+ case kDaikinBeepQuiet:
+ result += F(" (Quiet)");
+ break;
+ case kDaikinBeepOff:
+ result += F(" (Off)");
+ break;
+ default:
+ result += F(" (UNKNOWN)");
+ }
+ result += addIntToString(getLight(), F("Light"));
+ switch (getLight()) {
+ case kDaikinLightBright:
+ result += F(" (Bright)");
+ break;
+ case kDaikinLightDim:
+ result += F(" (Dim)");
+ break;
+ case kDaikinLightOff:
+ result += F(" (Off)");
+ break;
+ default:
+ result += F(" (UNKNOWN)");
+ }
+ result += addBoolToString(getMold(), F("Mold"));
+ result += addBoolToString(getClean(), F("Clean"));
+ result += addLabeledString(
+ getFreshAir() ? (getFreshAirHigh() ? F("High") : F("On")) : F("Off"),
+ F("Fresh Air"));
+ result += addBoolToString(getEye(), F("Eye"));
+ result += addBoolToString(getEyeAuto(), F("Eye Auto"));
+ result += addBoolToString(getQuiet(), F("Quiet"));
+ result += addBoolToString(getPowerful(), F("Powerful"));
+ result += addBoolToString(getPurify(), F("Purify"));
+ result += addBoolToString(getEcono(), F("Econo"));
+ return result;
+}
+
+#if DECODE_DAIKIN2
+// Decode the supplied Daikin2 A/C message.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion. (kDaikin2Bits)
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Supported devices:
+// - Daikin FTXZ25NV1B, FTXZ35NV1B, FTXZ50NV1B Aircon
+// - Daikin ARC477A1 remote
+//
+// Status: BETA / Work as expected.
+//
+// Ref:
+// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
+bool IRrecv::decodeDaikin2(decode_results *results, uint16_t nbits,
+ bool strict) {
+ if (results->rawlen < 2 * (nbits + kHeader + kFooter) + kHeader - 1)
+ return false;
+
+ // Compliance
+ if (strict && nbits != kDaikin2Bits) return false;
+
+ uint16_t offset = kStartOffset;
+ const uint8_t ksectionSize[kDaikin2Sections] = {kDaikin2Section1Length,
+ kDaikin2Section2Length};
+
+ // Leader
+ if (!matchMark(results->rawbuf[offset++], kDaikin2LeaderMark,
+ _tolerance + kDaikin2Tolerance)) return false;
+ if (!matchSpace(results->rawbuf[offset++], kDaikin2LeaderSpace,
+ _tolerance + kDaikin2Tolerance)) return false;
+
+ // Sections
+ uint16_t pos = 0;
+ for (uint8_t section = 0; section < kDaikin2Sections; section++) {
+ uint16_t used;
+ // Section Header + Section Data + Section Footer
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, ksectionSize[section] * 8,
+ kDaikin2HdrMark, kDaikin2HdrSpace,
+ kDaikin2BitMark, kDaikin2OneSpace,
+ kDaikin2BitMark, kDaikin2ZeroSpace,
+ kDaikin2BitMark, kDaikin2Gap,
+ section >= kDaikin2Sections - 1,
+ _tolerance + kDaikin2Tolerance, kDaikinMarkExcess,
+ false);
+ if (used == 0) return false;
+ offset += used;
+ pos += ksectionSize[section];
+ }
+ // Compliance
+ if (strict) {
+ // Re-check we got the correct size/length due to the way we read the data.
+ if (pos * 8 != kDaikin2Bits) return false;
+ // Validate the checksum.
+ if (!IRDaikin2::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->decode_type = DAIKIN2;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_DAIKIN2
+
+#if SEND_DAIKIN216
+// Send a Daikin 216 bit A/C message.
+//
+// Args:
+// data: An array of kDaikin216StateLength bytes containing the IR command.
+//
+// Status: Alpha/Untested on a real device.
+//
+// Supported devices:
+// - Daikin ARC433B69 remote.
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/689
+// https://github.com/danny-source/Arduino_DY_IRDaikin
+void IRsend::sendDaikin216(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ if (nbytes < kDaikin216Section1Length)
+ return; // Not enough bytes to send a partial message.
+
+ for (uint16_t r = 0; r <= repeat; r++) {
+ // Section #1
+ sendGeneric(kDaikin216HdrMark, kDaikin216HdrSpace, kDaikin216BitMark,
+ kDaikin216OneSpace, kDaikin216BitMark, kDaikin216ZeroSpace,
+ kDaikin216BitMark, kDaikin216Gap, data,
+ kDaikin216Section1Length,
+ kDaikin216Freq, false, 0, kDutyDefault);
+ // Section #2
+ sendGeneric(kDaikin216HdrMark, kDaikin216HdrSpace, kDaikin216BitMark,
+ kDaikin216OneSpace, kDaikin216BitMark, kDaikin216ZeroSpace,
+ kDaikin216BitMark, kDaikin216Gap,
+ data + kDaikin216Section1Length,
+ nbytes - kDaikin216Section1Length,
+ kDaikin216Freq, false, 0, kDutyDefault);
+ }
+}
+#endif // SEND_DAIKIN216
+
+// Class for handling Daikin 216 bit / 27 byte A/C messages.
+//
+// Code by crankyoldgit.
+//
+// Supported Remotes: Daikin ARC433B69 remote
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/689
+// https://github.com/danny-source/Arduino_DY_IRDaikin
+IRDaikin216::IRDaikin216(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
+
+void IRDaikin216::begin() { _irsend.begin(); }
+
+#if SEND_DAIKIN216
+void IRDaikin216::send(const uint16_t repeat) {
+ checksum();
+ _irsend.sendDaikin216(remote_state, kDaikin216StateLength, repeat);
+}
+#endif // SEND_DAIKIN216
+
+// Verify the checksum is valid for a given state.
+// Args:
+// state: The array to verify the checksum of.
+// length: The size of the state.
+// Returns:
+// A boolean.
+bool IRDaikin216::validChecksum(uint8_t state[], const uint16_t length) {
+ // Validate the checksum of section #1.
+ if (length <= kDaikin216Section1Length - 1 ||
+ state[kDaikin216Section1Length - 1] != sumBytes(
+ state, kDaikin216Section1Length - 1))
+ return false;
+ // Validate the checksum of section #2 (a.k.a. the rest)
+ if (length <= kDaikin216Section1Length + 1 ||
+ state[length - 1] != sumBytes(state + kDaikin216Section1Length,
+ length - kDaikin216Section1Length - 1))
+ return false;
+ return true;
+}
+
+// Calculate and set the checksum values for the internal state.
+void IRDaikin216::checksum() {
+ remote_state[kDaikin216Section1Length - 1] = sumBytes(
+ remote_state, kDaikin216Section1Length - 1);
+ remote_state[kDaikin216StateLength - 1] = sumBytes(
+ remote_state + kDaikin216Section1Length, kDaikin216Section2Length - 1);
+}
+
+void IRDaikin216::stateReset() {
+ for (uint8_t i = 0; i < kDaikin216StateLength; i++) remote_state[i] = 0x00;
+ remote_state[0] = 0x11;
+ remote_state[1] = 0xDA;
+ remote_state[2] = 0x27;
+ remote_state[3] = 0xF0;
+ // remote_state[7] is a checksum byte, it will be set by checksum().
+ remote_state[8] = 0x11;
+ remote_state[9] = 0xDA;
+ remote_state[10] = 0x27;
+ remote_state[23] = 0xC0;
+ // remote_state[26] is a checksum byte, it will be set by checksum().
+}
+
+uint8_t *IRDaikin216::getRaw() {
+ checksum(); // Ensure correct settings before sending.
+ return remote_state;
+}
+
+void IRDaikin216::setRaw(const uint8_t new_code[]) {
+ for (uint8_t i = 0; i < kDaikin216StateLength; i++)
+ remote_state[i] = new_code[i];
+}
+
+
+void IRDaikin216::on() {
+ remote_state[kDaikin216BytePower] |= kDaikinBitPower;
+}
+
+void IRDaikin216::off() {
+ remote_state[kDaikin216BytePower] &= ~kDaikinBitPower;
+}
+
+void IRDaikin216::setPower(const bool state) {
+ if (state)
+ on();
+ else
+ off();
+}
+
+bool IRDaikin216::getPower() {
+ return remote_state[kDaikin216BytePower] & kDaikinBitPower;
+}
+
+uint8_t IRDaikin216::getMode() {
+ return (remote_state[kDaikin216ByteMode] & kDaikin216MaskMode) >> 4;
+}
+
+void IRDaikin216::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kDaikinAuto:
+ case kDaikinCool:
+ case kDaikinHeat:
+ case kDaikinFan:
+ case kDaikinDry:
+ remote_state[kDaikin216ByteMode] &= ~kDaikin216MaskMode;
+ remote_state[kDaikin216ByteMode] |= (mode << 4);
+ break;
+ default:
+ this->setMode(kDaikinAuto);
+ }
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRDaikin216::convertMode(const stdAc::opmode_t mode) {
+ return IRDaikinESP::convertMode(mode);
+}
+
+// Set the temp in deg C
+void IRDaikin216::setTemp(const uint8_t temp) {
+ uint8_t degrees = std::max(temp, kDaikinMinTemp);
+ degrees = std::min(degrees, kDaikinMaxTemp);
+ remote_state[kDaikin216ByteTemp] &= ~kDaikin216MaskTemp;
+ remote_state[kDaikin216ByteTemp] |= (degrees << 1);
+}
+
+uint8_t IRDaikin216::getTemp(void) {
+ return (remote_state[kDaikin216ByteTemp] & kDaikin216MaskTemp) >> 1;
+}
+
+// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet
+void IRDaikin216::setFan(const uint8_t fan) {
+ // Set the fan speed bits, leave low 4 bits alone
+ uint8_t fanset;
+ if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto)
+ fanset = fan;
+ else if (fan < kDaikinFanMin || fan > kDaikinFanMax)
+ fanset = kDaikinFanAuto;
+ else
+ fanset = 2 + fan;
+ remote_state[kDaikin216ByteFan] &= ~kDaikin216MaskFan;
+ remote_state[kDaikin216ByteFan] |= (fanset << 4);
+}
+
+uint8_t IRDaikin216::getFan() {
+ uint8_t fan = remote_state[kDaikin216ByteFan] >> 4;
+ if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2;
+ return fan;
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRDaikin216::convertFan(const stdAc::fanspeed_t speed) {
+ return IRDaikinESP::convertFan(speed);
+}
+
+void IRDaikin216::setSwingVertical(const bool on) {
+ if (on)
+ remote_state[kDaikin216ByteSwingV] |= kDaikin216MaskSwingV;
+ else
+ remote_state[kDaikin216ByteSwingV] &= ~kDaikin216MaskSwingV;
+}
+
+bool IRDaikin216::getSwingVertical(void) {
+ return remote_state[kDaikin216ByteSwingV] & kDaikin216MaskSwingV;
+}
+
+void IRDaikin216::setSwingHorizontal(const bool on) {
+ if (on)
+ remote_state[kDaikin216ByteSwingH] |= kDaikin216MaskSwingH;
+ else
+ remote_state[kDaikin216ByteSwingH] &= ~kDaikin216MaskSwingH;
+}
+
+bool IRDaikin216::getSwingHorizontal(void) {
+ return remote_state[kDaikin216ByteSwingH] & kDaikin216MaskSwingH;
+}
+
+// This is a horrible hack till someone works out the quiet mode bit.
+void IRDaikin216::setQuiet(const bool on) {
+ if (on) {
+ this->setFan(kDaikinFanQuiet);
+ // Powerful & Quiet mode being on are mutually exclusive.
+ this->setPowerful(false);
+ } else if (this->getFan() == kDaikinFanQuiet) {
+ this->setFan(kDaikinFanAuto);
+ }
+}
+
+// This is a horrible hack till someone works out the quiet mode bit.
+bool IRDaikin216::getQuiet(void) {
+ return this->getFan() == kDaikinFanQuiet;
+}
+
+void IRDaikin216::setPowerful(const bool on) {
+ if (on) {
+ remote_state[kDaikin216BytePowerful] |= kDaikinBitPowerful;
+ // Powerful & Quiet mode being on are mutually exclusive.
+ this->setQuiet(false);
+ } else {
+ remote_state[kDaikin216BytePowerful] &= ~kDaikinBitPowerful;
+ }
+}
+
+bool IRDaikin216::getPowerful() {
+ return remote_state[kDaikin216BytePowerful] & kDaikinBitPowerful;
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRDaikin216::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::DAIKIN216;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = IRDaikinESP::toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = IRDaikinESP::toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwingVertical() ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.swingh = this->getSwingHorizontal() ? stdAc::swingh_t::kAuto :
+ stdAc::swingh_t::kOff;
+ result.quiet = this->getQuiet();
+ result.turbo = this->getPowerful();
+ // Not supported.
+ result.light = false;
+ result.clean = false;
+ result.econo = false;
+ result.filter = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRDaikin216::toString() {
+ String result = "";
+ result.reserve(120); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kDaikinAuto, kDaikinCool, kDaikinHeat,
+ kDaikinDry, kDaikinFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kDaikinFanMax, kDaikinFanMin,
+ kDaikinFanAuto, kDaikinFanQuiet, kDaikinFanMed);
+ result += addBoolToString(getSwingHorizontal(), F("Swing (Horizontal)"));
+ result += addBoolToString(getSwingVertical(), F("Swing (Vertical)"));
+ result += addBoolToString(getQuiet(), F("Quiet"));
+ result += addBoolToString(getPowerful(), F("Powerful"));
+ return result;
+}
+
+#if DECODE_DAIKIN216
+// Decode the supplied Daikin 216 bit A/C message.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion. (kDaikin216Bits)
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Supported devices:
+// - Daikin ARC433B69 remote.
+//
+// Status: BETA / Should be working.
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/689
+// https://github.com/danny-source/Arduino_DY_IRDaikin
+bool IRrecv::decodeDaikin216(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1)
+ return false;
+
+ // Compliance
+ if (strict && nbits != kDaikin216Bits) return false;
+
+ uint16_t offset = kStartOffset;
+ const uint8_t ksectionSize[kDaikin216Sections] = {kDaikin216Section1Length,
+ kDaikin216Section2Length};
+ // Sections
+ uint16_t pos = 0;
+ for (uint8_t section = 0; section < kDaikin216Sections; section++) {
+ uint16_t used;
+ // Section Header + Section Data + Section Footer
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, ksectionSize[section] * 8,
+ kDaikin216HdrMark, kDaikin216HdrSpace,
+ kDaikin216BitMark, kDaikin216OneSpace,
+ kDaikin216BitMark, kDaikin216ZeroSpace,
+ kDaikin216BitMark, kDaikin216Gap,
+ section >= kDaikin216Sections - 1,
+ kDaikinTolerance, kDaikinMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
+ pos += ksectionSize[section];
+ }
+ // Compliance
+ if (strict) {
+ if (pos * 8 != kDaikin216Bits) return false;
+ // Validate the checksum.
+ if (!IRDaikin216::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->decode_type = decode_type_t::DAIKIN216;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_DAIKIN216
+
+#if SEND_DAIKIN160
+// Send a Daikin 160 bit A/C message.
+//
+// Args:
+// data: An array of kDaikin160StateLength bytes containing the IR command.
+//
+// Status: STABLE / Confirmed working.
+//
+// Supported devices:
+// - Daikin ARC423A5 remote.
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/731
+void IRsend::sendDaikin160(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ if (nbytes < kDaikin160Section1Length)
+ return; // Not enough bytes to send a partial message.
+
+ for (uint16_t r = 0; r <= repeat; r++) {
+ // Section #1
+ sendGeneric(kDaikin160HdrMark, kDaikin160HdrSpace, kDaikin160BitMark,
+ kDaikin160OneSpace, kDaikin160BitMark, kDaikin160ZeroSpace,
+ kDaikin160BitMark, kDaikin160Gap, data,
+ kDaikin160Section1Length,
+ kDaikin160Freq, false, 0, kDutyDefault);
+ // Section #2
+ sendGeneric(kDaikin160HdrMark, kDaikin160HdrSpace, kDaikin160BitMark,
+ kDaikin160OneSpace, kDaikin160BitMark, kDaikin160ZeroSpace,
+ kDaikin160BitMark, kDaikin160Gap,
+ data + kDaikin160Section1Length,
+ nbytes - kDaikin160Section1Length,
+ kDaikin160Freq, false, 0, kDutyDefault);
+ }
+}
+#endif // SEND_DAIKIN160
+
+// Class for handling Daikin 160 bit / 20 byte A/C messages.
+//
+// Code by crankyoldgit.
+//
+// Supported Remotes: Daikin ARC423A5 remote
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/731
+IRDaikin160::IRDaikin160(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
+
+void IRDaikin160::begin() { _irsend.begin(); }
+
+// Verify the checksum is valid for a given state.
+// Args:
+// state: The array to verify the checksum of.
+// length: The size of the state.
+// Returns:
+// A boolean.
+bool IRDaikin160::validChecksum(uint8_t state[], const uint16_t length) {
+ // Validate the checksum of section #1.
+ if (length <= kDaikin160Section1Length - 1 ||
+ state[kDaikin160Section1Length - 1] != sumBytes(
+ state, kDaikin160Section1Length - 1))
+ return false;
+ // Validate the checksum of section #2 (a.k.a. the rest)
+ if (length <= kDaikin160Section1Length + 1 ||
+ state[length - 1] != sumBytes(state + kDaikin160Section1Length,
+ length - kDaikin160Section1Length - 1))
+ return false;
+ return true;
+}
+
+// Calculate and set the checksum values for the internal state.
+void IRDaikin160::checksum() {
+ remote_state[kDaikin160Section1Length - 1] = sumBytes(
+ remote_state, kDaikin160Section1Length - 1);
+ remote_state[kDaikin160StateLength - 1] = sumBytes(
+ remote_state + kDaikin160Section1Length, kDaikin160Section2Length - 1);
+}
+
+void IRDaikin160::stateReset() {
+ for (uint8_t i = 0; i < kDaikin160StateLength; i++) remote_state[i] = 0x00;
+ remote_state[0] = 0x11;
+ remote_state[1] = 0xDA;
+ remote_state[2] = 0x27;
+ remote_state[3] = 0xF0;
+ remote_state[4] = 0x0D;
+ // remote_state[6] is a checksum byte, it will be set by checksum().
+ remote_state[7] = 0x11;
+ remote_state[8] = 0xDA;
+ remote_state[9] = 0x27;
+ remote_state[11] = 0xD3;
+ remote_state[12] = 0x30;
+ remote_state[13] = 0x11;
+ remote_state[16] = 0x1E;
+ remote_state[17] = 0x0A;
+ remote_state[18] = 0x08;
+ // remote_state[19] is a checksum byte, it will be set by checksum().
+}
+
+uint8_t *IRDaikin160::getRaw() {
+ checksum(); // Ensure correct settings before sending.
+ return remote_state;
+}
+
+void IRDaikin160::setRaw(const uint8_t new_code[]) {
+ for (uint8_t i = 0; i < kDaikin160StateLength; i++)
+ remote_state[i] = new_code[i];
+}
+
+#if SEND_DAIKIN160
+void IRDaikin160::send(const uint16_t repeat) {
+ checksum();
+ _irsend.sendDaikin160(remote_state, kDaikin160StateLength, repeat);
+}
+#endif // SEND_DAIKIN160
+
+void IRDaikin160::on() {
+ remote_state[kDaikin160BytePower] |= kDaikinBitPower;
+}
+
+void IRDaikin160::off() {
+ remote_state[kDaikin160BytePower] &= ~kDaikinBitPower;
+}
+
+void IRDaikin160::setPower(const bool state) {
+ if (state)
+ on();
+ else
+ off();
+}
+
+bool IRDaikin160::getPower() {
+ return remote_state[kDaikin160BytePower] & kDaikinBitPower;
+}
+
+uint8_t IRDaikin160::getMode() {
+ return (remote_state[kDaikin160ByteMode] & kDaikin160MaskMode) >> 4;
+}
+
+void IRDaikin160::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kDaikinAuto:
+ case kDaikinCool:
+ case kDaikinHeat:
+ case kDaikinFan:
+ case kDaikinDry:
+ remote_state[kDaikin160ByteMode] &= ~kDaikin160MaskMode;
+ remote_state[kDaikin160ByteMode] |= (mode << 4);
+ break;
+ default:
+ this->setMode(kDaikinAuto);
+ }
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRDaikin160::convertMode(const stdAc::opmode_t mode) {
+ return IRDaikinESP::convertMode(mode);
+}
+
+// Set the temp in deg C
+void IRDaikin160::setTemp(const uint8_t temp) {
+ uint8_t degrees = std::max(temp, kDaikinMinTemp);
+ degrees = std::min(degrees, kDaikinMaxTemp) * 2 - 20;
+ remote_state[kDaikin160ByteTemp] &= ~kDaikin160MaskTemp;
+ remote_state[kDaikin160ByteTemp] |= degrees;
+}
+
+uint8_t IRDaikin160::getTemp(void) {
+ return (((remote_state[kDaikin160ByteTemp] & kDaikin160MaskTemp) / 2 ) + 10);
+}
+
+// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet
+void IRDaikin160::setFan(const uint8_t fan) {
+ uint8_t fanset;
+ if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto)
+ fanset = fan;
+ else if (fan < kDaikinFanMin || fan > kDaikinFanMax)
+ fanset = kDaikinFanAuto;
+ else
+ fanset = 2 + fan;
+ // Set the fan speed bits, leave *upper* 4 bits alone
+ remote_state[kDaikin160ByteFan] &= ~kDaikin160MaskFan;
+ remote_state[kDaikin160ByteFan] |= fanset;
+}
+
+uint8_t IRDaikin160::getFan() {
+ uint8_t fan = remote_state[kDaikin160ByteFan] & kDaikin160MaskFan;
+ if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2;
+ return fan;
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRDaikin160::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin: return kDaikinFanMin;
+ case stdAc::fanspeed_t::kLow: return kDaikinFanMin + 1;
+ case stdAc::fanspeed_t::kMedium: return kDaikinFanMin + 2;
+ case stdAc::fanspeed_t::kHigh: return kDaikinFanMax - 1;
+ case stdAc::fanspeed_t::kMax: return kDaikinFanMax;
+ default:
+ return kDaikinFanAuto;
+ }
+}
+
+void IRDaikin160::setSwingVertical(const uint8_t position) {
+ switch (position) {
+ case kDaikin160SwingVLowest:
+ case kDaikin160SwingVLow:
+ case kDaikin160SwingVMiddle:
+ case kDaikin160SwingVHigh:
+ case kDaikin160SwingVHighest:
+ case kDaikin160SwingVAuto:
+ remote_state[kDaikin160ByteSwingV] &= ~kDaikin160MaskSwingV;
+ remote_state[kDaikin160ByteSwingV] |= (position << 4);
+ break;
+ default:
+ setSwingVertical(kDaikin160SwingVAuto);
+ }
+}
+
+uint8_t IRDaikin160::getSwingVertical(void) {
+ return remote_state[kDaikin160ByteSwingV] >> 4;
+}
+
+// Convert a standard A/C vertical swing into its native version.
+uint8_t IRDaikin160::convertSwingV(const stdAc::swingv_t position) {
+ switch (position) {
+ case stdAc::swingv_t::kHighest:
+ case stdAc::swingv_t::kHigh:
+ case stdAc::swingv_t::kMiddle:
+ case stdAc::swingv_t::kLow:
+ case stdAc::swingv_t::kLowest:
+ return kDaikin160SwingVHighest + 1 - (uint8_t)position;
+ default:
+ return kDaikin160SwingVAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingv_t IRDaikin160::toCommonSwingV(const uint8_t setting) {
+ switch (setting) {
+ case kDaikin160SwingVHighest: return stdAc::swingv_t::kHighest;
+ case kDaikin160SwingVHigh: return stdAc::swingv_t::kHigh;
+ case kDaikin160SwingVMiddle: return stdAc::swingv_t::kMiddle;
+ case kDaikin160SwingVLow: return stdAc::swingv_t::kLow;
+ case kDaikin160SwingVLowest: return stdAc::swingv_t::kLowest;
+ default:
+ return stdAc::swingv_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRDaikin160::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::DAIKIN160;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = IRDaikinESP::toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = IRDaikinESP::toCommonFanSpeed(this->getFan());
+ result.swingv = this->toCommonSwingV(this->getSwingVertical());
+ // Not supported.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.quiet = false;
+ result.turbo = false;
+ result.light = false;
+ result.clean = false;
+ result.econo = false;
+ result.filter = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRDaikin160::toString() {
+ String result = "";
+ result.reserve(150); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kDaikinAuto, kDaikinCool, kDaikinHeat,
+ kDaikinDry, kDaikinFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kDaikinFanMax, kDaikinFanMin,
+ kDaikinFanAuto, kDaikinFanQuiet, kDaikinFanMed);
+ result += addIntToString(getSwingVertical(), F("Vent Position (V)"));
+ switch (getSwingVertical()) {
+ case kDaikin160SwingVHighest: result += F(" (Highest)"); break;
+ case kDaikin160SwingVHigh: result += F(" (High)"); break;
+ case kDaikin160SwingVMiddle: result += F(" (Middle)"); break;
+ case kDaikin160SwingVLow: result += F(" (Low)"); break;
+ case kDaikin160SwingVLowest: result += F(" (Lowest)"); break;
+ case kDaikin160SwingVAuto: result += F(" (Auto)"); break;
+ default:
+ result += F(" (Unknown)");
+ }
+ return result;
+}
+
+#if DECODE_DAIKIN160
+// Decode the supplied Daikin 160 bit A/C message.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion. (kDaikin160Bits)
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Supported devices:
+// - Daikin ARC423A5 remote.
+//
+// Status: STABLE / Confirmed working.
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/731
+bool IRrecv::decodeDaikin160(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1)
+ return false;
+
+ // Compliance
+ if (strict && nbits != kDaikin160Bits) return false;
+
+ uint16_t offset = kStartOffset;
+ const uint8_t ksectionSize[kDaikin160Sections] = {kDaikin160Section1Length,
+ kDaikin160Section2Length};
+
+ // Sections
+ uint16_t pos = 0;
+ for (uint8_t section = 0; section < kDaikin160Sections; section++) {
+ uint16_t used;
+ // Section Header + Section Data (7 bytes) + Section Footer
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, ksectionSize[section] * 8,
+ kDaikin160HdrMark, kDaikin160HdrSpace,
+ kDaikin160BitMark, kDaikin160OneSpace,
+ kDaikin160BitMark, kDaikin160ZeroSpace,
+ kDaikin160BitMark, kDaikin160Gap,
+ section >= kDaikin160Sections - 1,
+ kDaikinTolerance, kDaikinMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
+ pos += ksectionSize[section];
+ }
+ // Compliance
+ if (strict) {
+ // Validate the checksum.
+ if (!IRDaikin160::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->decode_type = decode_type_t::DAIKIN160;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_DAIKIN160
+
+#if SEND_DAIKIN176
+// Send a Daikin 176 bit A/C message.
+//
+// Args:
+// data: An array of kDaikin176StateLength bytes containing the IR command.
+//
+// Status: Alpha/Untested on a real device.
+//
+// Supported devices:
+// - Daikin BRC4C153 remote.
+//
+void IRsend::sendDaikin176(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ if (nbytes < kDaikin176Section1Length)
+ return; // Not enough bytes to send a partial message.
+
+ for (uint16_t r = 0; r <= repeat; r++) {
+ // Section #1
+ sendGeneric(kDaikin176HdrMark, kDaikin176HdrSpace, kDaikin176BitMark,
+ kDaikin176OneSpace, kDaikin176BitMark, kDaikin176ZeroSpace,
+ kDaikin176BitMark, kDaikin176Gap, data,
+ kDaikin176Section1Length,
+ kDaikin176Freq, false, 0, kDutyDefault);
+ // Section #2
+ sendGeneric(kDaikin176HdrMark, kDaikin176HdrSpace, kDaikin176BitMark,
+ kDaikin176OneSpace, kDaikin176BitMark, kDaikin176ZeroSpace,
+ kDaikin176BitMark, kDaikin176Gap,
+ data + kDaikin176Section1Length,
+ nbytes - kDaikin176Section1Length,
+ kDaikin176Freq, false, 0, kDutyDefault);
+ }
+}
+#endif // SEND_DAIKIN176
+
+// Class for handling Daikin 176 bit / 22 byte A/C messages.
+//
+// Code by crankyoldgit.
+//
+// Supported Remotes: Daikin BRC4C153 remote
+//
+IRDaikin176::IRDaikin176(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
+
+void IRDaikin176::begin() { _irsend.begin(); }
+
+// Verify the checksum is valid for a given state.
+// Args:
+// state: The array to verify the checksum of.
+// length: The size of the state.
+// Returns:
+// A boolean.
+bool IRDaikin176::validChecksum(uint8_t state[], const uint16_t length) {
+ // Validate the checksum of section #1.
+ if (length <= kDaikin176Section1Length - 1 ||
+ state[kDaikin176Section1Length - 1] != sumBytes(
+ state, kDaikin176Section1Length - 1))
+ return false;
+ // Validate the checksum of section #2 (a.k.a. the rest)
+ if (length <= kDaikin176Section1Length + 1 ||
+ state[length - 1] != sumBytes(state + kDaikin176Section1Length,
+ length - kDaikin176Section1Length - 1))
+ return false;
+ return true;
+}
+
+// Calculate and set the checksum values for the internal state.
+void IRDaikin176::checksum() {
+ remote_state[kDaikin176Section1Length - 1] = sumBytes(
+ remote_state, kDaikin176Section1Length - 1);
+ remote_state[kDaikin176StateLength - 1] = sumBytes(
+ remote_state + kDaikin176Section1Length, kDaikin176Section2Length - 1);
+}
+
+void IRDaikin176::stateReset() {
+ for (uint8_t i = 0; i < kDaikin176StateLength; i++) remote_state[i] = 0x00;
+ remote_state[0] = 0x11;
+ remote_state[1] = 0xDA;
+ remote_state[2] = 0x17;
+ remote_state[3] = 0x18;
+ remote_state[4] = 0x04;
+ // remote_state[6] is a checksum byte, it will be set by checksum().
+ remote_state[7] = 0x11;
+ remote_state[8] = 0xDA;
+ remote_state[9] = 0x17;
+ remote_state[10] = 0x18;
+ remote_state[12] = 0x73;
+ remote_state[14] = 0x20;
+ remote_state[18] = 0x16; // Fan speed and swing
+ remote_state[20] = 0x20;
+ // remote_state[21] is a checksum byte, it will be set by checksum().
+ _saved_temp = getTemp();
+}
+
+uint8_t *IRDaikin176::getRaw() {
+ checksum(); // Ensure correct settings before sending.
+ return remote_state;
+}
+
+void IRDaikin176::setRaw(const uint8_t new_code[]) {
+ for (uint8_t i = 0; i < kDaikin176StateLength; i++)
+ remote_state[i] = new_code[i];
+ _saved_temp = getTemp();
+}
+
+#if SEND_DAIKIN176
+void IRDaikin176::send(const uint16_t repeat) {
+ checksum();
+ _irsend.sendDaikin176(remote_state, kDaikin176StateLength, repeat);
+}
+#endif // SEND_DAIKIN176
+
+void IRDaikin176::on() { setPower(true); }
+
+void IRDaikin176::off() { setPower(false); }
+
+void IRDaikin176::setPower(const bool state) {
+ remote_state[kDaikin176ByteModeButton] = 0;
+ if (state)
+ remote_state[kDaikin176BytePower] |= kDaikinBitPower;
+ else
+ remote_state[kDaikin176BytePower] &= ~kDaikinBitPower;
+}
+
+bool IRDaikin176::getPower() {
+ return remote_state[kDaikin176BytePower] & kDaikinBitPower;
+}
+
+uint8_t IRDaikin176::getMode() {
+ return (remote_state[kDaikin176ByteMode] & kDaikin176MaskMode) >> 4;
+}
+
+void IRDaikin176::setMode(const uint8_t mode) {
+ uint8_t altmode = 0;
+ switch (mode) {
+ case kDaikinFan: altmode = 0; break;
+ case kDaikinDry: altmode = 7; break;
+ case kDaikin176Cool: altmode = 2; break;
+ default: this->setMode(kDaikin176Cool); return;
+ }
+ // Set the mode.
+ remote_state[kDaikin176ByteMode] &= ~kDaikin176MaskMode;
+ remote_state[kDaikin176ByteMode] |= (mode << 4);
+ // Set the altmode
+ remote_state[kDaikin176BytePower] &= ~kDaikin176MaskMode;
+ remote_state[kDaikin176BytePower] |= (altmode << 4);
+ setTemp(_saved_temp);
+ // Needs to happen after setTemp() as it will clear it.
+ remote_state[kDaikin176ByteModeButton] = kDaikin176ModeButton;
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRDaikin176::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kDry:
+ return kDaikinDry;
+ case stdAc::opmode_t::kHeat: // Heat not supported, but fan is the closest.
+ case stdAc::opmode_t::kFan:
+ return kDaikinFan;
+ default:
+ return kDaikin176Cool;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRDaikin176::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kDaikinDry: return stdAc::opmode_t::kDry;
+ case kDaikinHeat: // There is no heat mode, but fan is the closest.
+ case kDaikinFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kCool;
+ }
+}
+
+// Set the temp in deg C
+void IRDaikin176::setTemp(const uint8_t temp) {
+ uint8_t degrees = std::min(kDaikinMaxTemp, std::max(temp, kDaikinMinTemp));
+ _saved_temp = degrees;
+ switch (getMode()) {
+ case kDaikinDry:
+ case kDaikinFan:
+ degrees = kDaikin176DryFanTemp;
+ }
+ degrees = degrees * 2 - 18;
+ remote_state[kDaikin176ByteTemp] &= ~kDaikin176MaskTemp;
+ remote_state[kDaikin176ByteTemp] |= degrees;
+ remote_state[kDaikin176ByteModeButton] = 0;
+}
+
+uint8_t IRDaikin176::getTemp(void) {
+ return (((remote_state[kDaikin176ByteTemp] & kDaikin176MaskTemp) / 2 ) + 9);
+}
+
+// Set the speed of the fan, 1 for Min or 3 for Max
+void IRDaikin176::setFan(const uint8_t fan) {
+ switch (fan) {
+ case kDaikinFanMin:
+ case kDaikin176FanMax:
+ remote_state[kDaikin176ByteFan] &= ~kDaikin176MaskFan;
+ remote_state[kDaikin176ByteFan] |= (fan << 4);
+ remote_state[kDaikin176ByteModeButton] = 0;
+ break;
+ default:
+ setFan(kDaikin176FanMax);
+ }
+}
+
+uint8_t IRDaikin176::getFan() { return remote_state[kDaikin176ByteFan] >> 4; }
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRDaikin176::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ case stdAc::fanspeed_t::kLow:
+ return kDaikinFanMin;
+ default:
+ return kDaikin176FanMax;
+ }
+}
+
+void IRDaikin176::setSwingHorizontal(const uint8_t position) {
+ switch (position) {
+ case kDaikin176SwingHOff:
+ case kDaikin176SwingHAuto:
+ remote_state[kDaikin176ByteSwingH] &= ~kDaikin176MaskSwingH;
+ remote_state[kDaikin176ByteSwingH] |= position;
+ break;
+ default:
+ setSwingHorizontal(kDaikin176SwingHAuto);
+ }
+}
+
+uint8_t IRDaikin176::getSwingHorizontal() {
+ return remote_state[kDaikin176ByteSwingH] & kDaikin176MaskSwingH;
+}
+
+// Convert a standard A/C horizontal swing into its native version.
+uint8_t IRDaikin176::convertSwingH(const stdAc::swingh_t position) {
+ switch (position) {
+ case stdAc::swingh_t::kOff:
+ return kDaikin176SwingHOff;
+ case stdAc::swingh_t::kAuto:
+ return kDaikin176SwingHAuto;
+ default:
+ return kDaikin176SwingHAuto;
+ }
+}
+// Convert a native horizontal swing to it's common equivalent.
+stdAc::swingh_t IRDaikin176::toCommonSwingH(const uint8_t setting) {
+ switch (setting) {
+ case kDaikin176SwingHOff: return stdAc::swingh_t::kOff;
+ case kDaikin176SwingHAuto: return stdAc::swingh_t::kAuto;
+ default:
+ return stdAc::swingh_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRDaikin176::toCommonFanSpeed(const uint8_t speed) {
+ return (speed == kDaikinFanMin) ? stdAc::fanspeed_t::kMin
+ : stdAc::fanspeed_t::kMax;
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRDaikin176::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::DAIKIN176;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = IRDaikin176::toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingh = this->toCommonSwingH(this->getSwingHorizontal());
+
+ // Not supported.
+ result.swingv = stdAc::swingv_t::kOff;
+ result.quiet = false;
+ result.turbo = false;
+ result.light = false;
+ result.clean = false;
+ result.econo = false;
+ result.filter = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRDaikin176::toString() {
+ String result = "";
+ result.reserve(80); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kDaikinAuto, kDaikin176Cool, kDaikinHeat,
+ kDaikinDry, kDaikinFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kDaikin176FanMax, kDaikinFanMin,
+ kDaikinFanMin, kDaikinFanMin, kDaikinFanMin);
+ result += F(", Swing (H): ");
+ result += uint64ToString(getSwingHorizontal());
+ switch (getSwingHorizontal()) {
+ case kDaikin176SwingHAuto:
+ result += F(" (Auto)");
+ break;
+ case kDaikin176SwingHOff:
+ result += F(" (Off)");
+ break;
+ default:
+ result += F(" (UNKNOWN)");
+ }
+ return result;
+}
+
+#if DECODE_DAIKIN176
+// Decode the supplied Daikin 176 bit A/C message.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion. (kDaikin176Bits)
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Supported devices:
+// - Daikin BRC4C153 remote.
+//
+// Status: BETA / Probably works.
+//
+
+bool IRrecv::decodeDaikin176(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1)
+ return false;
+
+ // Compliance
+ if (strict && nbits != kDaikin176Bits) return false;
+
+ uint16_t offset = kStartOffset;
+ const uint8_t ksectionSize[kDaikin176Sections] = {kDaikin176Section1Length,
+ kDaikin176Section2Length};
+
+ // Sections
+ uint16_t pos = 0;
+ for (uint8_t section = 0; section < kDaikin176Sections; section++) {
+ uint16_t used;
+ // Section Header + Section Data (7 bytes) + Section Footer
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, ksectionSize[section] * 8,
+ kDaikin176HdrMark, kDaikin176HdrSpace,
+ kDaikin176BitMark, kDaikin176OneSpace,
+ kDaikin176BitMark, kDaikin176ZeroSpace,
+ kDaikin176BitMark, kDaikin176Gap,
+ section >= kDaikin176Sections - 1,
+ kDaikinTolerance, kDaikinMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
+ pos += ksectionSize[section];
+ }
+ // Compliance
+ if (strict) {
+ // Validate the checksum.
+ if (!IRDaikin176::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->decode_type = decode_type_t::DAIKIN176;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_DAIKIN176
+
+#if SEND_DAIKIN128
+// Send a Daikin 128 bit A/C message.
+//
+// Args:
+// data: An array of kDaikin128StateLength bytes containing the IR command.
+//
+// Status: STABLE / Known Working.
+//
+// Supported devices:
+// - Daikin BRC52B63 remote.
+//
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/827
+void IRsend::sendDaikin128(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ if (nbytes < kDaikin128SectionLength)
+ return; // Not enough bytes to send a partial message.
+
+ for (uint16_t r = 0; r <= repeat; r++) {
+ enableIROut(kDaikin128Freq);
+ // Leader
+ for (uint8_t i = 0; i < 2; i++) {
+ mark(kDaikin128LeaderMark);
+ space(kDaikin128LeaderSpace);
+ }
+ // Section #1 (Header + Data)
+ sendGeneric(kDaikin128HdrMark, kDaikin128HdrSpace, kDaikin128BitMark,
+ kDaikin128OneSpace, kDaikin128BitMark, kDaikin128ZeroSpace,
+ kDaikin128BitMark, kDaikin128Gap, data,
+ kDaikin128SectionLength,
+ kDaikin128Freq, false, 0, kDutyDefault);
+ // Section #2 (Data + Footer)
+ sendGeneric(0, 0, kDaikin128BitMark,
+ kDaikin128OneSpace, kDaikin128BitMark, kDaikin128ZeroSpace,
+ kDaikin128FooterMark, kDaikin128Gap,
+ data + kDaikin128SectionLength,
+ nbytes - kDaikin128SectionLength,
+ kDaikin128Freq, false, 0, kDutyDefault);
+ }
+}
+#endif // SEND_DAIKIN128
+
+// Class for handling Daikin 128 bit / 16 byte A/C messages.
+//
+// Code by crankyoldgit.
+// Analysis by Daniel Vena
+//
+// Status: STABLE / Known Working.
+//
+// Supported Remotes: Daikin BRC52B63 remote
+//
+IRDaikin128::IRDaikin128(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
+
+void IRDaikin128::begin() { _irsend.begin(); }
+
+uint8_t IRDaikin128::calcFirstChecksum(const uint8_t state[]) {
+ return sumNibbles(state, kDaikin128SectionLength - 1,
+ state[kDaikin128SectionLength - 1] & 0x0F) & 0x0F;
+}
+
+uint8_t IRDaikin128::calcSecondChecksum(const uint8_t state[]) {
+ return sumNibbles(state + kDaikin128SectionLength,
+ kDaikin128SectionLength - 1);
+}
+
+// Verify the checksum is valid for a given state.
+// Args:
+// state: The array to verify the checksum of.
+// Returns:
+// A boolean.
+bool IRDaikin128::validChecksum(uint8_t state[]) {
+ // Validate the checksum of section #1.
+ if (state[kDaikin128SectionLength - 1] >> 4 != calcFirstChecksum(state))
+ return false;
+ // Validate the checksum of section #2
+ if (state[kDaikin128StateLength - 1] != calcSecondChecksum(state))
+ return false;
+ return true;
+}
+
+// Calculate and set the checksum values for the internal state.
+void IRDaikin128::checksum() {
+ remote_state[kDaikin128SectionLength - 1] &= 0x0F; // Clear upper half.
+ remote_state[kDaikin128SectionLength - 1] |=
+ (calcFirstChecksum(remote_state) << 4);
+ remote_state[kDaikin128StateLength - 1] = calcSecondChecksum(remote_state);
+}
+
+void IRDaikin128::stateReset() {
+ for (uint8_t i = 0; i < kDaikin128StateLength; i++) remote_state[i] = 0x00;
+ remote_state[0] = 0x16;
+ remote_state[7] = 0x04; // Most significant nibble is a checksum.
+ remote_state[8] = 0xA1;
+ // remote_state[15] is a checksum byte, it will be set by checksum().
+}
+
+uint8_t *IRDaikin128::getRaw() {
+ checksum(); // Ensure correct settings before sending.
+ return remote_state;
+}
+
+void IRDaikin128::setRaw(const uint8_t new_code[]) {
+ for (uint8_t i = 0; i < kDaikin128StateLength; i++)
+ remote_state[i] = new_code[i];
+}
+
+#if SEND_DAIKIN128
+void IRDaikin128::send(const uint16_t repeat) {
+ checksum();
+ _irsend.sendDaikin128(remote_state, kDaikin128StateLength, repeat);
+}
+#endif // SEND_DAIKIN128
+
+void IRDaikin128::setPowerToggle(const bool toggle) {
+ if (toggle)
+ remote_state[kDaikin128BytePowerSwingSleep] |= kDaikin128BitPowerToggle;
+ else
+ remote_state[kDaikin128BytePowerSwingSleep] &= ~kDaikin128BitPowerToggle;
+}
+
+bool IRDaikin128::getPowerToggle(void) {
+ return remote_state[kDaikin128BytePowerSwingSleep] & kDaikin128BitPowerToggle;
+}
+
+uint8_t IRDaikin128::getMode() {
+ return remote_state[kDaikin128ByteModeFan] & kDaikin128MaskMode;
+}
+
+void IRDaikin128::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kDaikin128Auto:
+ case kDaikin128Cool:
+ case kDaikin128Heat:
+ case kDaikin128Fan:
+ case kDaikin128Dry:
+ remote_state[kDaikin128ByteModeFan] &= ~kDaikin128MaskMode;
+ remote_state[kDaikin128ByteModeFan] |= mode;
+ break;
+ default:
+ this->setMode(kDaikin128Auto);
+ return;
+ }
+ // Force a reset of mode dependant things.
+ setFan(getFan()); // Covers Quiet & Powerful too.
+ setEcono(getEcono());
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRDaikin128::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kDaikin128Cool;
+ case stdAc::opmode_t::kHeat:
+ return kDaikin128Heat;
+ case stdAc::opmode_t::kDry:
+ return kDaikinDry;
+ case stdAc::opmode_t::kFan:
+ return kDaikin128Fan;
+ default:
+ return kDaikin128Auto;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRDaikin128::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kDaikin128Cool: return stdAc::opmode_t::kCool;
+ case kDaikin128Heat: return stdAc::opmode_t::kHeat;
+ case kDaikin128Dry: return stdAc::opmode_t::kDry;
+ case kDaikin128Fan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Set the temp in deg C
+void IRDaikin128::setTemp(const uint8_t temp) {
+ remote_state[kDaikin128ByteTemp] = uint8ToBcd(
+ std::min(kDaikin128MaxTemp, std::max(temp, kDaikin128MinTemp)));
+}
+
+uint8_t IRDaikin128::getTemp(void) {
+ return bcdToUint8(remote_state[kDaikin128ByteTemp]);
+}
+
+uint8_t IRDaikin128::getFan() {
+ return (remote_state[kDaikin128ByteModeFan] & kDaikin128MaskFan) >> 4;
+}
+
+void IRDaikin128::setFan(const uint8_t speed) {
+ uint8_t new_speed = speed;
+ uint8_t mode = getMode();
+ switch (speed) {
+ case kDaikin128FanQuiet:
+ case kDaikin128FanPowerful:
+ if (mode == kDaikin128Auto) new_speed = kDaikin128FanAuto;
+ // FALL-THRU
+ case kDaikin128FanAuto:
+ case kDaikin128FanHigh:
+ case kDaikin128FanMed:
+ case kDaikin128FanLow:
+ // if (mode == kDaikinDry) new_speed = kDaikin128FanMed;
+ remote_state[kDaikin128ByteModeFan] &= ~kDaikin128MaskFan;
+ remote_state[kDaikin128ByteModeFan] |= (new_speed << 4);
+ break;
+ default:
+ this->setFan(kDaikin128FanAuto);
+ }
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRDaikin128::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin: return kDaikinFanQuiet;
+ case stdAc::fanspeed_t::kLow: return kDaikin128FanLow;
+ case stdAc::fanspeed_t::kMedium: return kDaikin128FanMed;
+ case stdAc::fanspeed_t::kHigh: return kDaikin128FanHigh;
+ case stdAc::fanspeed_t::kMax: return kDaikin128FanPowerful;
+ default: return kDaikin128FanAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRDaikin128::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kDaikin128FanPowerful: return stdAc::fanspeed_t::kMax;
+ case kDaikin128FanHigh: return stdAc::fanspeed_t::kHigh;
+ case kDaikin128FanMed: return stdAc::fanspeed_t::kMedium;
+ case kDaikin128FanLow: return stdAc::fanspeed_t::kLow;
+ case kDaikinFanQuiet: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+void IRDaikin128::setSwingVertical(const bool on) {
+ if (on)
+ remote_state[kDaikin128BytePowerSwingSleep] |= kDaikin128BitSwing;
+ else
+ remote_state[kDaikin128BytePowerSwingSleep] &= ~kDaikin128BitSwing;
+}
+
+bool IRDaikin128::getSwingVertical(void) {
+ return remote_state[kDaikin128BytePowerSwingSleep] & kDaikin128BitSwing;
+}
+
+void IRDaikin128::setSleep(const bool on) {
+ if (on)
+ remote_state[kDaikin128BytePowerSwingSleep] |= kDaikin128BitSleep;
+ else
+ remote_state[kDaikin128BytePowerSwingSleep] &= ~kDaikin128BitSleep;
+}
+
+bool IRDaikin128::getSleep(void) {
+ return remote_state[kDaikin128BytePowerSwingSleep] & kDaikin128BitSleep;
+}
+
+void IRDaikin128::setEcono(const bool on) {
+ uint8_t mode = getMode();
+ if (on && (mode == kDaikin128Cool || mode == kDaikin128Heat))
+ remote_state[kDaikin128ByteEconoLight] |= kDaikin128BitEcono;
+ else
+ remote_state[kDaikin128ByteEconoLight] &= ~kDaikin128BitEcono;
+}
+
+bool IRDaikin128::getEcono(void) {
+ return remote_state[kDaikin128ByteEconoLight] & kDaikin128BitEcono;
+}
+
+void IRDaikin128::setQuiet(const bool on) {
+ uint8_t mode = getMode();
+ if (on && (mode == kDaikin128Cool || mode == kDaikin128Heat))
+ setFan(kDaikin128FanQuiet);
+ else if (getFan() == kDaikin128FanQuiet)
+ setFan(kDaikin128FanAuto);
+}
+
+bool IRDaikin128::getQuiet(void) {
+ return getFan() == kDaikin128FanQuiet;
+}
+
+void IRDaikin128::setPowerful(const bool on) {
+ uint8_t mode = getMode();
+ if (on && (mode == kDaikin128Cool || mode == kDaikin128Heat))
+ setFan(kDaikin128FanPowerful);
+ else if (getFan() == kDaikin128FanPowerful)
+ setFan(kDaikin128FanAuto);
+}
+
+bool IRDaikin128::getPowerful(void) {
+ return getFan() == kDaikin128FanPowerful;
+}
+
+// Set the clock in mins since midnight
+void IRDaikin128::setClock(const uint16_t mins_since_midnight) {
+ uint16_t mins = mins_since_midnight;
+ if (mins_since_midnight >= 24 * 60) mins = 0; // Bounds check.
+ // Hours.
+ remote_state[kDaikin128ByteClockHours] = uint8ToBcd(mins / 60);
+ // Minutes.
+ remote_state[kDaikin128ByteClockMins] = uint8ToBcd(mins % 60);
+}
+
+uint16_t IRDaikin128::getClock(void) {
+ return bcdToUint8(remote_state[kDaikin128ByteClockHours]) * 60 +
+ bcdToUint8(remote_state[kDaikin128ByteClockMins]);
+}
+
+void IRDaikin128::setOnTimerEnabled(const bool on) {
+ if (on)
+ remote_state[kDaikin128ByteOnTimer] |= kDaikin128BitTimerEnabled;
+ else
+ remote_state[kDaikin128ByteOnTimer] &= ~kDaikin128BitTimerEnabled;
+}
+
+bool IRDaikin128::getOnTimerEnabled(void) {
+ return remote_state[kDaikin128ByteOnTimer] & kDaikin128BitTimerEnabled;
+}
+
+// Timer is rounds down to the nearest half hour.
+// Args:
+// ptr: A PTR to the byte containing the Timer value to be updated.
+// mins_since_midnight: The number of minutes the new timer should be set to.
+void IRDaikin128::setTimer(uint8_t *ptr, const uint16_t mins_since_midnight) {
+ uint16_t mins = mins_since_midnight;
+ if (mins_since_midnight >= 24 * 60) mins = 0; // Bounds check.
+ // Clear the time component
+ *ptr &= kDaikin128BitTimerEnabled;
+ uint8_t bcdhours = uint8ToBcd(mins / 60);
+ bool addhalf = (mins % 60) >= 30;
+ *ptr |= ((addhalf << 6) | bcdhours);
+}
+
+// Timer is stored in nr of half hours internally.
+// Args:
+// ptr: A PTR to the byte containing the Timer value.
+// Returns:
+// A uint16_t containing the number of minutes since midnight.
+uint16_t IRDaikin128::getTimer(const uint8_t *ptr) {
+ uint8_t bcdhours = *ptr & kDaikin128MaskHours;
+ bool addhalf = *ptr & kDaikin128BitHalfHour;
+ return bcdToUint8(bcdhours) * 60 + (addhalf ? 30 : 0);
+}
+
+void IRDaikin128::setOnTimer(const uint16_t mins_since_midnight) {
+ setTimer(remote_state + kDaikin128ByteOnTimer, mins_since_midnight);
+}
+
+uint16_t IRDaikin128::getOnTimer(void) {
+ return getTimer(remote_state + kDaikin128ByteOnTimer);
+}
+
+void IRDaikin128::setOffTimerEnabled(const bool on) {
+ if (on)
+ remote_state[kDaikin128ByteOffTimer] |= kDaikin128BitTimerEnabled;
+ else
+ remote_state[kDaikin128ByteOffTimer] &= ~kDaikin128BitTimerEnabled;
+}
+
+bool IRDaikin128::getOffTimerEnabled(void) {
+ return remote_state[kDaikin128ByteOffTimer] & kDaikin128BitTimerEnabled;
+}
+
+void IRDaikin128::setOffTimer(const uint16_t mins_since_midnight) {
+ setTimer(remote_state + kDaikin128ByteOffTimer, mins_since_midnight);
+}
+
+uint16_t IRDaikin128::getOffTimer(void) {
+ return getTimer(remote_state + kDaikin128ByteOffTimer);
+}
+
+void IRDaikin128::setLightToggle(const uint8_t unit) {
+ switch (unit) {
+ case kDaikin128BitCeiling:
+ case kDaikin128BitWall:
+ case 0:
+ remote_state[kDaikin128ByteEconoLight] &= ~kDaikin128MaskLight;
+ remote_state[kDaikin128ByteEconoLight] |= unit;
+ break;
+ default: setLightToggle(0);
+ }
+}
+
+uint8_t IRDaikin128::getLightToggle(void) {
+ return remote_state[kDaikin128ByteEconoLight] & kDaikin128MaskLight;
+}
+
+// Convert the internal state into a human readable string.
+String IRDaikin128::toString(void) {
+ String result = "";
+ result.reserve(240); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPowerToggle(), F("Power Toggle"), false);
+ result += addModeToString(getMode(), kDaikin128Auto, kDaikin128Cool,
+ kDaikin128Heat, kDaikin128Dry, kDaikin128Fan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kDaikin128FanHigh, kDaikin128FanLow,
+ kDaikin128FanAuto, kDaikin128FanQuiet,
+ kDaikin128FanMed);
+ result += addBoolToString(getPowerful(), F("Powerful"));
+ result += addBoolToString(getQuiet(), F("Quiet"));
+ result += addBoolToString(getSwingVertical(), F("Swing (V)"));
+ result += addBoolToString(getSleep(), F("Sleep"));
+ result += addBoolToString(getEcono(), F("Econo"));
+ result += addLabeledString(minsToString(getClock()), F("Clock"));
+ result += addBoolToString(getOnTimerEnabled(), F("On Timer"));
+ result += addLabeledString(minsToString(getOnTimer()), F("On Time"));
+ result += addBoolToString(getOffTimerEnabled(), F("Off Timer"));
+ result += addLabeledString(minsToString(getOffTimer()), F("Off Time"));
+ result += addIntToString(getLightToggle(), F("Light Toggle"));
+ result += F(" (");
+ switch (getLightToggle()) {
+ case kDaikin128BitCeiling: result += F("Ceiling"); break;
+ case kDaikin128BitWall: result += F("Wall"); break;
+ case 0: result += F("Off"); break;
+ default: result += F("UNKNOWN");
+ }
+ result += ')';
+ return result;
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRDaikin128::toCommon(const stdAc::state_t *prev) {
+ stdAc::state_t result;
+ if (prev != NULL) result = *prev;
+ result.protocol = decode_type_t::DAIKIN128;
+ result.model = -1; // No models used.
+ result.power ^= getPowerToggle();
+ result.mode = toCommonMode(getMode());
+ result.celsius = true;
+ result.degrees = getTemp();
+ result.fanspeed = toCommonFanSpeed(getFan());
+ result.swingv = getSwingVertical() ? stdAc::swingv_t::kAuto
+ : stdAc::swingv_t::kOff;
+ result.quiet = getQuiet();
+ result.turbo = getPowerful();
+ result.econo = getEcono();
+ result.light ^= (getLightToggle() != 0);
+ result.sleep = getSleep() ? 0 : -1;
+ result.clock = getClock();
+ // Not supported.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.clean = false;
+ result.filter = false;
+ result.beep = false;
+ return result;
+}
+
+#if DECODE_DAIKIN128
+// Decode the supplied Daikin 128 bit A/C message.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion. (kDaikin128Bits)
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Supported devices:
+// - Daikin BRC52B63 remote.
+//
+// Status: STABLE / Known Working.
+//
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/827
+bool IRrecv::decodeDaikin128(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ if (results->rawlen < 2 * (nbits + kHeader) + kFooter - 1)
+ return false;
+ if (nbits / 8 <= kDaikin128SectionLength) return false;
+
+ // Compliance
+ if (strict && nbits != kDaikin128Bits) return false;
+
+ uint16_t offset = kStartOffset;
+
+ // Leader
+ for (uint8_t i = 0; i < 2; i++) {
+ if (!matchMark(results->rawbuf[offset++], kDaikin128LeaderMark,
+ kDaikinTolerance, kDaikinMarkExcess)) return false;
+ if (!matchSpace(results->rawbuf[offset++], kDaikin128LeaderSpace,
+ kDaikinTolerance, kDaikinMarkExcess)) return false;
+ }
+ const uint16_t ksectionSize[kDaikin128Sections] = {
+ kDaikin128SectionLength, (uint16_t)(nbits / 8 - kDaikin128SectionLength)};
+ // Data Sections
+ uint16_t pos = 0;
+ for (uint8_t section = 0; section < kDaikin128Sections; section++) {
+ uint16_t used;
+ // Section Header (first section only) + Section Data (8 bytes) +
+ // Section Footer (Not for first section)
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, ksectionSize[section] * 8,
+ section == 0 ? kDaikin128HdrMark : 0,
+ section == 0 ? kDaikin128HdrSpace : 0,
+ kDaikin128BitMark, kDaikin128OneSpace,
+ kDaikin128BitMark, kDaikin128ZeroSpace,
+ section > 0 ? kDaikin128FooterMark : kDaikin128BitMark,
+ kDaikin128Gap,
+ section > 0,
+ kDaikinTolerance, kDaikinMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
+ pos += ksectionSize[section];
+ }
+ // Compliance
+ if (strict) {
+ if (!IRDaikin128::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->decode_type = decode_type_t::DAIKIN128;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_DAIKIN128
+
+#if SEND_DAIKIN152
+// Send a Daikin 152 bit A/C message.
+//
+// Args:
+// data: An array of kDaikin152StateLength bytes containing the IR command.
+//
+// Supported devices:
+// - Daikin ARC480A5 remote.
+//
+// Status: Beta / Probably working.
+//
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/873
+void IRsend::sendDaikin152(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ for (uint16_t r = 0; r <= repeat; r++) {
+ // Leader
+ sendGeneric(0, 0, kDaikin152BitMark, kDaikin152OneSpace,
+ kDaikin152BitMark, kDaikin152ZeroSpace,
+ kDaikin152BitMark, kDaikin152Gap,
+ (uint64_t)0, kDaikin152LeaderBits,
+ kDaikin152Freq, false, 0, kDutyDefault);
+ // Header + Data + Footer
+ sendGeneric(kDaikin152HdrMark, kDaikin152HdrSpace, kDaikin152BitMark,
+ kDaikin152OneSpace, kDaikin152BitMark, kDaikin152ZeroSpace,
+ kDaikin152BitMark, kDaikin152Gap, data,
+ nbytes, kDaikin152Freq, false, 0, kDutyDefault);
+ }
+}
+#endif // SEND_DAIKIN152
+
+#if DECODE_DAIKIN152
+// Decode the supplied Daikin 152 bit A/C message.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion. (kDaikin152Bits)
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Supported devices:
+// - Daikin ARC480A5 remote.
+//
+// Status: Beta / Probably working.
+//
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/873
+bool IRrecv::decodeDaikin152(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ if (results->rawlen < 2 * (5 + nbits + kFooter) + kHeader - 1)
+ return false;
+ if (nbits / 8 < kDaikin152StateLength) return false;
+
+ // Compliance
+ if (strict && nbits != kDaikin152Bits) return false;
+
+ uint16_t offset = kStartOffset;
+ uint16_t used;
+
+ // Leader
+ uint64_t leader = 0;
+ used = matchGeneric(results->rawbuf + offset, &leader,
+ results->rawlen - offset, kDaikin152LeaderBits,
+ 0, 0, // No Header
+ kDaikin152BitMark, kDaikin152OneSpace,
+ kDaikin152BitMark, kDaikin152ZeroSpace,
+ kDaikin152BitMark, kDaikin152Gap, // Footer gap
+ false, _tolerance, kMarkExcess, false);
+ if (used == 0 || leader != 0) return false;
+ offset += used;
+
+ // Header + Data + Footer
+ used = matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kDaikin152HdrMark, kDaikin152HdrSpace,
+ kDaikin152BitMark, kDaikin152OneSpace,
+ kDaikin152BitMark, kDaikin152ZeroSpace,
+ kDaikin152BitMark, kDaikin152Gap,
+ true, _tolerance, kMarkExcess, false);
+ if (used == 0) return false;
+
+ // Compliance
+ if (strict) {
+ if (!IRDaikin152::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->decode_type = decode_type_t::DAIKIN152;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_DAIKIN152
+
+// Class for handling Daikin 152 bit / 19 byte A/C messages.
+//
+// Code by crankyoldgit.
+//
+// Supported Remotes: Daikin ARC480A5 remote
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/873
+IRDaikin152::IRDaikin152(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
+
+void IRDaikin152::begin() { _irsend.begin(); }
+
+#if SEND_DAIKIN152
+void IRDaikin152::send(const uint16_t repeat) {
+ checksum();
+ _irsend.sendDaikin152(remote_state, kDaikin152StateLength, repeat);
+}
+#endif // SEND_DAIKIN152
+
+// Verify the checksum is valid for a given state.
+// Args:
+// state: The array to verify the checksum of.
+// length: The size of the state.
+// Returns:
+// A boolean.
+bool IRDaikin152::validChecksum(uint8_t state[], const uint16_t length) {
+ // Validate the checksum of the given state.
+ if (length <= 1 || state[length - 1] != sumBytes(state, length - 1))
+ return false;
+ else
+ return true;
+}
+
+// Calculate and set the checksum values for the internal state.
+void IRDaikin152::checksum() {
+ remote_state[kDaikin152StateLength - 1] = sumBytes(
+ remote_state, kDaikin152StateLength - 1);
+}
+
+void IRDaikin152::stateReset() {
+ for (uint8_t i = 3; i < kDaikin152StateLength; i++) remote_state[i] = 0x00;
+ remote_state[0] = 0x11;
+ remote_state[1] = 0xDA;
+ remote_state[2] = 0x27;
+ // remote_state[19] is a checksum byte, it will be set by checksum().
+}
+
+uint8_t *IRDaikin152::getRaw() {
+ checksum(); // Ensure correct settings before sending.
+ return remote_state;
+}
+
+void IRDaikin152::setRaw(const uint8_t new_code[]) {
+ for (uint8_t i = 0; i < kDaikin152StateLength; i++)
+ remote_state[i] = new_code[i];
+}
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.h b/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.h
new file mode 100644
index 000000000..98a38c640
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.h
@@ -0,0 +1,763 @@
+// Copyright 2016 sillyfrog
+// Copyright 2017 sillyfrog, crankyoldgit
+// Copyright 2018-2019 crankyoldgit
+
+// Supports:
+// Brand: Daikin, Model: ARC433** remote
+// Brand: Daikin, Model: ARC477A1 remote
+// Brand: Daikin, Model: FTXZ25NV1B A/C
+// Brand: Daikin, Model: FTXZ35NV1B A/C
+// Brand: Daikin, Model: FTXZ50NV1B A/C
+// Brand: Daikin, Model: ARC433B69 remote
+// Brand: Daikin, Model: ARC423A5 remote
+// Brand: Daikin, Model: FTE12HV2S A/C
+// Brand: Daikin, Model: BRC4C153 remote
+// Brand: Daikin, Model: 17 Series A/C (DAIKIN128)
+// Brand: Daikin, Model: FTXB12AXVJU A/C (DAIKIN128)
+// Brand: Daikin, Model: FTXB09AXVJU A/C (DAIKIN128)
+// Brand: Daikin, Model: BRC52B63 remote (DAIKIN128)
+// Brand: Daikin, Model: ARC480A5 remote (DAIKIN152)
+
+#ifndef IR_DAIKIN_H_
+#define IR_DAIKIN_H_
+
+#ifndef UNIT_TEST
+#include
+#endif
+#include "IRrecv.h"
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#ifdef UNIT_TEST
+#include "IRsend_test.h"
+#endif
+
+/*
+ Daikin AC map (i.e. DAIKIN, not the other variants)
+ byte 6=
+ b4:Comfort
+ byte 7= checksum of the first part (and last byte before a 29ms pause)
+ byte 13=Current time, mins past midnight, low bits
+ byte 14
+ b5-b3=Day of the week (SUN=1, MON=2, ..., SAT=7)
+ b2-b0=Current time, mins past midnight, high bits
+ byte 15= checksum of the second part (and last byte before a 29ms pause)
+ byte 21=mode
+ b7 = 0
+ b6+b5+b4 = Mode
+ Modes: b6+b5+b4
+ 011 = Cool
+ 100 = Heat (temp 23)
+ 110 = FAN (temp not shown, but 25)
+ 000 = Fully Automatic (temp 25)
+ 010 = DRY (temp 0xc0 = 96 degrees c)
+ b3 = 1
+ b2 = OFF timer set
+ b1 = ON timer set
+ b0 = Air Conditioner ON
+ byte 22=temp*2 (Temp should be between 10 - 32)
+ byte 24=Fan
+ FAN control
+ b7+b6+b5+b4 = Fan speed
+ Fan: b7+b6+b5+b4
+ 0Ć3 = 1 bar
+ 0Ć4 = 2 bar
+ 0Ć5 = 3 bar
+ 0Ć6 = 4 bar
+ 0Ć7 = 5 bar
+ 0xa = Auto
+ 0xb = Quite
+ b3+b2+b1+b0 = Swing control up/down
+ Swing control up/down:
+ 0000 = Swing up/down off
+ 1111 = Swing up/down on
+ byte 25
+ Swing control left/right:
+ 0000 = Swing left/right off
+ 1111 = Swing left/right on
+ byte 26=On timer mins past midnight, low bits
+ byte 27
+ b0-b3=On timer mins past midnight, high bits
+ b4-b7=Off timer mins past midnight, low bits
+ byte 28=Off timer mins past midnight, high bits
+ byte 29=Aux -> Powerful (bit 1), Silent (bit 5)
+ byte 32=Aux2
+ b1: Sensor
+ b2: Econo mode
+ b7: Intelligent eye on
+ byte 33=Aux3
+ b1: Mold Proof
+ byte 34= checksum of the third part
+*/
+
+// Constants
+const uint8_t kDaikinAuto = 0b000;
+const uint8_t kDaikinDry = 0b010;
+const uint8_t kDaikinCool = 0b011;
+const uint8_t kDaikinHeat = 0b100;
+const uint8_t kDaikinFan = 0b110;
+const uint8_t kDaikinMinTemp = 10; // Celsius
+const uint8_t kDaikinMaxTemp = 32; // Celsius
+const uint8_t kDaikinFanMin = 1;
+const uint8_t kDaikinFanMed = 3;
+const uint8_t kDaikinFanMax = 5;
+const uint8_t kDaikinFanAuto = 0b1010;
+const uint8_t kDaikinFanQuiet = 0b1011;
+const uint16_t kDaikinHeaderLength = 5;
+const uint8_t kDaikinSections = 3;
+const uint8_t kDaikinSection1Length = 8;
+const uint8_t kDaikinSection2Length = 8;
+const uint8_t kDaikinSection3Length =
+ kDaikinStateLength - kDaikinSection1Length - kDaikinSection2Length;
+const uint8_t kDaikinByteComfort = 6;
+const uint8_t kDaikinByteChecksum1 = 7;
+const uint8_t kDaikinBitComfort = 0b00010000;
+const uint8_t kDaikinByteClockMinsLow = 13;
+const uint8_t kDaikinByteClockMinsHigh = 14;
+const uint8_t kDaikinByteChecksum2 = 15;
+const uint8_t kDaikinBytePower = 21;
+const uint8_t kDaikinBitPower = 0b00000001;
+const uint8_t kDaikinByteTemp = 22;
+const uint8_t kDaikinByteFan = 24;
+const uint8_t kDaikinByteSwingH = 25;
+const uint8_t kDaikinByteOnTimerMinsLow = 26;
+const uint8_t kDaikinByteOnTimerMinsHigh = 27;
+const uint8_t kDaikinByteOffTimerMinsLow = kDaikinByteOnTimerMinsHigh;
+const uint8_t kDaikinByteOffTimerMinsHigh = 28;
+const uint8_t kDaikinBytePowerful = 29;
+const uint8_t kDaikinBitPowerful = 0b00000001;
+const uint8_t kDaikinByteSilent = kDaikinBytePowerful;
+const uint8_t kDaikinBitSilent = 0b00100000;
+const uint8_t kDaikinByteSensor = 32;
+const uint8_t kDaikinBitSensor = 0b00000010;
+const uint8_t kDaikinByteEcono = kDaikinByteSensor;
+const uint8_t kDaikinBitEcono = 0b00000100;
+const uint8_t kDaikinByteEye = kDaikinByteSensor;
+const uint8_t kDaikinBitEye = 0b10000000;
+const uint8_t kDaikinByteWeeklyTimer = kDaikinByteSensor;
+const uint8_t kDaikinBitWeeklyTimer = 0b10000000;
+const uint8_t kDaikinByteMold = 33;
+const uint8_t kDaikinBitMold = 0b00000010;
+const uint8_t kDaikinByteOffTimer = kDaikinBytePower;
+const uint8_t kDaikinBitOffTimer = 0b00000100;
+const uint8_t kDaikinByteOnTimer = kDaikinByteOffTimer;
+const uint8_t kDaikinBitOnTimer = 0b00000010;
+const uint8_t kDaikinByteChecksum3 = kDaikinStateLength - 1;
+const uint16_t kDaikinUnusedTime = 0x600;
+const uint8_t kDaikinBeepQuiet = 1;
+const uint8_t kDaikinBeepLoud = 2;
+const uint8_t kDaikinBeepOff = 3;
+const uint8_t kDaikinLightBright = 1;
+const uint8_t kDaikinLightDim = 2;
+const uint8_t kDaikinLightOff = 3;
+const uint8_t kDaikinCurBit = kDaikinStateLength;
+const uint8_t kDaikinCurIndex = kDaikinStateLength + 1;
+const uint8_t kDaikinTolerance = 35;
+const uint16_t kDaikinMarkExcess = kMarkExcess;
+const uint16_t kDaikinHdrMark = 3650; // kDaikinBitMark * 8
+const uint16_t kDaikinHdrSpace = 1623; // kDaikinBitMark * 4
+const uint16_t kDaikinBitMark = 428;
+const uint16_t kDaikinZeroSpace = 428;
+const uint16_t kDaikinOneSpace = 1280;
+const uint16_t kDaikinGap = 29000;
+// Note bits in each octet swapped so can be sent as a single value
+const uint64_t kDaikinFirstHeader64 =
+ 0b1101011100000000000000001100010100000000001001111101101000010001;
+
+// Another variant of the protocol for the Daikin ARC477A1 remote.
+const uint16_t kDaikin2Freq = 36700; // Modulation Frequency in Hz.
+const uint16_t kDaikin2LeaderMark = 10024;
+const uint16_t kDaikin2LeaderSpace = 25180;
+const uint16_t kDaikin2Gap = kDaikin2LeaderMark + kDaikin2LeaderSpace;
+const uint16_t kDaikin2HdrMark = 3500;
+const uint16_t kDaikin2HdrSpace = 1728;
+const uint16_t kDaikin2BitMark = 460;
+const uint16_t kDaikin2OneSpace = 1270;
+const uint16_t kDaikin2ZeroSpace = 420;
+const uint16_t kDaikin2Sections = 2;
+const uint16_t kDaikin2Section1Length = 20;
+const uint16_t kDaikin2Section2Length = 19;
+const uint8_t kDaikin2Tolerance = 5; // Extra percentage tolerance
+
+const uint8_t kDaikin2BitSleepTimer = 0b00100000;
+const uint8_t kDaikin2BitPurify = 0b00010000;
+const uint8_t kDaikin2BitEye = 0b00000010;
+const uint8_t kDaikin2BitEyeAuto = 0b10000000;
+const uint8_t kDaikin2BitMold = 0b00001000;
+const uint8_t kDaikin2BitClean = 0b00100000;
+const uint8_t kDaikin2BitFreshAir = 0b00000001;
+const uint8_t kDaikin2BitFreshAirHigh = 0b10000000;
+const uint8_t kDaikin2BitPower = 0b10000000;
+const uint8_t kDaikin2LightMask = 0b00110000;
+const uint8_t kDaikin2BeepMask = 0b11000000;
+const uint8_t kDaikin2SwingVHigh = 0x1;
+const uint8_t kDaikin2SwingVLow = 0x6;
+const uint8_t kDaikin2SwingVBreeze = 0xC;
+const uint8_t kDaikin2SwingVCirculate = 0xD;
+const uint8_t kDaikin2SwingVAuto = 0xE;
+const uint8_t kDaikin2SwingHAuto = 0xBE;
+const uint8_t kDaikin2SwingHSwing = 0xBF;
+const uint8_t kDaikin2MinCoolTemp = 18; // Min temp (in C) when in Cool mode.
+
+// Another variant of the protocol for the Daikin ARC433B69 remote.
+const uint16_t kDaikin216Freq = 38000; // Modulation Frequency in Hz.
+const uint16_t kDaikin216HdrMark = 3440;
+const uint16_t kDaikin216HdrSpace = 1750;
+const uint16_t kDaikin216BitMark = 420;
+const uint16_t kDaikin216OneSpace = 1300;
+const uint16_t kDaikin216ZeroSpace = 450;
+const uint16_t kDaikin216Gap = 29650;
+const uint16_t kDaikin216Sections = 2;
+const uint16_t kDaikin216Section1Length = 8;
+const uint16_t kDaikin216Section2Length = kDaikin216StateLength -
+ kDaikin216Section1Length;
+const uint8_t kDaikin216BytePower = 13;
+const uint8_t kDaikin216ByteMode = kDaikin216BytePower;
+const uint8_t kDaikin216MaskMode = 0b01110000;
+const uint8_t kDaikin216ByteTemp = 14;
+const uint8_t kDaikin216MaskTemp = 0b01111110;
+const uint8_t kDaikin216ByteFan = 16;
+const uint8_t kDaikin216MaskFan = 0b11110000;
+const uint8_t kDaikin216ByteSwingV = 16;
+const uint8_t kDaikin216MaskSwingV = 0b00001111;
+const uint8_t kDaikin216ByteSwingH = 17;
+const uint8_t kDaikin216MaskSwingH = kDaikin216MaskSwingV;
+const uint8_t kDaikin216BytePowerful = 21;
+
+// Another variant of the protocol for the Daikin ARC423A5 remote.
+const uint16_t kDaikin160Freq = 38000; // Modulation Frequency in Hz.
+const uint16_t kDaikin160HdrMark = 5000;
+const uint16_t kDaikin160HdrSpace = 2145;
+const uint16_t kDaikin160BitMark = 342;
+const uint16_t kDaikin160OneSpace = 1786;
+const uint16_t kDaikin160ZeroSpace = 700;
+const uint16_t kDaikin160Gap = 29650;
+const uint16_t kDaikin160Sections = 2;
+const uint16_t kDaikin160Section1Length = 7;
+const uint16_t kDaikin160Section2Length = kDaikin160StateLength -
+ kDaikin160Section1Length;
+const uint8_t kDaikin160BytePower = 12;
+const uint8_t kDaikin160ByteMode = kDaikin160BytePower;
+const uint8_t kDaikin160MaskMode = 0b01110000;
+const uint8_t kDaikin160ByteTemp = 16;
+const uint8_t kDaikin160MaskTemp = 0b01111110;
+const uint8_t kDaikin160ByteFan = 17;
+const uint8_t kDaikin160MaskFan = 0b00001111;
+const uint8_t kDaikin160ByteSwingV = 13;
+const uint8_t kDaikin160MaskSwingV = 0b11110000;
+const uint8_t kDaikin160SwingVLowest = 0x1;
+const uint8_t kDaikin160SwingVLow = 0x2;
+const uint8_t kDaikin160SwingVMiddle = 0x3;
+const uint8_t kDaikin160SwingVHigh = 0x4;
+const uint8_t kDaikin160SwingVHighest = 0x5;
+const uint8_t kDaikin160SwingVAuto = 0xF;
+
+// Another variant of the protocol for the Daikin BRC4C153 remote.
+const uint16_t kDaikin176Freq = 38000; // Modulation Frequency in Hz.
+const uint16_t kDaikin176HdrMark = 5070;
+const uint16_t kDaikin176HdrSpace = 2140;
+const uint16_t kDaikin176BitMark = 370;
+const uint16_t kDaikin176OneSpace = 1780;
+const uint16_t kDaikin176ZeroSpace = 710;
+const uint16_t kDaikin176Gap = 29410;
+const uint16_t kDaikin176Sections = 2;
+const uint16_t kDaikin176Section1Length = 7;
+const uint16_t kDaikin176Section2Length = kDaikin176StateLength -
+ kDaikin176Section1Length;
+const uint8_t kDaikin176Cool = 0b111; // 7
+const uint8_t kDaikin176BytePower = 14;
+const uint8_t kDaikin176ByteMode = 12;
+const uint8_t kDaikin176MaskMode = 0b01110000;
+const uint8_t kDaikin176ByteModeButton = 13;
+const uint8_t kDaikin176ModeButton = 0b00000100;
+const uint8_t kDaikin176ByteTemp = 17;
+const uint8_t kDaikin176MaskTemp = 0b01111110;
+const uint8_t kDaikin176DryFanTemp = 17; // Dry/Fan mode is always 17 Celsius.
+const uint8_t kDaikin176ByteFan = 18;
+const uint8_t kDaikin176MaskFan = 0b11110000;
+const uint8_t kDaikin176FanMax = 3;
+const uint8_t kDaikin176ByteSwingH = 18;
+const uint8_t kDaikin176MaskSwingH = 0b00001111;
+const uint8_t kDaikin176SwingHAuto = 0x5;
+const uint8_t kDaikin176SwingHOff = 0x6;
+
+// Another variant of the protocol for the Daikin BRC52B63 remote.
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/827
+const uint16_t kDaikin128Freq = 38000; // Modulation Frequency in Hz.
+const uint16_t kDaikin128LeaderMark = 9800;
+const uint16_t kDaikin128LeaderSpace = 9800;
+const uint16_t kDaikin128HdrMark = 4600;
+const uint16_t kDaikin128HdrSpace = 2500;
+const uint16_t kDaikin128BitMark = 350;
+const uint16_t kDaikin128OneSpace = 954;
+const uint16_t kDaikin128ZeroSpace = 382;
+const uint16_t kDaikin128Gap = 20300;
+const uint16_t kDaikin128FooterMark = kDaikin128HdrMark;
+const uint16_t kDaikin128Sections = 2;
+const uint16_t kDaikin128SectionLength = 8;
+const uint8_t kDaikin128ByteModeFan = 1;
+const uint8_t kDaikin128MaskMode = 0b00001111;
+const uint8_t kDaikin128Dry = 0b00000001;
+const uint8_t kDaikin128Cool = 0b00000010;
+const uint8_t kDaikin128Fan = 0b00000100;
+const uint8_t kDaikin128Heat = 0b00001000;
+const uint8_t kDaikin128Auto = 0b00001010;
+const uint8_t kDaikin128MaskFan = 0b11110000;
+const uint8_t kDaikin128FanAuto = 0b0001;
+const uint8_t kDaikin128FanHigh = 0b0010;
+const uint8_t kDaikin128FanMed = 0b0100;
+const uint8_t kDaikin128FanLow = 0b1000;
+const uint8_t kDaikin128FanPowerful = 0b0011;
+const uint8_t kDaikin128FanQuiet = 0b1001;
+const uint8_t kDaikin128ByteClockMins = 2;
+const uint8_t kDaikin128ByteClockHours = 3;
+const uint8_t kDaikin128ByteOnTimer = 4;
+const uint8_t kDaikin128ByteOffTimer = 5;
+const uint8_t kDaikin128BitTimerEnabled = 0b10000000;
+const uint8_t kDaikin128BitHalfHour = 0b01000000;
+const uint8_t kDaikin128MaskHours = 0b00111111;
+const uint8_t kDaikin128ByteTemp = 6;
+const uint8_t kDaikin128MinTemp = 16; // C
+const uint8_t kDaikin128MaxTemp = 30; // C
+const uint8_t kDaikin128BytePowerSwingSleep = 7;
+const uint8_t kDaikin128BitSwing = 0b00000001;
+const uint8_t kDaikin128BitSleep = 0b00000010;
+const uint8_t kDaikin128BitPowerToggle = 0b00001000;
+const uint8_t kDaikin128ByteEconoLight = 9;
+const uint8_t kDaikin128BitEcono = 0b00000100;
+const uint8_t kDaikin128BitWall = 0b00001000;
+const uint8_t kDaikin128BitCeiling = 0b00000001;
+const uint8_t kDaikin128MaskLight = kDaikin128BitWall | kDaikin128BitCeiling;
+
+// Another variant of the protocol for the Daikin ARC480A5 remote.
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/873
+const uint16_t kDaikin152Freq = 38000; // Modulation Frequency in Hz.
+const uint8_t kDaikin152LeaderBits = 5;
+const uint16_t kDaikin152HdrMark = 3492;
+const uint16_t kDaikin152HdrSpace = 1718;
+const uint16_t kDaikin152BitMark = 433;
+const uint16_t kDaikin152OneSpace = 1529;
+const uint16_t kDaikin152ZeroSpace = kDaikin152BitMark;
+const uint16_t kDaikin152Gap = 25182;
+
+// Legacy defines.
+#define DAIKIN_COOL kDaikinCool
+#define DAIKIN_HEAT kDaikinHeat
+#define DAIKIN_FAN kDaikinFan
+#define DAIKIN_AUTO kDaikinAuto
+#define DAIKIN_DRY kDaikinDry
+#define DAIKIN_MIN_TEMP kDaikinMinTemp
+#define DAIKIN_MAX_TEMP kDaikinMaxTemp
+#define DAIKIN_FAN_MIN kDaikinFanMin
+#define DAIKIN_FAN_MAX kDaikinFanMax
+#define DAIKIN_FAN_AUTO kDaikinFanAuto
+#define DAIKIN_FAN_QUIET kDaikinFanQuiet
+
+class IRDaikinESP {
+ public:
+ explicit IRDaikinESP(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+#if SEND_DAIKIN
+ void send(const uint16_t repeat = kDaikinDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp();
+ void setFan(const uint8_t fan);
+ uint8_t getFan(void);
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ void setSwingVertical(const bool on);
+ bool getSwingVertical(void);
+ void setSwingHorizontal(const bool on);
+ bool getSwingHorizontal(void);
+ bool getQuiet(void);
+ void setQuiet(const bool on);
+ bool getPowerful(void);
+ void setPowerful(const bool on);
+ void setSensor(const bool on);
+ bool getSensor(void);
+ void setEcono(const bool on);
+ bool getEcono(void);
+ void setMold(const bool on);
+ bool getMold(void);
+ void setComfort(const bool on);
+ bool getComfort(void);
+ void enableOnTimer(const uint16_t starttime);
+ void disableOnTimer(void);
+ uint16_t getOnTime(void);
+ bool getOnTimerEnabled();
+ void enableOffTimer(const uint16_t endtime);
+ void disableOffTimer(void);
+ uint16_t getOffTime(void);
+ bool getOffTimerEnabled(void);
+ void setCurrentTime(const uint16_t mins_since_midnight);
+ uint16_t getCurrentTime(void);
+ void setCurrentDay(const uint8_t day_of_week);
+ uint8_t getCurrentDay(void);
+ void setWeeklyTimerEnable(const bool on);
+ bool getWeeklyTimerEnable(void);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t new_code[],
+ const uint16_t length = kDaikinStateLength);
+ static bool validChecksum(uint8_t state[],
+ const uint16_t length = kDaikinStateLength);
+ static uint8_t convertMode(const stdAc::opmode_t mode);
+ static uint8_t convertFan(const stdAc::fanspeed_t speed);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // # of bytes per command
+ uint8_t remote[kDaikinStateLength];
+ void stateReset(void);
+ void checksum(void);
+};
+
+// Class to emulate a Daikin ARC477A1 remote.
+class IRDaikin2 {
+ public:
+ explicit IRDaikin2(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+#if SEND_DAIKIN2
+ void send(const uint16_t repeat = kDaikin2DefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif
+ void begin();
+ void on();
+ void off();
+ void setPower(const bool state);
+ bool getPower();
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp();
+ void setFan(const uint8_t fan);
+ uint8_t getFan();
+ uint8_t getMode();
+ void setMode(const uint8_t mode);
+ void setSwingVertical(const uint8_t position);
+ uint8_t getSwingVertical();
+ void setSwingHorizontal(const uint8_t position);
+ uint8_t getSwingHorizontal();
+ bool getQuiet();
+ void setQuiet(const bool on);
+ bool getPowerful();
+ void setPowerful(const bool on);
+ void setSensor(const bool on);
+ bool getSensor();
+ void setEcono(const bool on);
+ bool getEcono();
+ void setEye(const bool on);
+ bool getEye();
+ void setEyeAuto(const bool on);
+ bool getEyeAuto();
+ void setPurify(const bool on);
+ bool getPurify();
+ void setMold(const bool on);
+ bool getMold();
+ void enableOnTimer(const uint16_t starttime);
+ void disableOnTimer();
+ uint16_t getOnTime();
+ bool getOnTimerEnabled();
+ void enableSleepTimer(const uint16_t sleeptime);
+ void disableSleepTimer();
+ uint16_t getSleepTime();
+ bool getSleepTimerEnabled();
+ void enableOffTimer(const uint16_t endtime);
+ void disableOffTimer();
+ uint16_t getOffTime();
+ bool getOffTimerEnabled();
+ void setCurrentTime(const uint16_t time);
+ uint16_t getCurrentTime();
+ void setBeep(const uint8_t beep);
+ uint8_t getBeep();
+ void setLight(const uint8_t light);
+ uint8_t getLight();
+ void setClean(const bool on);
+ bool getClean();
+ void setFreshAir(const bool on);
+ bool getFreshAir();
+ void setFreshAirHigh(const bool on);
+ bool getFreshAirHigh();
+ uint8_t* getRaw();
+ void setRaw(const uint8_t new_code[]);
+ uint32_t getCommand();
+ void setCommand(uint32_t value);
+ static bool validChecksum(uint8_t state[],
+ const uint16_t length = kDaikin2StateLength);
+ static uint8_t convertMode(const stdAc::opmode_t mode);
+ static uint8_t convertFan(const stdAc::fanspeed_t speed);
+ uint8_t convertSwingV(const stdAc::swingv_t position);
+ static stdAc::swingv_t toCommonSwingV(const uint8_t setting);
+ static stdAc::swingh_t toCommonSwingH(const uint8_t setting);
+ stdAc::state_t toCommon(void);
+ String toString();
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // # of bytes per command
+ uint8_t remote_state[kDaikin2StateLength];
+ void stateReset();
+ void checksum();
+ void clearOnTimerFlag();
+ void clearSleepTimerFlag();
+};
+
+// Class to emulate a Daikin ARC433B69 remote.
+class IRDaikin216 {
+ public:
+ explicit IRDaikin216(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+#if SEND_DAIKIN216
+ void send(const uint16_t repeat = kDaikin216DefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif
+ void begin();
+ uint8_t* getRaw();
+ void setRaw(const uint8_t new_code[]);
+ static bool validChecksum(uint8_t state[],
+ const uint16_t length = kDaikin216StateLength);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp();
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ static uint8_t convertMode(const stdAc::opmode_t mode);
+ void setFan(const uint8_t fan);
+ uint8_t getFan(void);
+ static uint8_t convertFan(const stdAc::fanspeed_t speed);
+ void setSwingVertical(const bool on);
+ bool getSwingVertical(void);
+ void setSwingHorizontal(const bool on);
+ bool getSwingHorizontal(void);
+ void setQuiet(const bool on);
+ bool getQuiet(void);
+ void setPowerful(const bool on);
+ bool getPowerful(void);
+ stdAc::state_t toCommon(void);
+ String toString(void);
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // # of bytes per command
+ uint8_t remote_state[kDaikin216StateLength];
+ void stateReset();
+ void checksum();
+};
+
+// Class to emulate a Daikin ARC423A5 remote.
+class IRDaikin160 {
+ public:
+ explicit IRDaikin160(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+#if SEND_DAIKIN160
+ void send(const uint16_t repeat = kDaikin160DefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif
+ void begin();
+ uint8_t* getRaw();
+ void setRaw(const uint8_t new_code[]);
+ static bool validChecksum(uint8_t state[],
+ const uint16_t length = kDaikin160StateLength);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp();
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ static uint8_t convertMode(const stdAc::opmode_t mode);
+ void setFan(const uint8_t fan);
+ uint8_t getFan(void);
+ static uint8_t convertFan(const stdAc::fanspeed_t speed);
+ void setSwingVertical(const uint8_t position);
+ uint8_t getSwingVertical(void);
+ static uint8_t convertSwingV(const stdAc::swingv_t position);
+ static stdAc::swingv_t toCommonSwingV(const uint8_t setting);
+ stdAc::state_t toCommon(void);
+ String toString(void);
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // # of bytes per command
+ uint8_t remote_state[kDaikin160StateLength];
+ void stateReset();
+ void checksum();
+};
+
+// Class to emulate a Daikin BRC4C153 remote.
+class IRDaikin176 {
+ public:
+ explicit IRDaikin176(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+#if SEND_DAIKIN176
+ void send(const uint16_t repeat = kDaikin176DefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif
+ void begin();
+ uint8_t* getRaw();
+ void setRaw(const uint8_t new_code[]);
+ static bool validChecksum(uint8_t state[],
+ const uint16_t length = kDaikin176StateLength);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp();
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ static uint8_t convertMode(const stdAc::opmode_t mode);
+ void setFan(const uint8_t fan);
+ uint8_t getFan(void);
+ static uint8_t convertFan(const stdAc::fanspeed_t speed);
+ void setSwingHorizontal(const uint8_t position);
+ uint8_t getSwingHorizontal(void);
+ static uint8_t convertSwingH(const stdAc::swingh_t position);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::swingh_t toCommonSwingH(const uint8_t setting);
+ stdAc::state_t toCommon(void);
+ String toString(void);
+
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // # of bytes per command
+ uint8_t remote_state[kDaikin176StateLength];
+ uint8_t _saved_temp;
+ void stateReset();
+ void checksum();
+};
+
+// Class to emulate a Daikin BRC52B63 remote / Daikin 17 series A/C.
+class IRDaikin128 {
+ public:
+ explicit IRDaikin128(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+#if SEND_DAIKIN128
+ void send(const uint16_t repeat = kDaikin128DefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif // SEND_DAIKIN128
+ void begin();
+ void setPowerToggle(const bool toggle);
+ bool getPowerToggle(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp(void);
+ void setFan(const uint8_t fan);
+ uint8_t getFan(void);
+ uint8_t getMode(void);
+ void setMode(const uint8_t mode);
+ void setSwingVertical(const bool on);
+ bool getSwingVertical();
+ bool getSleep(void);
+ void setSleep(const bool on);
+ bool getQuiet(void);
+ void setQuiet(const bool on);
+ bool getPowerful(void);
+ void setPowerful(const bool on);
+ void setEcono(const bool on);
+ bool getEcono(void);
+ void setOnTimer(const uint16_t mins_since_midnight);
+ uint16_t getOnTimer(void);
+ bool getOnTimerEnabled(void);
+ void setOnTimerEnabled(const bool on);
+ void setOffTimer(const uint16_t mins_since_midnight);
+ uint16_t getOffTimer(void);
+ bool getOffTimerEnabled(void);
+ void setOffTimerEnabled(const bool on);
+ void setClock(const uint16_t mins_since_midnight);
+ uint16_t getClock(void);
+ void setLightToggle(const uint8_t unit_type);
+ uint8_t getLightToggle(void);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t new_code[]);
+ static bool validChecksum(uint8_t state[]);
+ static uint8_t convertMode(const stdAc::opmode_t mode);
+ static uint8_t convertFan(const stdAc::fanspeed_t speed);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(const stdAc::state_t *prev = NULL);
+ String toString(void);
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // # of bytes per command
+ uint8_t remote_state[kDaikin128StateLength];
+ void stateReset(void);
+ static uint8_t calcFirstChecksum(const uint8_t state[]);
+ static uint8_t calcSecondChecksum(const uint8_t state[]);
+ static void setTimer(uint8_t *ptr, const uint16_t mins_since_midnight);
+ static uint16_t getTimer(const uint8_t *ptr);
+ void checksum(void);
+ void clearOnTimerFlag(void);
+ void clearSleepTimerFlag(void);
+};
+
+// Class to emulate a Daikin ARC480A5 remote.
+class IRDaikin152 {
+ public:
+ explicit IRDaikin152(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+#if SEND_DAIKIN152
+ void send(const uint16_t repeat = kDaikin152DefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif
+ void begin();
+ uint8_t* getRaw();
+ void setRaw(const uint8_t new_code[]);
+ static bool validChecksum(uint8_t state[],
+ const uint16_t length = kDaikin152StateLength);
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // # of bytes per command
+ uint8_t remote_state[kDaikin152StateLength];
+ void stateReset();
+ void checksum();
+};
+#endif // IR_DAIKIN_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Denon.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Denon.cpp
similarity index 71%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Denon.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Denon.cpp
index 6798e022e..8a32ae261 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Denon.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Denon.cpp
@@ -6,12 +6,6 @@
#include "IRsend.h"
#include "IRutils.h"
-// DDDD EEEEE N N OOO N N
-// D D E NN N O O NN N
-// D D EEE N N N O O N N N
-// D D E N NN O O N NN
-// DDDD EEEEE N N OOO N N
-
// Original Denon support added by https://github.com/csBlueChip
// Ported over by Massimiliano Pinto
@@ -43,7 +37,7 @@ const uint64_t kDenonManufacturer = 0x2A4CULL;
//
// Args:
// data: Contents of the message to be sent.
-// nbits: Nr. of bits of data to be sent. Typically DENON_BITS.
+// nbits: Nr. of bits of data to be sent. Typically kDenonBits.
// repeat: Nr. of additional times the message is to be sent.
//
// Status: BETA / Should be working.
@@ -70,7 +64,7 @@ void IRsend::sendDenon(uint64_t data, uint16_t nbits, uint16_t repeat) {
//
// Args:
// results: Ptr to the data to decode and where to store the decode result.
-// nbits: Expected nr. of data bits. (Typically DENON_BITS)
+// nbits: Expected nr. of data bits. (Typically kDenonBits)
// Returns:
// boolean: True if it can decode it, false if it can't.
//
@@ -82,8 +76,8 @@ bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) {
// Compliance
if (strict) {
switch (nbits) {
- case DENON_BITS:
- case DENON_48_BITS:
+ case kDenonBits:
+ case kDenon48Bits:
case kDenonLegacyBits:
break;
default:
@@ -103,33 +97,18 @@ bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) {
// We couldn't decode it as expected, so try the old legacy method.
// NOTE: I don't think this following protocol actually exists.
// Looks like a partial version of the Sharp protocol.
- // Check we have enough data
- if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false;
if (strict && nbits != kDenonLegacyBits) return false;
uint64_t data = 0;
uint16_t offset = kStartOffset;
- // Header
- if (!matchMark(results->rawbuf[offset], kDenonHdrMark)) return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kDenonHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kDenonHdrSpace)) return false;
- uint32_t s_tick =
- results->rawbuf[offset++] * kRawTick / kDenonHdrSpaceTicks;
-
- // Data
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits,
- kDenonBitMarkTicks * m_tick, kDenonOneSpaceTicks * s_tick,
- kDenonBitMarkTicks * m_tick, kDenonZeroSpaceTicks * s_tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kDenonBitMarkTicks * m_tick))
- return false;
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kDenonHdrMark, kDenonHdrSpace,
+ kDenonBitMark, kDenonOneSpace,
+ kDenonBitMark, kDenonZeroSpace,
+ kDenonBitMark, 0, false)) return false;
// Success
results->bits = nbits;
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Dish.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Dish.cpp
similarity index 70%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Dish.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Dish.cpp
index 040aa3bf7..b217da763 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Dish.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Dish.cpp
@@ -5,15 +5,12 @@
#include "IRsend.h"
#include "IRutils.h"
-// DDDD IIIII SSSS H H
-// D D I S H H
-// D D I SSS HHHHH
-// D D I S H H
-// DDDD IIIII SSSS H H
-
// DISH support originally by Todd Treece
// http://unionbridge.org/design/ircommand
+// Supports:
+// Brand: DISH NETWORK, Model: echostar 301
+
// Constants
// Ref:
// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Dish.cpp
@@ -95,35 +92,17 @@ bool IRrecv::decodeDISH(decode_results *results, uint16_t nbits, bool strict) {
uint64_t data = 0;
uint16_t offset = kStartOffset;
- // Header
- if (!match(results->rawbuf[offset], kDishHdrMark)) return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kDishHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kDishHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kDishHdrSpaceTicks;
-
- // Data
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits, kDishBitMarkTicks * m_tick,
- kDishOneSpaceTicks * s_tick, kDishBitMarkTicks * m_tick,
- kDishZeroSpaceTicks * s_tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kDishBitMarkTicks * m_tick))
- return false;
-
- // Compliance
- if (strict) {
- // The DISH protocol calls for a repeated message, so strictly speaking
- // there should be a code following this. Only require it if we are set to
- // strict matching.
- if (!matchSpace(results->rawbuf[offset], kDishRptSpaceTicks * s_tick))
- return false;
- }
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kDishHdrMark, kDishHdrSpace,
+ kDishBitMark, kDishOneSpace,
+ kDishBitMark, kDishZeroSpace,
+ kDishBitMark,
+ // The DISH protocol calls for a repeated message, so
+ // strictly speaking there should be a code following this.
+ // Only require it if we are set to strict matching.
+ strict ? kDishRptSpace : 0, false)) return false;
// Success
results->decode_type = DISH;
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Electra.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Electra.cpp
new file mode 100644
index 000000000..6b945aa3f
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Electra.cpp
@@ -0,0 +1,336 @@
+// Copyright 2018, 2019 David Conran
+
+#include "ir_Electra.h"
+#include
+#include "IRrecv.h"
+#include "IRsend.h"
+#include "IRutils.h"
+
+// Electra A/C added by crankyoldgit
+//
+
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/527
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/642
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/778
+// https://github.com/ToniA/arduino-heatpumpir/blob/master/AUXHeatpumpIR.cpp
+
+// Constants
+const uint16_t kElectraAcHdrMark = 9166;
+const uint16_t kElectraAcBitMark = 646;
+const uint16_t kElectraAcHdrSpace = 4470;
+const uint16_t kElectraAcOneSpace = 1647;
+const uint16_t kElectraAcZeroSpace = 547;
+const uint32_t kElectraAcMessageGap = kDefaultMessageGap; // Just a guess.
+
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addFanToString;
+using irutils::addTempToString;
+
+#if SEND_ELECTRA_AC
+// Send a Electra message
+//
+// Args:
+// data: Contents of the message to be sent. (Guessing MSBF order)
+// nbits: Nr. of bits of data to be sent. Typically kElectraAcBits.
+// repeat: Nr. of additional times the message is to be sent.
+//
+// Status: Alpha / Needs testing against a real device.
+//
+void IRsend::sendElectraAC(const uint8_t data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ for (uint16_t r = 0; r <= repeat; r++)
+ sendGeneric(kElectraAcHdrMark, kElectraAcHdrSpace, kElectraAcBitMark,
+ kElectraAcOneSpace, kElectraAcBitMark, kElectraAcZeroSpace,
+ kElectraAcBitMark, kElectraAcMessageGap, data, nbytes,
+ 38000, // Complete guess of the modulation frequency.
+ false, // Send data in LSB order per byte
+ 0, 50);
+}
+#endif
+
+
+IRElectraAc::IRElectraAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) {
+ this->stateReset();
+}
+
+void IRElectraAc::stateReset(void) {
+ for (uint8_t i = 1; i < kElectraAcStateLength - 2; i++)
+ remote_state[i] = 0;
+ remote_state[0] = 0xC3;
+ remote_state[11] = 0x08;
+ // [12] is the checksum.
+}
+
+void IRElectraAc::begin(void) { _irsend.begin(); }
+
+uint8_t IRElectraAc::calcChecksum(const uint8_t state[],
+ const uint16_t length) {
+ if (length == 0) return state[0];
+ return sumBytes(state, length - 1);
+}
+
+bool IRElectraAc::validChecksum(const uint8_t state[], const uint16_t length) {
+ if (length < 2)
+ return true; // No checksum to compare with. Assume okay.
+ return (state[length - 1] == calcChecksum(state, length));
+}
+
+// Update the checksum for the internal state.
+void IRElectraAc::checksum(uint16_t length) {
+ if (length < 2) return;
+ remote_state[length - 1] = calcChecksum(remote_state, length);
+}
+
+#if SEND_ELECTRA_AC
+void IRElectraAc::send(const uint16_t repeat) {
+ this->checksum();
+ _irsend.sendElectraAC(remote_state, kElectraAcStateLength, repeat);
+}
+#endif // SEND_ELECTRA_AC
+
+uint8_t *IRElectraAc::getRaw(void) {
+ this->checksum();
+ return remote_state;
+}
+
+void IRElectraAc::setRaw(const uint8_t new_code[], const uint16_t length) {
+ for (uint8_t i = 0; i < length && i < kElectraAcStateLength; i++)
+ remote_state[i] = new_code[i];
+}
+
+void IRElectraAc::on(void) { this->setPower(true); }
+
+void IRElectraAc::off(void) { this->setPower(false); }
+
+void IRElectraAc::setPower(const bool on) {
+ if (on)
+ remote_state[9] |= kElectraAcPowerMask;
+ else
+ remote_state[9] &= ~kElectraAcPowerMask;
+}
+
+bool IRElectraAc::getPower(void) {
+ return remote_state[9] & kElectraAcPowerMask;
+}
+
+void IRElectraAc::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kElectraAcAuto:
+ case kElectraAcDry:
+ case kElectraAcCool:
+ case kElectraAcHeat:
+ case kElectraAcFan:
+ remote_state[6] &= ~kElectraAcModeMask;
+ remote_state[6] |= (mode << 5);
+ break;
+ default:
+ // If we get an unexpected mode, default to AUTO.
+ this->setMode(kElectraAcAuto);
+ }
+}
+
+uint8_t IRElectraAc::getMode(void) {
+ return (remote_state[6] & kElectraAcModeMask) >> 5;
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRElectraAc::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kElectraAcCool;
+ case stdAc::opmode_t::kHeat:
+ return kElectraAcHeat;
+ case stdAc::opmode_t::kDry:
+ return kElectraAcDry;
+ case stdAc::opmode_t::kFan:
+ return kElectraAcFan;
+ default:
+ return kElectraAcAuto;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRElectraAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kElectraAcCool: return stdAc::opmode_t::kCool;
+ case kElectraAcHeat: return stdAc::opmode_t::kHeat;
+ case kElectraAcDry: return stdAc::opmode_t::kDry;
+ case kElectraAcFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Set the temp. in deg C
+void IRElectraAc::setTemp(const uint8_t temp) {
+ uint8_t newtemp = std::max(kElectraAcMinTemp, temp);
+ newtemp = std::min(kElectraAcMaxTemp, newtemp);
+ remote_state[1] = (remote_state[1] & ~kElectraAcTempMask) |
+ ((newtemp - kElectraAcOffsetTemp) << 3);
+}
+
+// Return the set temp. in deg C
+uint8_t IRElectraAc::getTemp(void) {
+ return ((remote_state[1] & kElectraAcTempMask) >> 3) + kElectraAcOffsetTemp;
+}
+
+// Set the speed of the fan, 0-3, 0 is auto, 1-3 is the speed
+void IRElectraAc::setFan(const uint8_t speed) {
+ switch (speed) {
+ case kElectraAcFanAuto:
+ case kElectraAcFanHigh:
+ case kElectraAcFanMed:
+ case kElectraAcFanLow:
+ remote_state[4] &= ~kElectraAcFanMask;
+ remote_state[4] |= (speed << 5);
+ break;
+ default:
+ // If we get an unexpected speed, default to Auto.
+ this->setFan(kElectraAcFanAuto);
+ }
+}
+
+uint8_t IRElectraAc::getFan(void) {
+ return (remote_state[4] & kElectraAcFanMask) >> 5;
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRElectraAc::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ case stdAc::fanspeed_t::kLow:
+ return kElectraAcFanLow;
+ case stdAc::fanspeed_t::kMedium:
+ return kElectraAcFanMed;
+ case stdAc::fanspeed_t::kHigh:
+ case stdAc::fanspeed_t::kMax:
+ return kElectraAcFanHigh;
+ default:
+ return kElectraAcFanAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRElectraAc::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kElectraAcFanHigh: return stdAc::fanspeed_t::kMax;
+ case kElectraAcFanMed: return stdAc::fanspeed_t::kMedium;
+ case kElectraAcFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+void IRElectraAc::setSwingV(const bool on) {
+ if (on)
+ remote_state[1] &= ~kElectraAcSwingVMask;
+ else
+ remote_state[1] |= kElectraAcSwingVMask;
+}
+
+bool IRElectraAc::getSwingV(void) {
+ return !(remote_state[1] & kElectraAcSwingVMask);
+}
+
+void IRElectraAc::setSwingH(const bool on) {
+ if (on)
+ remote_state[2] &= ~kElectraAcSwingHMask;
+ else
+ remote_state[2] |= kElectraAcSwingHMask;
+}
+
+bool IRElectraAc::getSwingH(void) {
+ return !(remote_state[2] & kElectraAcSwingHMask);
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRElectraAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::ELECTRA_AC;
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwingV() ? stdAc::swingv_t::kAuto
+ : stdAc::swingv_t::kOff;
+ result.swingh = this->getSwingH() ? stdAc::swingh_t::kAuto
+ : stdAc::swingh_t::kOff;
+ // Not supported.
+ result.model = -1; // No models used.
+ result.quiet = false;
+ result.turbo = false;
+ result.econo = false;
+ result.clean = false;
+ result.light = false;
+ result.filter = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRElectraAc::toString(void) {
+ String result = "";
+ result.reserve(80); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kElectraAcAuto, kElectraAcCool,
+ kElectraAcHeat, kElectraAcDry, kElectraAcFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kElectraAcFanHigh, kElectraAcFanLow,
+ kElectraAcFanAuto, kElectraAcFanAuto,
+ kElectraAcFanMed);
+ result += addBoolToString(getSwingV(), F("Swing(V)"));
+ result += addBoolToString(getSwingH(), F("Swing(H)"));
+ return result;
+}
+
+#if DECODE_ELECTRA_AC
+// Decode the supplied Electra A/C message.
+//
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: The number of data bits to expect. Typically kElectraAcBits.
+// strict: Flag indicating if we should perform strict matching.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: STABLE / Known working.
+//
+bool IRrecv::decodeElectraAC(decode_results *results, uint16_t nbits,
+ bool strict) {
+ if (strict) {
+ if (nbits != kElectraAcBits)
+ return false; // Not strictly a ELECTRA_AC message.
+ }
+
+ uint16_t offset = kStartOffset;
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kElectraAcHdrMark, kElectraAcHdrSpace,
+ kElectraAcBitMark, kElectraAcOneSpace,
+ kElectraAcBitMark, kElectraAcZeroSpace,
+ kElectraAcBitMark, kElectraAcMessageGap, true,
+ _tolerance, 0, false)) return false;
+
+ // Compliance
+ if (strict) {
+ // Verify the checksum.
+ if (!IRElectraAc::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->decode_type = decode_type_t::ELECTRA_AC;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_ELECTRA_AC
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Electra.h b/lib/IRremoteESP8266-2.6.5/src/ir_Electra.h
new file mode 100644
index 000000000..c9c6f018e
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Electra.h
@@ -0,0 +1,102 @@
+// Electra A/C
+//
+// Copyright 2019 David Conran
+
+#ifndef IR_ELECTRA_H_
+#define IR_ELECTRA_H_
+
+#define __STDC_LIMIT_MACROS
+#include
+#ifndef UNIT_TEST
+#include
+#endif
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#ifdef UNIT_TEST
+#include "IRsend_test.h"
+#endif
+
+// Supports:
+// Brand: AUX, Model: KFR-35GW/BpNFW=3 A/C
+// Brand: AUX, Model: YKR-T/011 remote
+
+// Ref:
+// https://github.com/ToniA/arduino-heatpumpir/blob/master/AUXHeatpumpIR.cpp
+
+// Constants
+// state[1]
+const uint8_t kElectraAcTempMask = 0b11111000;
+const uint8_t kElectraAcMinTemp = 16; // 16C
+const uint8_t kElectraAcMaxTemp = 32; // 32C
+const uint8_t kElectraAcOffsetTemp = 8;
+const uint8_t kElectraAcSwingVMask = 0b00000111;
+// state[2]
+const uint8_t kElectraAcSwingHMask = 0b11100000;
+// state[4]
+const uint8_t kElectraAcFanMask = 0b11100000;
+const uint8_t kElectraAcFanAuto = 0b101;
+const uint8_t kElectraAcFanLow = 0b011;
+const uint8_t kElectraAcFanMed = 0b010;
+const uint8_t kElectraAcFanHigh = 0b001;
+// state[6]
+const uint8_t kElectraAcModeMask = 0b11100000;
+const uint8_t kElectraAcAuto = 0b000;
+const uint8_t kElectraAcCool = 0b001;
+const uint8_t kElectraAcDry = 0b010;
+const uint8_t kElectraAcHeat = 0b100;
+const uint8_t kElectraAcFan = 0b110;
+// state[9]
+const uint8_t kElectraAcPowerMask = 0b00100000;
+
+
+// Classes
+class IRElectraAc {
+ public:
+ explicit IRElectraAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+ void stateReset(void);
+#if SEND_ELECTRA_AC
+ void send(const uint16_t repeat = kElectraAcMinRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif // SEND_ELECTRA_AC
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp(void);
+ void setFan(const uint8_t speed);
+ uint8_t getFan(void);
+ void setSwingV(const bool on);
+ bool getSwingV(void);
+ void setSwingH(const bool on);
+ bool getSwingH(void);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t new_code[],
+ const uint16_t length = kElectraAcStateLength);
+ static bool validChecksum(const uint8_t state[],
+ const uint16_t length = kElectraAcStateLength);
+ static uint8_t calcChecksum(const uint8_t state[],
+ const uint16_t length = kElectraAcStateLength);
+ String toString(void);
+ uint8_t convertMode(const stdAc::opmode_t mode);
+ uint8_t convertFan(const stdAc::fanspeed_t speed);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // The state of the IR remote in IR code form.
+ uint8_t remote_state[kElectraAcStateLength];
+ void checksum(const uint16_t length = kElectraAcStateLength);
+};
+#endif // IR_ELECTRA_H_
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.cpp
new file mode 100644
index 000000000..fa6a0ce8c
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.cpp
@@ -0,0 +1,730 @@
+// Copyright 2017 Jonny Graham
+// Copyright 2017-2019 David Conran
+#include "ir_Fujitsu.h"
+#include
+#ifndef ARDUINO
+#include
+#endif
+#include "IRsend.h"
+#include "IRutils.h"
+
+// Fujitsu A/C support added by Jonny Graham & David Conran
+
+// Equipment it seems compatible with:
+// * Fujitsu ASYG30LFCA with remote AR-RAH2E
+// * Fujitsu AST9RSGCW with remote AR-DB1
+// * Fujitsu ASYG7LMCA with remote AR-REB1E
+// * Fujitsu AR-RAE1E remote.
+// * Fujitsu General with remote AR-JW2
+// *
+
+// Ref:
+// These values are based on averages of measurements
+const uint16_t kFujitsuAcHdrMark = 3324;
+const uint16_t kFujitsuAcHdrSpace = 1574;
+const uint16_t kFujitsuAcBitMark = 448;
+const uint16_t kFujitsuAcOneSpace = 1182;
+const uint16_t kFujitsuAcZeroSpace = 390;
+const uint16_t kFujitsuAcMinGap = 8100;
+
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addFanToString;
+using irutils::addTempToString;
+
+#if SEND_FUJITSU_AC
+// Send a Fujitsu A/C message.
+//
+// Args:
+// data: An array of bytes containing the IR command.
+// nbytes: Nr. of bytes of data in the array. Typically one of:
+// kFujitsuAcStateLength
+// kFujitsuAcStateLength - 1
+// kFujitsuAcStateLengthShort
+// kFujitsuAcStateLengthShort - 1
+// repeat: Nr. of times the message is to be repeated.
+// (Default = kFujitsuAcMinRepeat).
+//
+// Status: STABLE / Known Good.
+//
+void IRsend::sendFujitsuAC(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ sendGeneric(kFujitsuAcHdrMark, kFujitsuAcHdrSpace, kFujitsuAcBitMark,
+ kFujitsuAcOneSpace, kFujitsuAcBitMark, kFujitsuAcZeroSpace,
+ kFujitsuAcBitMark, kFujitsuAcMinGap, data, nbytes, 38, false,
+ repeat, 50);
+}
+#endif // SEND_FUJITSU_AC
+
+// Code to emulate Fujitsu A/C IR remote control unit.
+
+// Initialise the object.
+IRFujitsuAC::IRFujitsuAC(const uint16_t pin,
+ const fujitsu_ac_remote_model_t model,
+ const bool inverted, const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) {
+ this->setModel(model);
+ this->stateReset();
+}
+
+void IRFujitsuAC::setModel(const fujitsu_ac_remote_model_t model) {
+ _model = model;
+ switch (model) {
+ case ARDB1:
+ case ARJW2:
+ _state_length = kFujitsuAcStateLength - 1;
+ _state_length_short = kFujitsuAcStateLengthShort - 1;
+ break;
+ case ARRAH2E:
+ case ARREB1E:
+ default:
+ _state_length = kFujitsuAcStateLength;
+ _state_length_short = kFujitsuAcStateLengthShort;
+ }
+}
+
+fujitsu_ac_remote_model_t IRFujitsuAC::getModel(void) { return _model; }
+
+// Reset the state of the remote to a known good state/sequence.
+void IRFujitsuAC::stateReset(void) {
+ _temp = 24;
+ _fanSpeed = kFujitsuAcFanHigh;
+ _mode = kFujitsuAcModeCool;
+ _swingMode = kFujitsuAcSwingBoth;
+ _cmd = kFujitsuAcCmdTurnOn;
+ this->buildState();
+}
+
+// Configure the pin for output.
+void IRFujitsuAC::begin(void) { _irsend.begin(); }
+
+#if SEND_FUJITSU_AC
+// Send the current desired state to the IR LED.
+void IRFujitsuAC::send(const uint16_t repeat) {
+ this->buildState();
+ _irsend.sendFujitsuAC(remote_state, getStateLength(), repeat);
+}
+#endif // SEND_FUJITSU_AC
+
+void IRFujitsuAC::buildState(void) {
+ remote_state[0] = 0x14;
+ remote_state[1] = 0x63;
+ remote_state[2] = 0x00;
+ remote_state[3] = 0x10;
+ remote_state[4] = 0x10;
+ bool fullCmd = false;
+ switch (_cmd) {
+ case kFujitsuAcCmdTurnOff: // 0x02
+ case kFujitsuAcCmdEcono: // 0x09
+ case kFujitsuAcCmdPowerful: // 0x39
+ case kFujitsuAcCmdStepVert: // 0x6C
+ case kFujitsuAcCmdToggleSwingVert: // 0x6D
+ case kFujitsuAcCmdStepHoriz: // 0x79
+ case kFujitsuAcCmdToggleSwingHoriz: // 0x7A
+ remote_state[5] = _cmd;
+ break;
+ default:
+ switch (_model) {
+ case ARRAH2E:
+ case ARREB1E:
+ remote_state[5] = 0xFE;
+ break;
+ case ARDB1:
+ case ARJW2:
+ remote_state[5] = 0xFC;
+ break;
+ }
+ fullCmd = true;
+ break;
+ }
+ if (fullCmd) { // long codes
+ uint8_t tempByte = _temp - kFujitsuAcMinTemp;
+ // Nr. of bytes in the message after this byte.
+ remote_state[6] = _state_length - 7;
+
+ remote_state[7] = 0x30;
+ remote_state[8] = (_cmd == kFujitsuAcCmdTurnOn) | (tempByte << 4);
+ remote_state[9] = _mode | 0 << 4; // timer off
+ remote_state[10] = _fanSpeed;
+ remote_state[11] = 0; // timerOff values
+ remote_state[12] = 0; // timerOff/On values
+ remote_state[13] = 0; // timerOn values
+ remote_state[14] = 0;
+ uint8_t checksum = 0;
+ uint8_t checksum_complement = 0;
+ switch (_model) {
+ case ARDB1:
+ case ARJW2:
+ checksum = sumBytes(remote_state, _state_length - 1);
+ checksum_complement = 0x9B;
+ break;
+ case ARREB1E:
+ remote_state[14] |= (_outsideQuiet << 7);
+ // FALL THRU
+ case ARRAH2E:
+ remote_state[14] |= 0x20;
+ remote_state[10] |= _swingMode << 4;
+ // FALL THRU
+ default:
+ checksum = sumBytes(remote_state + _state_length_short,
+ _state_length - _state_length_short - 1);
+ }
+ // and negate the checksum and store it in the last byte.
+ remote_state[_state_length - 1] = checksum_complement - checksum;
+ } else { // short codes
+ switch (_model) {
+ case ARRAH2E:
+ case ARREB1E:
+ // The last byte is the inverse of penultimate byte
+ remote_state[_state_length_short - 1] =
+ ~remote_state[_state_length_short - 2];
+ break;
+ default:
+ {}; // We don't need to do anything for the others.
+ }
+ // Zero the rest of the state.
+ for (uint8_t i = _state_length_short; i < kFujitsuAcStateLength; i++)
+ remote_state[i] = 0;
+ }
+}
+
+uint8_t IRFujitsuAC::getStateLength(void) {
+ this->buildState(); // Force an update of the internal state.
+ if (((_model == ARRAH2E || _model == ARREB1E) && remote_state[5] != 0xFE) ||
+ ((_model == ARDB1 || _model == ARJW2) && remote_state[5] != 0xFC))
+ return _state_length_short;
+ else
+ return _state_length;
+}
+
+// Return a pointer to the internal state date of the remote.
+uint8_t* IRFujitsuAC::getRaw(void) {
+ this->buildState();
+ return remote_state;
+}
+
+void IRFujitsuAC::buildFromState(const uint16_t length) {
+ switch (length) {
+ case kFujitsuAcStateLength - 1:
+ case kFujitsuAcStateLengthShort - 1:
+ this->setModel(ARDB1);
+ // ARJW2 has horizontal swing.
+ if (this->getSwing(true) > kFujitsuAcSwingVert) this->setModel(ARJW2);
+ break;
+ default:
+ switch (this->getCmd(true)) {
+ case kFujitsuAcCmdEcono:
+ case kFujitsuAcCmdPowerful:
+ this->setModel(fujitsu_ac_remote_model_t::ARREB1E);
+ break;
+ default:
+ this->setModel(fujitsu_ac_remote_model_t::ARRAH2E);
+ }
+ }
+ switch (remote_state[6]) {
+ case 8:
+ if (this->getModel() != fujitsu_ac_remote_model_t::ARJW2)
+ this->setModel(ARDB1);
+ break;
+ case 9:
+ if (this->getModel() != fujitsu_ac_remote_model_t::ARREB1E)
+ this->setModel(ARRAH2E);
+ break;
+ }
+ setTemp((remote_state[8] >> 4) + kFujitsuAcMinTemp);
+ if (remote_state[8] & 0x1)
+ setCmd(kFujitsuAcCmdTurnOn);
+ else
+ setCmd(kFujitsuAcCmdStayOn);
+ setMode(remote_state[9] & 0b111);
+ setFanSpeed(remote_state[10] & 0b111);
+ setSwing(remote_state[10] >> 4);
+ switch (remote_state[5]) {
+ case kFujitsuAcCmdTurnOff:
+ case kFujitsuAcCmdStepHoriz:
+ case kFujitsuAcCmdToggleSwingHoriz:
+ case kFujitsuAcCmdStepVert:
+ case kFujitsuAcCmdToggleSwingVert:
+ case kFujitsuAcCmdEcono:
+ case kFujitsuAcCmdPowerful:
+ setCmd(remote_state[5]);
+ break;
+ }
+ _outsideQuiet = this->getOutsideQuiet(true);
+}
+
+bool IRFujitsuAC::setRaw(const uint8_t newState[], const uint16_t length) {
+ if (length > kFujitsuAcStateLength) return false;
+ for (uint16_t i = 0; i < kFujitsuAcStateLength; i++) {
+ if (i < length)
+ remote_state[i] = newState[i];
+ else
+ remote_state[i] = 0;
+ }
+ buildFromState(length);
+ return true;
+}
+
+void IRFujitsuAC::stepHoriz(void) { this->setCmd(kFujitsuAcCmdStepHoriz); }
+
+void IRFujitsuAC::toggleSwingHoriz(const bool update) {
+ // Toggle the current setting.
+ if (update) this->setSwing(this->getSwing() ^ kFujitsuAcSwingHoriz);
+ // and set the appropriate special command.
+ this->setCmd(kFujitsuAcCmdToggleSwingHoriz);
+}
+
+void IRFujitsuAC::stepVert(void) { this->setCmd(kFujitsuAcCmdStepVert); }
+
+void IRFujitsuAC::toggleSwingVert(const bool update) {
+ // Toggle the current setting.
+ if (update) this->setSwing(this->getSwing() ^ kFujitsuAcSwingVert);
+ // and set the appropriate special command.
+ this->setCmd(kFujitsuAcCmdToggleSwingVert);
+}
+
+// Set the requested command of the A/C.
+void IRFujitsuAC::setCmd(const uint8_t cmd) {
+ switch (cmd) {
+ case kFujitsuAcCmdTurnOff:
+ case kFujitsuAcCmdTurnOn:
+ case kFujitsuAcCmdStayOn:
+ case kFujitsuAcCmdStepVert:
+ case kFujitsuAcCmdToggleSwingVert:
+ _cmd = cmd;
+ break;
+ case kFujitsuAcCmdStepHoriz:
+ case kFujitsuAcCmdToggleSwingHoriz:
+ switch (_model) {
+ // Only these remotes have step horizontal.
+ case ARRAH2E:
+ case ARJW2:
+ _cmd = cmd;
+ break;
+ default:
+ _cmd = kFujitsuAcCmdStayOn;
+ }
+ break;
+ case kFujitsuAcCmdEcono:
+ case kFujitsuAcCmdPowerful:
+ switch (_model) {
+ // Only these remotes have these commands.
+ case ARREB1E:
+ _cmd = cmd;
+ break;
+ default:
+ _cmd = kFujitsuAcCmdStayOn;
+ }
+ break;
+ default:
+ _cmd = kFujitsuAcCmdStayOn;
+ }
+}
+
+// Get the special command part of the message.
+// Args:
+// raw: Do we need to get it from first principles from the raw data?
+// Returns:
+// A uint8_t containing the contents of the special command byte.
+uint8_t IRFujitsuAC::getCmd(const bool raw) {
+ if (raw) return remote_state[5];
+ return _cmd;
+}
+
+// Set the requested power state of the A/C.
+void IRFujitsuAC::setPower(const bool on) {
+ this->setCmd(on ? kFujitsuAcCmdTurnOn : kFujitsuAcCmdTurnOff);
+}
+
+// Set the requested power state of the A/C to off.
+void IRFujitsuAC::off(void) { this->setPower(false); }
+
+// Set the requested power state of the A/C to on.
+void IRFujitsuAC::on(void) { this->setPower(true); }
+
+bool IRFujitsuAC::getPower(void) { return _cmd != kFujitsuAcCmdTurnOff; }
+
+void IRFujitsuAC::setOutsideQuiet(const bool on) {
+ _outsideQuiet = on;
+ this->setCmd(kFujitsuAcCmdStayOn); // No special command involved.
+}
+
+// Get the status of the Outside Quiet setting.
+// Args:
+// raw: Do we get the result from base data?
+// Returns:
+// A boolean for if it is set or not.
+bool IRFujitsuAC::getOutsideQuiet(const bool raw) {
+ if (_state_length == kFujitsuAcStateLength && raw) {
+ _outsideQuiet = remote_state[14] & 0b10000000;
+ // Only ARREB1E seems to have this mode.
+ if (_outsideQuiet) this->setModel(fujitsu_ac_remote_model_t::ARREB1E);
+ }
+ return _outsideQuiet;
+}
+
+// Set the temp. in deg C
+void IRFujitsuAC::setTemp(const uint8_t temp) {
+ _temp = std::max((uint8_t)kFujitsuAcMinTemp, temp);
+ _temp = std::min((uint8_t)kFujitsuAcMaxTemp, _temp);
+ this->setCmd(kFujitsuAcCmdStayOn); // No special command involved.
+}
+
+uint8_t IRFujitsuAC::getTemp(void) { return _temp; }
+
+// Set the speed of the fan
+void IRFujitsuAC::setFanSpeed(const uint8_t fanSpeed) {
+ if (fanSpeed > kFujitsuAcFanQuiet)
+ _fanSpeed = kFujitsuAcFanHigh; // Set the fan to maximum if out of range.
+ else
+ _fanSpeed = fanSpeed;
+ this->setCmd(kFujitsuAcCmdStayOn); // No special command involved.
+}
+uint8_t IRFujitsuAC::getFanSpeed(void) { return _fanSpeed; }
+
+// Set the requested climate operation mode of the a/c unit.
+void IRFujitsuAC::setMode(const uint8_t mode) {
+ if (mode > kFujitsuAcModeHeat)
+ _mode = kFujitsuAcModeHeat; // Set the mode to maximum if out of range.
+ else
+ _mode = mode;
+ this->setCmd(kFujitsuAcCmdStayOn); // No special command involved.
+}
+
+uint8_t IRFujitsuAC::getMode(void) { return _mode; }
+
+// Set the requested swing operation mode of the a/c unit.
+void IRFujitsuAC::setSwing(const uint8_t swingMode) {
+ _swingMode = swingMode;
+ switch (_model) {
+ // No Horizontal support.
+ case ARDB1:
+ case ARREB1E:
+ // Set the mode to max if out of range
+ if (swingMode > kFujitsuAcSwingVert) _swingMode = kFujitsuAcSwingVert;
+ break;
+ // Has Horizontal support.
+ case ARRAH2E:
+ case ARJW2:
+ default:
+ // Set the mode to max if out of range
+ if (swingMode > kFujitsuAcSwingBoth) _swingMode = kFujitsuAcSwingBoth;
+ }
+ this->setCmd(kFujitsuAcCmdStayOn); // No special command involved.
+}
+
+// Get what the swing part of the message should be.
+// Args:
+// raw: Do we need to get it from first principles from the raw data?
+// Returns:
+// A uint8_t containing the contents of the swing state.
+uint8_t IRFujitsuAC::getSwing(const bool raw) {
+ if (raw) _swingMode = remote_state[10] >> 4;
+ return _swingMode;
+}
+
+bool IRFujitsuAC::validChecksum(uint8_t state[], const uint16_t length) {
+ uint8_t sum = 0;
+ uint8_t sum_complement = 0;
+ uint8_t checksum = state[length - 1];
+ switch (length) {
+ case kFujitsuAcStateLengthShort: // ARRAH2E & ARREB1E
+ return state[length - 1] == (uint8_t)~state[length - 2];
+ case kFujitsuAcStateLength - 1: // ARDB1 & ARJW2
+ sum = sumBytes(state, length - 1);
+ sum_complement = 0x9B;
+ break;
+ case kFujitsuAcStateLength: // ARRAH2E & ARREB1E
+ sum = sumBytes(state + kFujitsuAcStateLengthShort,
+ length - 1 - kFujitsuAcStateLengthShort);
+ break;
+ default: // Includes ARDB1 & ARJW2 short.
+ return true; // Assume the checksum is valid for other lengths.
+ }
+ return checksum == (uint8_t)(sum_complement - sum); // Does it match?
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRFujitsuAC::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kFujitsuAcModeCool;
+ case stdAc::opmode_t::kHeat:
+ return kFujitsuAcModeHeat;
+ case stdAc::opmode_t::kDry:
+ return kFujitsuAcModeDry;
+ case stdAc::opmode_t::kFan:
+ return kFujitsuAcModeFan;
+ default:
+ return kFujitsuAcModeAuto;
+ }
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRFujitsuAC::convertFan(stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ return kFujitsuAcFanQuiet;
+ case stdAc::fanspeed_t::kLow:
+ return kFujitsuAcFanLow;
+ case stdAc::fanspeed_t::kMedium:
+ return kFujitsuAcFanMed;
+ case stdAc::fanspeed_t::kHigh:
+ case stdAc::fanspeed_t::kMax:
+ return kFujitsuAcFanHigh;
+ default:
+ return kFujitsuAcFanAuto;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRFujitsuAC::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kFujitsuAcModeCool: return stdAc::opmode_t::kCool;
+ case kFujitsuAcModeHeat: return stdAc::opmode_t::kHeat;
+ case kFujitsuAcModeDry: return stdAc::opmode_t::kDry;
+ case kFujitsuAcModeFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRFujitsuAC::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kFujitsuAcFanHigh: return stdAc::fanspeed_t::kMax;
+ case kFujitsuAcFanMed: return stdAc::fanspeed_t::kMedium;
+ case kFujitsuAcFanLow: return stdAc::fanspeed_t::kLow;
+ case kFujitsuAcFanQuiet: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRFujitsuAC::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::FUJITSU_AC;
+ result.model = this->getModel();
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFanSpeed());
+ uint8_t swing = this->getSwing();
+ switch (result.model) {
+ case fujitsu_ac_remote_model_t::ARREB1E:
+ case fujitsu_ac_remote_model_t::ARRAH2E:
+ result.swingv = (swing & kFujitsuAcSwingVert) ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.swingh = (swing & kFujitsuAcSwingHoriz) ? stdAc::swingh_t::kAuto :
+ stdAc::swingh_t::kOff;
+ break;
+ case fujitsu_ac_remote_model_t::ARDB1:
+ case fujitsu_ac_remote_model_t::ARJW2:
+ default:
+ result.swingv = stdAc::swingv_t::kOff;
+ result.swingh = stdAc::swingh_t::kOff;
+ }
+
+ result.quiet = (this->getFanSpeed() == kFujitsuAcFanQuiet);
+ result.turbo = this->getCmd() == kFujitsuAcCmdPowerful;
+ result.econo = this->getCmd() == kFujitsuAcCmdEcono;
+ // Not supported.
+ result.light = false;
+ result.filter = false;
+ result.clean = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRFujitsuAC::toString(void) {
+ String result = "";
+ result.reserve(100); // Reserve some heap for the string to reduce fragging.
+ fujitsu_ac_remote_model_t model = this->getModel();
+ result += addIntToString(model, F("Model"), false);
+ switch (model) {
+ case fujitsu_ac_remote_model_t::ARRAH2E: result += F(" (ARRAH2E)"); break;
+ case fujitsu_ac_remote_model_t::ARDB1: result += F(" (ARDB1)"); break;
+ case fujitsu_ac_remote_model_t::ARREB1E: result += F(" (ARREB1E)"); break;
+ case fujitsu_ac_remote_model_t::ARJW2: result += F(" (ARJW2)"); break;
+ default: result += F(" (UNKNOWN)");
+ }
+ result += addBoolToString(getPower(), F("Power"));
+ result += addModeToString(getMode(), kFujitsuAcModeAuto, kFujitsuAcModeCool,
+ kFujitsuAcModeHeat, kFujitsuAcModeDry,
+ kFujitsuAcModeFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFanSpeed(), kFujitsuAcFanHigh, kFujitsuAcFanLow,
+ kFujitsuAcFanAuto, kFujitsuAcFanQuiet,
+ kFujitsuAcFanMed);
+ switch (model) {
+ // These models have no internal swing state.
+ case fujitsu_ac_remote_model_t::ARDB1:
+ case fujitsu_ac_remote_model_t::ARJW2:
+ break;
+ default: // Assume everything else does.
+ result += F(", Swing: ");
+ switch (this->getSwing()) {
+ case kFujitsuAcSwingOff:
+ result += F("Off");
+ break;
+ case kFujitsuAcSwingVert:
+ result += F("Vert");
+ break;
+ case kFujitsuAcSwingHoriz:
+ result += F("Horiz");
+ break;
+ case kFujitsuAcSwingBoth:
+ result += F("Vert + Horiz");
+ break;
+ default:
+ result += F("UNKNOWN");
+ }
+ }
+ result += F(", Command: ");
+ switch (this->getCmd()) {
+ case kFujitsuAcCmdStepHoriz:
+ result += F("Step vane horizontally");
+ break;
+ case kFujitsuAcCmdStepVert:
+ result += F("Step vane vertically");
+ break;
+ case kFujitsuAcCmdToggleSwingHoriz:
+ result += F("Toggle horizontal swing");
+ break;
+ case kFujitsuAcCmdToggleSwingVert:
+ result += F("Toggle vertically swing");
+ break;
+ case kFujitsuAcCmdEcono:
+ result += F("Economy");
+ break;
+ case kFujitsuAcCmdPowerful:
+ result += F("Powerful");
+ break;
+ default:
+ result += F("N/A");
+ }
+ if (this->getModel() == fujitsu_ac_remote_model_t::ARREB1E)
+ result += addBoolToString(getOutsideQuiet(), F("Outside Quiet"));
+ return result;
+}
+
+#if DECODE_FUJITSU_AC
+// Decode a Fujitsu AC IR message if possible.
+// Places successful decode information in the results pointer.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: The number of data bits to expect. Typically kFujitsuAcBits.
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: ALPHA / Untested.
+//
+// Ref:
+//
+bool IRrecv::decodeFujitsuAC(decode_results* results, uint16_t nbits,
+ bool strict) {
+ uint16_t offset = kStartOffset;
+ uint16_t dataBitsSoFar = 0;
+
+ // Have we got enough data to successfully decode?
+ if (results->rawlen < (2 * kFujitsuAcMinBits) + kHeader + kFooter - 1)
+ return false; // Can't possibly be a valid message.
+
+ // Compliance
+ if (strict) {
+ switch (nbits) {
+ case kFujitsuAcBits:
+ case kFujitsuAcBits - 8:
+ case kFujitsuAcMinBits:
+ case kFujitsuAcMinBits + 8:
+ break;
+ default:
+ return false; // Must be called with the correct nr. of bits.
+ }
+ }
+
+ // Header
+ if (!matchMark(results->rawbuf[offset++], kFujitsuAcHdrMark)) return false;
+ if (!matchSpace(results->rawbuf[offset++], kFujitsuAcHdrSpace)) return false;
+
+ // Data (Fixed signature)
+ match_result_t data_result =
+ matchData(&(results->rawbuf[offset]), kFujitsuAcMinBits - 8,
+ kFujitsuAcBitMark, kFujitsuAcOneSpace, kFujitsuAcBitMark,
+ kFujitsuAcZeroSpace, _tolerance, kMarkExcess, false);
+ if (data_result.success == false) return false; // Fail
+ if (data_result.data != 0x1010006314) return false; // Signature failed.
+ dataBitsSoFar += kFujitsuAcMinBits - 8;
+ offset += data_result.used;
+ results->state[0] = 0x14;
+ results->state[1] = 0x63;
+ results->state[2] = 0x00;
+ results->state[3] = 0x10;
+ results->state[4] = 0x10;
+
+ // Keep reading bytes until we either run out of message or state to fill.
+ for (uint16_t i = 5;
+ offset <= results->rawlen - 16 && i < kFujitsuAcStateLength;
+ i++, dataBitsSoFar += 8, offset += data_result.used) {
+ data_result = matchData(
+ &(results->rawbuf[offset]), 8, kFujitsuAcBitMark, kFujitsuAcOneSpace,
+ kFujitsuAcBitMark, kFujitsuAcZeroSpace, _tolerance, kMarkExcess, false);
+ if (data_result.success == false) break; // Fail
+ results->state[i] = data_result.data;
+ }
+
+ // Footer
+ if (offset > results->rawlen ||
+ !matchMark(results->rawbuf[offset++], kFujitsuAcBitMark))
+ return false;
+ // The space is optional if we are out of capture.
+ if (offset < results->rawlen &&
+ !matchAtLeast(results->rawbuf[offset], kFujitsuAcMinGap))
+ return false;
+
+ // Compliance
+ if (strict) {
+ if (dataBitsSoFar != nbits) return false;
+ }
+
+ results->decode_type = FUJITSU_AC;
+ results->bits = dataBitsSoFar;
+
+ // Compliance
+ switch (dataBitsSoFar) {
+ case kFujitsuAcMinBits:
+ // Check if this values indicate that this should have been a long state
+ // message.
+ if (results->state[5] == 0xFC) return false;
+ return true; // Success
+ case kFujitsuAcMinBits + 8:
+ // Check if this values indicate that this should have been a long state
+ // message.
+ if (results->state[5] == 0xFE) return false;
+ // The last byte needs to be the inverse of the penultimate byte.
+ if (results->state[5] != (uint8_t)~results->state[6]) return false;
+ return true; // Success
+ case kFujitsuAcBits - 8:
+ // Long messages of this size require this byte be correct.
+ if (results->state[5] != 0xFC) return false;
+ break;
+ case kFujitsuAcBits:
+ // Long messages of this size require this byte be correct.
+ if (results->state[5] != 0xFE) return false;
+ break;
+ default:
+ return false; // Unexpected size.
+ }
+ if (!IRFujitsuAC::validChecksum(results->state, dataBitsSoFar / 8))
+ return false;
+
+ // Success
+ return true; // All good.
+}
+#endif // DECODE_FUJITSU_AC
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.h b/lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.h
similarity index 51%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.h
index 78a4f8951..e953f9058 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.h
@@ -1,5 +1,16 @@
// Copyright 2017 Jonny Graham
-// Copyright 2018 David Conran
+// Copyright 2018-2019 David Conran
+
+// Supports:
+// Brand: Fujitsu, Model: AR-RAH2E remote
+// Brand: Fujitsu, Model: ASYG30LFCA A/C
+// Brand: Fujitsu, Model: AR-DB1 remote
+// Brand: Fujitsu, Model: AST9RSGCW A/C
+// Brand: Fujitsu, Model: AR-REB1E remote
+// Brand: Fujitsu, Model: ASYG7LMCA A/C
+// Brand: Fujitsu, Model: AR-RAE1E remote
+// Brand: Fujitsu General, Model: AR-JW2 remote
+
#ifndef IR_FUJITSU_H_
#define IR_FUJITSU_H_
@@ -7,8 +18,6 @@
#include
#ifdef ARDUINO
#include
-#else
-#include
#endif
#include "IRrecv.h"
#include "IRremoteESP8266.h"
@@ -26,11 +35,15 @@ const uint8_t kFujitsuAcModeDry = 0x02;
const uint8_t kFujitsuAcModeFan = 0x03;
const uint8_t kFujitsuAcModeHeat = 0x04;
-const uint8_t kFujitsuAcCmdStayOn = 0x00;
-const uint8_t kFujitsuAcCmdTurnOn = 0x01;
-const uint8_t kFujitsuAcCmdTurnOff = 0x02;
-const uint8_t kFujitsuAcCmdStepHoriz = 0x79;
-const uint8_t kFujitsuAcCmdStepVert = 0x6C;
+const uint8_t kFujitsuAcCmdStayOn = 0x00; // b00000000
+const uint8_t kFujitsuAcCmdTurnOn = 0x01; // b00000001
+const uint8_t kFujitsuAcCmdTurnOff = 0x02; // b00000010
+const uint8_t kFujitsuAcCmdEcono = 0x09; // b00001001
+const uint8_t kFujitsuAcCmdPowerful = 0x39; // b00111001
+const uint8_t kFujitsuAcCmdStepVert = 0x6C; // b01101100
+const uint8_t kFujitsuAcCmdToggleSwingVert = 0x6D; // b01101101
+const uint8_t kFujitsuAcCmdStepHoriz = 0x79; // b01111001
+const uint8_t kFujitsuAcCmdToggleSwingHoriz = 0x7A; // b01111010
const uint8_t kFujitsuAcFanAuto = 0x00;
const uint8_t kFujitsuAcFanHigh = 0x01;
@@ -70,45 +83,59 @@ const uint8_t kFujitsuAcSwingBoth = 0x03;
#define FUJITSU_AC_SWING_BOTH kFujitsuAcSwingBoth
enum fujitsu_ac_remote_model_t {
- ARRAH2E = 1,
- ARDB1,
+ ARRAH2E = 1, // (1) AR-RAH2E, AR-RAE1E (Default)
+ ARDB1, // (2) AR-DB1
+ ARREB1E, // (3) AR-REB1E
+ ARJW2, // (4) AR-JW2 (Same as ARDB1 but with horiz control)
};
class IRFujitsuAC {
public:
- explicit IRFujitsuAC(uint16_t pin, fujitsu_ac_remote_model_t model = ARRAH2E);
+ explicit IRFujitsuAC(const uint16_t pin,
+ const fujitsu_ac_remote_model_t model = ARRAH2E,
+ const bool inverted = false,
+ const bool use_modulation = true);
- void setModel(fujitsu_ac_remote_model_t model);
- void stateReset();
+ void setModel(const fujitsu_ac_remote_model_t model);
+ fujitsu_ac_remote_model_t getModel(void);
+ void stateReset(void);
#if SEND_FUJITSU_AC
void send(const uint16_t repeat = kFujitsuAcMinRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_FUJITSU_AC
- void begin();
- void off();
- void stepHoriz();
- void stepVert();
- void setCmd(uint8_t cmd);
- uint8_t getCmd();
- void setTemp(uint8_t temp);
- uint8_t getTemp();
- void setFanSpeed(uint8_t fan);
- uint8_t getFanSpeed();
- void setMode(uint8_t mode);
- uint8_t getMode();
- void setSwing(uint8_t mode);
- uint8_t getSwing();
- uint8_t* getRaw();
+ void begin(void);
+ void stepHoriz(void);
+ void toggleSwingHoriz(const bool update = true);
+ void stepVert(void);
+ void toggleSwingVert(const bool update = true);
+ void setCmd(const uint8_t cmd);
+ uint8_t getCmd(const bool raw = false);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp(void);
+ void setFanSpeed(const uint8_t fan);
+ uint8_t getFanSpeed(void);
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ void setSwing(const uint8_t mode);
+ uint8_t getSwing(const bool raw = false);
+ uint8_t* getRaw(void);
bool setRaw(const uint8_t newState[], const uint16_t length);
- uint8_t getStateLength();
- static bool validChecksum(uint8_t* state, uint16_t length);
- bool getPower();
+ uint8_t getStateLength(void);
+ static bool validChecksum(uint8_t* state, const uint16_t length);
+ void setPower(const bool on);
+ void off(void);
+ void on(void);
+ bool getPower(void);
+ void setOutsideQuiet(const bool on);
+
+ bool getOutsideQuiet(const bool raw = false);
+
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(stdAc::fanspeed_t speed);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -125,7 +152,8 @@ class IRFujitsuAC {
fujitsu_ac_remote_model_t _model;
uint8_t _state_length;
uint8_t _state_length_short;
- void buildState();
+ bool _outsideQuiet;
+ void buildState(void);
void buildFromState(const uint16_t length);
};
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_GICable.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_GICable.cpp
similarity index 70%
rename from lib/IRremoteESP8266-2.6.0/src/ir_GICable.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_GICable.cpp
index 229e4e5bb..6b3849b4c 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_GICable.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_GICable.cpp
@@ -1,4 +1,5 @@
// Copyright 2018 David Conran
+// G.I. Cable
#define __STDC_LIMIT_MACROS
#include
@@ -7,15 +8,9 @@
#include "IRsend.h"
#include "IRutils.h"
-// GGGG IIIII CCCCC AAA BBBBB LL EEEEEEE
-// GG GG III CC C AAAAA BB B LL EE
-// GG III CC AA AA BBBBBB LL EEEEE
-// GG GG ... III ... CC C AAAAAAA BB BB LL EE
-// GGGGGG ... IIIII ... CCCCC AA AA BBBBBB LLLLLLL EEEEEEE
-//
// Ref:
// https://github.com/cyborg5/IRLib2/blob/master/IRLibProtocols/IRLib_P09_GICable.h
-// https://github.com/markszabo/IRremoteESP8266/issues/447
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/447
// Constants
const uint16_t kGicableHdrMark = 9000;
@@ -71,32 +66,21 @@ void IRsend::sendGICable(uint64_t data, uint16_t nbits, uint16_t repeat) {
// Status: Alpha / Not tested against a real device.
bool IRrecv::decodeGICable(decode_results *results, uint16_t nbits,
bool strict) {
- if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1)
- return false; // Can't possibly be a valid GICABLE message.
if (strict && nbits != kGicableBits)
return false; // Not strictly an GICABLE message.
uint64_t data = 0;
uint16_t offset = kStartOffset;
-
- // Header
- if (!matchMark(results->rawbuf[offset++], kGicableHdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kGicableHdrSpace)) return false;
-
- // Data
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits, kGicableBitMark,
- kGicableOneSpace, kGicableBitMark, kGicableZeroSpace);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kGicableBitMark)) return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kGicableMinGap))
- return false;
-
+ // Match Header + Data + Footer
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kGicableHdrMark, kGicableHdrSpace,
+ kGicableBitMark, kGicableOneSpace,
+ kGicableBitMark, kGicableZeroSpace,
+ kGicableBitMark, kGicableMinGap, true);
+ if (!used) return false;
+ offset += used;
// Compliance
if (strict) {
// We expect a repeat frame.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_GlobalCache.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_GlobalCache.cpp
similarity index 86%
rename from lib/IRremoteESP8266-2.6.0/src/ir_GlobalCache.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_GlobalCache.cpp
index daa9dd22c..8c9646970 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_GlobalCache.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_GlobalCache.cpp
@@ -1,18 +1,12 @@
// Copyright 2016 Hisham Khalifa
// Copyright 2017 David Conran
-#include
-#include "IRsend.h"
-
-// GGG L OOOO BBBB AA L CCCC AA CCCC H H EEEEEE
-// G G L O O B B AAAA L C C AAAA C C H H E
-// G L O O BBBBB A A L C A A C HHHHHH EEEE
-// G GG L O O B BB AAAAAA L C C AAAAAA C C H H E
-// GGGGG LLLLLL OOOO BBBBB A A LLLLLL CCCC A A CCCC H H EEEEEE
-
// Global Cache IR format sender originally added by Hisham Khalifa
// (http://www.hishamkhalifa.com)
+#include
+#include "IRsend.h"
+
// Constants
const uint16_t kGlobalCacheMaxRepeat = 50;
const uint32_t kGlobalCacheMinUsec = 80;
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.cpp
new file mode 100644
index 000000000..d8ac45f1b
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.cpp
@@ -0,0 +1,464 @@
+// Copyright 2019 ribeirodanielf
+// Copyright 2019 David Conran
+//
+// Code to emulate Goodweather protocol compatible HVAC devices.
+// Should be compatible with:
+// * ZH/JT-03 remote control
+//
+
+#include "ir_Goodweather.h"
+#include
+#ifndef ARDUINO
+#include
+#endif
+#include "IRrecv.h"
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#include "IRutils.h"
+
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addFanToString;
+using irutils::addTempToString;
+
+#if SEND_GOODWEATHER
+// Send a Goodweather message.
+//
+// Args:
+// data: The raw message to be sent.
+// nbits: Nr. of bits of data in the message. (Default is kGoodweatherBits)
+// repeat: Nr. of times the message is to be repeated. (Default = 0).
+//
+// Status: ALPHA / Untested.
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/697
+void IRsend::sendGoodweather(const uint64_t data, const uint16_t nbits,
+ const uint16_t repeat) {
+ if (nbits != kGoodweatherBits)
+ return; // Wrong nr. of bits to send a proper message.
+ // Set IR carrier frequency
+ enableIROut(38);
+
+ for (uint16_t r = 0; r <= repeat; r++) {
+ // Header
+ mark(kGoodweatherHdrMark);
+ space(kGoodweatherHdrSpace);
+
+ // Data
+ for (int16_t i = 0; i < nbits; i += 8) {
+ uint16_t chunk = (data >> i) & 0xFF; // Grab a byte at a time.
+ chunk = (~chunk) << 8 | chunk; // Prepend a inverted copy of the byte.
+ sendData(kGoodweatherBitMark, kGoodweatherOneSpace,
+ kGoodweatherBitMark, kGoodweatherZeroSpace,
+ chunk, 16, false);
+ }
+ // Footer
+ mark(kGoodweatherBitMark);
+ space(kGoodweatherHdrSpace);
+ mark(kGoodweatherBitMark);
+ space(kDefaultMessageGap);
+ }
+}
+#endif // SEND_GOODWEATHER
+
+IRGoodweatherAc::IRGoodweatherAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
+
+void IRGoodweatherAc::stateReset(void) {
+}
+
+void IRGoodweatherAc::begin(void) { _irsend.begin(); }
+
+#if SEND_GOODWEATHER
+void IRGoodweatherAc::send(const uint16_t repeat) {
+ _irsend.sendGoodweather(remote, kGoodweatherBits, repeat);
+}
+#endif // SEND_GOODWEATHER
+
+uint64_t IRGoodweatherAc::getRaw(void) { return remote; }
+
+void IRGoodweatherAc::setRaw(const uint64_t state) { remote = state; }
+
+void IRGoodweatherAc::on(void) { this->setPower(true); }
+
+void IRGoodweatherAc::off(void) { this->setPower(false); }
+
+void IRGoodweatherAc::setPower(const bool on) {
+ this->setCommand(kGoodweatherCmdPower);
+ if (on)
+ remote |= kGoodweatherPowerMask;
+ else
+ remote &= ~kGoodweatherPowerMask;
+}
+
+bool IRGoodweatherAc::getPower(void) { return remote & kGoodweatherPowerMask; }
+
+// Set the temp. in deg C
+void IRGoodweatherAc::setTemp(const uint8_t temp) {
+ uint8_t new_temp = std::max(kGoodweatherTempMin, temp);
+ new_temp = std::min(kGoodweatherTempMax, new_temp);
+ if (new_temp > this->getTemp()) this->setCommand(kGoodweatherCmdUpTemp);
+ if (new_temp < this->getTemp()) this->setCommand(kGoodweatherCmdDownTemp);
+ remote &= ~kGoodweatherTempMask;
+ remote |= (uint64_t)(new_temp - kGoodweatherTempMin) << kGoodweatherBitTemp;
+}
+
+// Return the set temp. in deg C
+uint8_t IRGoodweatherAc::getTemp(void) {
+ return ((remote & kGoodweatherTempMask) >> kGoodweatherBitTemp) +
+ kGoodweatherTempMin;
+}
+
+// Set the speed of the fan
+void IRGoodweatherAc::setFan(const uint8_t speed) {
+ switch (speed) {
+ case kGoodweatherFanAuto:
+ case kGoodweatherFanLow:
+ case kGoodweatherFanMed:
+ case kGoodweatherFanHigh:
+ this->setCommand(kGoodweatherCmdFan);
+ remote &= ~kGoodweatherFanMask;
+ remote |= ((uint64_t)speed << kGoodweatherBitFan);
+ break;
+ default:
+ this->setFan(kGoodweatherFanAuto);
+ }
+}
+
+uint8_t IRGoodweatherAc::getFan() {
+ return (remote & kGoodweatherFanMask) >> kGoodweatherBitFan;
+}
+
+void IRGoodweatherAc::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kGoodweatherAuto:
+ case kGoodweatherDry:
+ case kGoodweatherCool:
+ case kGoodweatherFan:
+ case kGoodweatherHeat:
+ this->setCommand(kGoodweatherCmdMode);
+ remote &= ~kGoodweatherModeMask;
+ remote |= (uint64_t)mode << kGoodweatherBitMode;
+ break;
+ default:
+ // If we get an unexpected mode, default to AUTO.
+ this->setMode(kGoodweatherAuto);
+ }
+}
+
+uint8_t IRGoodweatherAc::getMode() {
+ return (remote & kGoodweatherModeMask) >> kGoodweatherBitMode;
+}
+
+void IRGoodweatherAc::setLight(const bool toggle) {
+ this->setCommand(kGoodweatherCmdLight);
+ if (toggle)
+ remote |= kGoodweatherLightMask;
+ else
+ remote &= ~kGoodweatherLightMask;
+}
+
+bool IRGoodweatherAc::getLight() { return remote & kGoodweatherLightMask; }
+
+void IRGoodweatherAc::setSleep(const bool toggle) {
+ this->setCommand(kGoodweatherCmdSleep);
+ if (toggle)
+ remote |= kGoodweatherSleepMask;
+ else
+ remote &= ~kGoodweatherSleepMask;
+}
+
+bool IRGoodweatherAc::getSleep() { return remote & kGoodweatherSleepMask; }
+
+void IRGoodweatherAc::setTurbo(const bool toggle) {
+ this->setCommand(kGoodweatherCmdTurbo);
+ if (toggle)
+ remote |= kGoodweatherTurboMask;
+ else
+ remote &= ~kGoodweatherTurboMask;
+}
+
+bool IRGoodweatherAc::getTurbo() { return remote & kGoodweatherTurboMask; }
+
+void IRGoodweatherAc::setSwing(const uint8_t speed) {
+ switch (speed) {
+ case kGoodweatherSwingOff:
+ case kGoodweatherSwingSlow:
+ case kGoodweatherSwingFast:
+ this->setCommand(kGoodweatherCmdSwing);
+ remote &= ~kGoodweatherSwingMask;
+ remote |= ((uint64_t)speed << kGoodweatherBitSwing);
+ break;
+ default:
+ this->setSwing(kGoodweatherSwingOff);
+ }
+}
+
+uint8_t IRGoodweatherAc::getSwing() {
+ return (remote & kGoodweatherSwingMask) >> kGoodweatherBitSwing;
+}
+
+void IRGoodweatherAc::setCommand(const uint8_t cmd) {
+ if (cmd <= kGoodweatherCmdLight) {
+ remote &= ~kGoodweatherCommandMask;
+ remote |= (cmd << kGoodweatherBitCommand);
+ }
+}
+
+uint8_t IRGoodweatherAc::getCommand() {
+ return (remote & kGoodweatherCommandMask) >> kGoodweatherBitCommand;
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRGoodweatherAc::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kGoodweatherCool;
+ case stdAc::opmode_t::kHeat:
+ return kGoodweatherHeat;
+ case stdAc::opmode_t::kDry:
+ return kGoodweatherDry;
+ case stdAc::opmode_t::kFan:
+ return kGoodweatherFan;
+ default:
+ return kGoodweatherAuto;
+ }
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRGoodweatherAc::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ case stdAc::fanspeed_t::kLow:
+ return kGoodweatherFanLow;
+ case stdAc::fanspeed_t::kMedium:
+ return kGoodweatherFanMed;
+ case stdAc::fanspeed_t::kHigh:
+ case stdAc::fanspeed_t::kMax:
+ return kGoodweatherFanHigh;
+ default:
+ return kGoodweatherFanAuto;
+ }
+}
+
+// Convert a standard A/C Vertical Swing into its native version.
+uint8_t IRGoodweatherAc::convertSwingV(const stdAc::swingv_t swingv) {
+ switch (swingv) {
+ case stdAc::swingv_t::kHighest:
+ case stdAc::swingv_t::kHigh:
+ case stdAc::swingv_t::kMiddle:
+ return kGoodweatherSwingFast;
+ case stdAc::swingv_t::kLow:
+ case stdAc::swingv_t::kLowest:
+ case stdAc::swingv_t::kAuto:
+ return kGoodweatherSwingSlow;
+ default:
+ return kGoodweatherSwingOff;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRGoodweatherAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kGoodweatherCool: return stdAc::opmode_t::kCool;
+ case kGoodweatherHeat: return stdAc::opmode_t::kHeat;
+ case kGoodweatherDry: return stdAc::opmode_t::kDry;
+ case kGoodweatherFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRGoodweatherAc::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kGoodweatherFanHigh: return stdAc::fanspeed_t::kMax;
+ case kGoodweatherFanMed: return stdAc::fanspeed_t::kMedium;
+ case kGoodweatherFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRGoodweatherAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::GOODWEATHER;
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwing() == kGoodweatherSwingOff ?
+ stdAc::swingv_t::kOff : stdAc::swingv_t::kAuto;
+ result.turbo = this->getTurbo();
+ result.light = this->getLight();
+ result.sleep = this->getSleep() ? 0: -1;
+ // Not supported.
+ result.model = -1;
+ result.swingh = stdAc::swingh_t::kOff;
+ result.quiet = false;
+ result.econo = false;
+ result.filter = false;
+ result.clean = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRGoodweatherAc::toString() {
+ String result = "";
+ result.reserve(150); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kGoodweatherAuto, kGoodweatherCool,
+ kGoodweatherHeat, kGoodweatherDry, kGoodweatherFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kGoodweatherFanHigh, kGoodweatherFanLow,
+ kGoodweatherFanAuto, kGoodweatherFanAuto,
+ kGoodweatherFanMed);
+ result += addLabeledString(getTurbo() ? F("Toggle") : F("-"), F("Turbo"));
+ result += addLabeledString(getLight() ? F("Toggle") : F("-"), F("Light"));
+ result += addLabeledString(getSleep() ? F("Toggle") : F("-"), F("Sleep"));
+ result += addIntToString(getSwing(), F("Swing"));
+ switch (this->getSwing()) {
+ case kGoodweatherSwingFast:
+ result += F(" (Fast)");
+ break;
+ case kGoodweatherSwingSlow:
+ result += F(" (Slow)");
+ break;
+ case kGoodweatherSwingOff:
+ result += F(" (Off)");
+ break;
+ default:
+ result += F(" (UNKNOWN)");
+ }
+ result += addIntToString(getCommand(), F("Command"));
+ switch (this->getCommand()) {
+ case kGoodweatherCmdPower:
+ result += F(" (Power)");
+ break;
+ case kGoodweatherCmdMode:
+ result += F(" (Mode)");
+ break;
+ case kGoodweatherCmdUpTemp:
+ result += F(" (Temp Up)");
+ break;
+ case kGoodweatherCmdDownTemp:
+ result += F(" (Temp Down)");
+ break;
+ case kGoodweatherCmdSwing:
+ result += F(" (Swing)");
+ break;
+ case kGoodweatherCmdFan:
+ result += F(" (Fan)");
+ break;
+ case kGoodweatherCmdTimer:
+ result += F(" (Timer)");
+ break;
+ case kGoodweatherCmdAirFlow:
+ result += F(" (Air Flow)");
+ break;
+ case kGoodweatherCmdHold:
+ result += F(" (Hold)");
+ break;
+ case kGoodweatherCmdSleep:
+ result += F(" (Sleep)");
+ break;
+ case kGoodweatherCmdTurbo:
+ result += F(" (Turbo)");
+ break;
+ case kGoodweatherCmdLight:
+ result += F(" (Light)");
+ break;
+ default:
+ result += F(" (UNKNOWN)");
+ }
+ return result;
+}
+
+#if DECODE_GOODWEATHER
+// Decode the supplied Goodweather message.
+//
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: The number of data bits to expect. Typically kGoodweatherBits.
+// strict: Flag indicating if we should perform strict matching.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: ALPHA / Untested.
+bool IRrecv::decodeGoodweather(decode_results* results,
+ const uint16_t nbits,
+ const bool strict) {
+ if (results->rawlen < 2 * (2 * nbits) + kHeader + 2 * kFooter - 1)
+ return false; // Can't possibly be a valid Goodweather message.
+ if (strict && nbits != kGoodweatherBits)
+ return false; // Not strictly a Goodweather message.
+
+ uint64_t dataSoFar = 0;
+ uint16_t dataBitsSoFar = 0;
+ uint16_t offset = kStartOffset;
+ match_result_t data_result;
+
+ // Header
+ if (!matchMark(results->rawbuf[offset++], kGoodweatherHdrMark)) return false;
+ if (!matchSpace(results->rawbuf[offset++], kGoodweatherHdrSpace))
+ return false;
+
+ // Data
+ for (; offset <= results->rawlen - 32 && dataBitsSoFar < nbits;
+ dataBitsSoFar += 8) {
+ DPRINT("DEBUG: Attempting Byte #");
+ DPRINTLN(dataBitsSoFar / 8);
+ // Read in a byte at a time.
+ // Normal first.
+ data_result = matchData(&(results->rawbuf[offset]), 8,
+ kGoodweatherBitMark, kGoodweatherOneSpace,
+ kGoodweatherBitMark, kGoodweatherZeroSpace,
+ _tolerance, kMarkExcess, false);
+ if (data_result.success == false) return false;
+ DPRINTLN("DEBUG: Normal byte read okay.");
+ offset += data_result.used;
+ uint8_t data = (uint8_t)data_result.data;
+ // Then inverted.
+ data_result = matchData(&(results->rawbuf[offset]), 8,
+ kGoodweatherBitMark, kGoodweatherOneSpace,
+ kGoodweatherBitMark, kGoodweatherZeroSpace,
+ _tolerance, kMarkExcess, false);
+ if (data_result.success == false) return false;
+ DPRINTLN("DEBUG: Inverted byte read okay.");
+ offset += data_result.used;
+ uint8_t inverted = (uint8_t)data_result.data;
+ DPRINT("DEBUG: data = ");
+ DPRINTLN((uint16_t)data);
+ DPRINT("DEBUG: inverted = ");
+ DPRINTLN((uint16_t)inverted);
+ if (data != (inverted ^ 0xFF)) return false; // Data integrity failed.
+ dataSoFar |= (uint64_t)data << dataBitsSoFar;
+ }
+
+ // Footer.
+ if (!matchMark(results->rawbuf[offset++], kGoodweatherBitMark)) return false;
+ if (!matchSpace(results->rawbuf[offset++], kGoodweatherHdrSpace))
+ return false;
+ if (!matchMark(results->rawbuf[offset++], kGoodweatherBitMark)) return false;
+ if (offset <= results->rawlen &&
+ !matchAtLeast(results->rawbuf[offset], kGoodweatherHdrSpace))
+ return false;
+
+ // Compliance
+ if (strict && (dataBitsSoFar != kGoodweatherBits)) return false;
+
+ // Success
+ results->decode_type = decode_type_t::GOODWEATHER;
+ results->bits = dataBitsSoFar;
+ results->value = dataSoFar;
+ results->address = 0;
+ results->command = 0;
+ return true;
+}
+#endif // DECODE_GOODWEATHER
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.h b/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.h
new file mode 100644
index 000000000..76d559779
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.h
@@ -0,0 +1,137 @@
+// Goodweather A/C
+//
+// Copyright 2019 ribeirodanielf
+// Copyright 2019 David Conran
+
+// Supports:
+// Brand: Goodweather, Model: ZH/JT-03 remote
+
+#ifndef IR_GOODWEATHER_H_
+#define IR_GOODWEATHER_H_
+
+#define __STDC_LIMIT_MACROS
+#include
+#ifndef UNIT_TEST
+#include
+#endif
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#ifdef UNIT_TEST
+#include "IRsend_test.h"
+#endif
+
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/697
+
+// Constants
+
+// Timing
+const uint16_t kGoodweatherBitMark = 640;
+const uint16_t kGoodweatherOneSpace = 580;
+const uint16_t kGoodweatherZeroSpace = 1600;
+const uint16_t kGoodweatherHdrMark = 6800;
+const uint16_t kGoodweatherHdrSpace = 6800;
+
+// Masks
+const uint8_t kGoodweatherBitLight = 8;
+const uint64_t kGoodweatherLightMask = 0x1ULL << kGoodweatherBitLight;
+const uint8_t kGoodweatherBitTurbo = kGoodweatherBitLight + 3; // 11
+const uint64_t kGoodweatherTurboMask = 0x1ULL << kGoodweatherBitTurbo;
+const uint8_t kGoodweatherBitCommand = kGoodweatherBitTurbo + 5; // 16
+const uint64_t kGoodweatherCommandMask = 0xFULL << kGoodweatherBitCommand;
+const uint8_t kGoodweatherBitSleep = kGoodweatherBitCommand + 8; // 24
+const uint64_t kGoodweatherSleepMask = 0x1ULL << kGoodweatherBitSleep;
+const uint8_t kGoodweatherBitPower = kGoodweatherBitSleep + 1; // 25
+const uint64_t kGoodweatherPowerMask = 0x1ULL << kGoodweatherBitPower;
+const uint8_t kGoodweatherBitSwing = kGoodweatherBitPower + 1; // 26
+const uint64_t kGoodweatherSwingMask = 0x3ULL << kGoodweatherBitSwing;
+const uint8_t kGoodweatherBitFan = kGoodweatherBitSwing + 3; // 29
+const uint64_t kGoodweatherFanMask = 0x3ULL << kGoodweatherBitFan;
+const uint8_t kGoodweatherBitTemp = kGoodweatherBitFan + 3; // 32
+const uint64_t kGoodweatherTempMask = 0xFULL << kGoodweatherBitTemp;
+const uint8_t kGoodweatherBitMode = kGoodweatherBitTemp + 5; // 37
+const uint64_t kGoodweatherModeMask = 0x7ULL << kGoodweatherBitMode;
+
+// Modes
+const uint8_t kGoodweatherAuto = 0b000;
+const uint8_t kGoodweatherCool = 0b001;
+const uint8_t kGoodweatherDry = 0b010;
+const uint8_t kGoodweatherFan = 0b011;
+const uint8_t kGoodweatherHeat = 0b100;
+const uint8_t kGoodweatherSwingFast = 0b00;
+const uint8_t kGoodweatherSwingSlow = 0b01;
+const uint8_t kGoodweatherSwingOff = 0b10;
+// Fan Control
+const uint8_t kGoodweatherFanAuto = 0b00;
+const uint8_t kGoodweatherFanHigh = 0b01;
+const uint8_t kGoodweatherFanMed = 0b10;
+const uint8_t kGoodweatherFanLow = 0b11;
+// Temperature
+const uint8_t kGoodweatherTempMin = 16; // Celsius
+const uint8_t kGoodweatherTempMax = 31; // Celsius
+// Commands
+const uint8_t kGoodweatherCmdPower = 0x00;
+const uint8_t kGoodweatherCmdMode = 0x01;
+const uint8_t kGoodweatherCmdUpTemp = 0x02;
+const uint8_t kGoodweatherCmdDownTemp = 0x03;
+const uint8_t kGoodweatherCmdSwing = 0x04;
+const uint8_t kGoodweatherCmdFan = 0x05;
+const uint8_t kGoodweatherCmdTimer = 0x06;
+const uint8_t kGoodweatherCmdAirFlow = 0x07;
+const uint8_t kGoodweatherCmdHold = 0x08;
+const uint8_t kGoodweatherCmdSleep = 0x09;
+const uint8_t kGoodweatherCmdTurbo = 0x0A;
+const uint8_t kGoodweatherCmdLight = 0x0B;
+
+
+// Classes
+class IRGoodweatherAc {
+ public:
+ explicit IRGoodweatherAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+ void stateReset(void);
+#if SEND_GOODWEATHER
+ void send(const uint16_t repeat = kGoodweatherMinRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif // SEND_GOODWEATHER
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp(void);
+ void setFan(const uint8_t speed);
+ uint8_t getFan(void);
+ void setMode(const uint8_t mode);
+ uint8_t getMode();
+ void setSwing(const uint8_t speed);
+ uint8_t getSwing(void);
+ void setSleep(const bool toggle);
+ bool getSleep(void);
+ void setTurbo(const bool toggle);
+ bool getTurbo(void);
+ void setLight(const bool toggle);
+ bool getLight(void);
+ void setCommand(const uint8_t cmd);
+ uint8_t getCommand(void);
+ uint64_t getRaw(void);
+ void setRaw(const uint64_t state);
+ uint8_t convertMode(const stdAc::opmode_t mode);
+ uint8_t convertFan(const stdAc::fanspeed_t speed);
+ uint8_t convertSwingV(const stdAc::swingv_t swingv);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString();
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ uint64_t remote; // The state of the IR remote in IR code form.
+};
+#endif // IR_GOODWEATHER_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Gree.cpp
similarity index 50%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Gree.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Gree.cpp
index 756f008d4..a4d906424 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Gree.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Gree.cpp
@@ -18,12 +18,6 @@
#include "IRutils.h"
#include "ir_Kelvinator.h"
-// GGGG RRRRRR EEEEEEE EEEEEEE
-// GG GG RR RR EE EE
-// GG RRRRRR EEEEE EEEEE
-// GG GG RR RR EE EE
-// GGGGGG RR RR EEEEEEE EEEEEEE
-
// Constants
// Ref: https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.h
const uint16_t kGreeHdrMark = 9000;
@@ -35,6 +29,14 @@ const uint16_t kGreeMsgSpace = 19000;
const uint8_t kGreeBlockFooter = 0b010;
const uint8_t kGreeBlockFooterBits = 3;
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addFanToString;
+using irutils::addTempToString;
+using irutils::minsToString;
+
#if SEND_GREE
// Send a Gree Heat Pump message.
//
@@ -47,7 +49,8 @@ const uint8_t kGreeBlockFooterBits = 3;
//
// Ref:
// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp
-void IRsend::sendGree(unsigned char data[], uint16_t nbytes, uint16_t repeat) {
+void IRsend::sendGree(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kGreeStateLength)
return; // Not enough bytes to send a proper message.
@@ -80,7 +83,8 @@ void IRsend::sendGree(unsigned char data[], uint16_t nbytes, uint16_t repeat) {
//
// Ref:
// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp
-void IRsend::sendGree(uint64_t data, uint16_t nbits, uint16_t repeat) {
+void IRsend::sendGree(const uint64_t data, const uint16_t nbits,
+ const uint16_t repeat) {
if (nbits != kGreeBits)
return; // Wrong nr. of bits to send a proper message.
// Set IR carrier frequency
@@ -110,9 +114,14 @@ void IRsend::sendGree(uint64_t data, uint16_t nbits, uint16_t repeat) {
}
#endif // SEND_GREE
-IRGreeAC::IRGreeAC(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRGreeAC::IRGreeAC(const uint16_t pin, const gree_ac_remote_model_t model,
+ const bool inverted, const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) {
+ stateReset();
+ setModel(model);
+}
-void IRGreeAC::stateReset() {
+void IRGreeAC::stateReset(void) {
// This resets to a known-good state to Power Off, Fan Auto, Mode Auto, 25C.
for (uint8_t i = 0; i < kGreeStateLength; i++) remote_state[i] = 0x0;
remote_state[1] = 0x09;
@@ -122,11 +131,12 @@ void IRGreeAC::stateReset() {
remote_state[7] = 0x50;
}
-void IRGreeAC::fixup() {
+void IRGreeAC::fixup(void) {
+ setPower(getPower()); // Redo the power bits as they differ between models.
checksum(); // Calculate the checksums
}
-void IRGreeAC::begin() { _irsend.begin(); }
+void IRGreeAC::begin(void) { _irsend.begin(); }
#if SEND_GREE
void IRGreeAC::send(const uint16_t repeat) {
@@ -135,15 +145,22 @@ void IRGreeAC::send(const uint16_t repeat) {
}
#endif // SEND_GREE
-uint8_t* IRGreeAC::getRaw() {
+uint8_t* IRGreeAC::getRaw(void) {
fixup(); // Ensure correct settings before sending.
return remote_state;
}
-void IRGreeAC::setRaw(uint8_t new_code[]) {
+void IRGreeAC::setRaw(const uint8_t new_code[]) {
for (uint8_t i = 0; i < kGreeStateLength; i++) {
remote_state[i] = new_code[i];
}
+ // We can only detect the difference between models when the power is on.
+ if (getPower()) {
+ if (remote_state[2] & kGreePower2Mask)
+ _model = gree_ac_remote_model_t::YAW1F;
+ else
+ _model = gree_ac_remote_model_t::YBOFB;
+ }
}
void IRGreeAC::checksum(const uint16_t length) {
@@ -160,33 +177,45 @@ void IRGreeAC::checksum(const uint16_t length) {
// A boolean.
bool IRGreeAC::validChecksum(const uint8_t state[], const uint16_t length) {
// Top 4 bits of the last byte in the state is the state's checksum.
- if (state[length - 1] >> 4 ==
- IRKelvinatorAC::calcBlockChecksum(state, length))
- return true;
- else
- return false;
+ return (state[length - 1] >> 4 == IRKelvinatorAC::calcBlockChecksum(state,
+ length));
}
-void IRGreeAC::on() {
- remote_state[0] |= kGreePower1Mask;
- remote_state[2] |= kGreePower2Mask;
+void IRGreeAC::setModel(const gree_ac_remote_model_t model) {
+ switch (model) {
+ case gree_ac_remote_model_t::YAW1F:
+ case gree_ac_remote_model_t::YBOFB:
+ _model = model; break;
+ default:
+ setModel(gree_ac_remote_model_t::YAW1F);
+ }
}
-void IRGreeAC::off() {
- remote_state[0] &= ~kGreePower1Mask;
- remote_state[2] &= ~kGreePower2Mask;
+gree_ac_remote_model_t IRGreeAC::getModel(void) {
+ return _model;
}
-void IRGreeAC::setPower(const bool state) {
- if (state)
- on();
- else
- off();
+void IRGreeAC::on(void) { setPower(true); }
+
+void IRGreeAC::off(void) { setPower(false); }
+
+void IRGreeAC::setPower(const bool on) {
+ if (on) {
+ remote_state[0] |= kGreePower1Mask;
+ switch (_model) {
+ case gree_ac_remote_model_t::YBOFB: break;
+ default:
+ remote_state[2] |= kGreePower2Mask;
+ }
+ } else {
+ remote_state[0] &= ~kGreePower1Mask;
+ remote_state[2] &= ~kGreePower2Mask; // May not be needed. See #814
+ }
}
-bool IRGreeAC::getPower() {
- return (remote_state[0] & kGreePower1Mask) &&
- (remote_state[2] & kGreePower2Mask);
+bool IRGreeAC::getPower(void) {
+ // See #814. Not checking/requiring: (remote_state[2] & kGreePower2Mask)
+ return remote_state[0] & kGreePower1Mask;
}
// Set the temp. in deg C
@@ -194,12 +223,13 @@ void IRGreeAC::setTemp(const uint8_t temp) {
uint8_t new_temp = std::max((uint8_t)kGreeMinTemp, temp);
new_temp = std::min((uint8_t)kGreeMaxTemp, new_temp);
if (getMode() == kGreeAuto) new_temp = 25;
- remote_state[1] = (remote_state[1] & 0xF0U) | (new_temp - kGreeMinTemp);
+ remote_state[1] = (remote_state[1] & ~kGreeTempMask) |
+ (new_temp - kGreeMinTemp);
}
// Return the set temp. in deg C
-uint8_t IRGreeAC::getTemp() {
- return ((remote_state[1] & 0xFU) + kGreeMinTemp);
+uint8_t IRGreeAC::getTemp(void) {
+ return ((remote_state[1] & kGreeTempMask) + kGreeMinTemp);
}
// Set the speed of the fan, 0-3, 0 is auto, 1-3 is the speed
@@ -212,7 +242,7 @@ void IRGreeAC::setFan(const uint8_t speed) {
remote_state[0] |= (fan << 4);
}
-uint8_t IRGreeAC::getFan() { return ((remote_state[0] & kGreeFanMask) >> 4); }
+uint8_t IRGreeAC::getFan(void) { return (remote_state[0] & kGreeFanMask) >> 4; }
void IRGreeAC::setMode(const uint8_t new_mode) {
uint8_t mode = new_mode;
@@ -237,35 +267,61 @@ void IRGreeAC::setMode(const uint8_t new_mode) {
remote_state[0] |= mode;
}
-uint8_t IRGreeAC::getMode() { return (remote_state[0] & kGreeModeMask); }
+uint8_t IRGreeAC::getMode(void) { return (remote_state[0] & kGreeModeMask); }
-void IRGreeAC::setLight(const bool state) {
- remote_state[2] &= ~kGreeLightMask;
- remote_state[2] |= (state << 5);
+void IRGreeAC::setLight(const bool on) {
+ if (on)
+ remote_state[2] |= kGreeLightMask;
+ else
+ remote_state[2] &= ~kGreeLightMask;
}
-bool IRGreeAC::getLight() { return remote_state[2] & kGreeLightMask; }
+bool IRGreeAC::getLight(void) { return remote_state[2] & kGreeLightMask; }
-void IRGreeAC::setXFan(const bool state) {
- remote_state[2] &= ~kGreeXfanMask;
- remote_state[2] |= (state << 7);
+void IRGreeAC::setIFeel(const bool on) {
+ if (on)
+ remote_state[5] |= kGreeIFeelMask;
+ else
+ remote_state[5] &= ~kGreeIFeelMask;
}
-bool IRGreeAC::getXFan() { return remote_state[2] & kGreeXfanMask; }
+bool IRGreeAC::getIFeel(void) { return remote_state[5] & kGreeIFeelMask; }
-void IRGreeAC::setSleep(const bool state) {
- remote_state[0] &= ~kGreeSleepMask;
- remote_state[0] |= (state << 7);
+void IRGreeAC::setWiFi(const bool on) {
+ if (on)
+ remote_state[5] |= kGreeWiFiMask;
+ else
+ remote_state[5] &= ~kGreeWiFiMask;
}
-bool IRGreeAC::getSleep() { return remote_state[0] & kGreeSleepMask; }
+bool IRGreeAC::getWiFi(void) { return remote_state[5] & kGreeWiFiMask; }
-void IRGreeAC::setTurbo(const bool state) {
- remote_state[2] &= ~kGreeTurboMask;
- remote_state[2] |= (state << 4);
+void IRGreeAC::setXFan(const bool on) {
+ if (on)
+ remote_state[2] |= kGreeXfanMask;
+ else
+ remote_state[2] &= ~kGreeXfanMask;
}
-bool IRGreeAC::getTurbo() { return remote_state[2] & kGreeTurboMask; }
+bool IRGreeAC::getXFan(void) { return remote_state[2] & kGreeXfanMask; }
+
+void IRGreeAC::setSleep(const bool on) {
+ if (on)
+ remote_state[0] |= kGreeSleepMask;
+ else
+ remote_state[0] &= ~kGreeSleepMask;
+}
+
+bool IRGreeAC::getSleep(void) { return remote_state[0] & kGreeSleepMask; }
+
+void IRGreeAC::setTurbo(const bool on) {
+ if (on)
+ remote_state[2] |= kGreeTurboMask;
+ else
+ remote_state[2] &= ~kGreeTurboMask;
+}
+
+bool IRGreeAC::getTurbo(void) { return remote_state[2] & kGreeTurboMask; }
void IRGreeAC::setSwingVertical(const bool automatic, const uint8_t position) {
remote_state[0] &= ~kGreeSwingAutoMask;
@@ -297,14 +353,52 @@ void IRGreeAC::setSwingVertical(const bool automatic, const uint8_t position) {
remote_state[4] |= new_position;
}
-bool IRGreeAC::getSwingVerticalAuto() {
+bool IRGreeAC::getSwingVerticalAuto(void) {
return remote_state[0] & kGreeSwingAutoMask;
}
-uint8_t IRGreeAC::getSwingVerticalPosition() {
+uint8_t IRGreeAC::getSwingVerticalPosition(void) {
return remote_state[4] & kGreeSwingPosMask;
}
+void IRGreeAC::setTimerEnabled(const bool on) {
+ if (on)
+ remote_state[1] |= kGreeTimerEnabledBit;
+ else
+ remote_state[1] &= ~kGreeTimerEnabledBit;
+}
+
+bool IRGreeAC::getTimerEnabled(void) {
+ return remote_state[1] & kGreeTimerEnabledBit;
+}
+
+// Returns the number of minutes the timer is set for.
+uint16_t IRGreeAC::getTimer(void) {
+ uint16_t hrs = irutils::bcdToUint8(
+ (remote_state[2] & kGreeTimerHoursMask) |
+ ((remote_state[1] & kGreeTimerTensHrMask) >> 1));
+ return hrs * 60 + ((remote_state[1] & kGreeTimerHalfHrBit) ? 30 : 0);
+}
+
+// Set the A/C's timer to turn off in X many minutes.
+// Stores time internally in 30 min units.
+// e.g. 5 mins means 0 (& Off), 95 mins is 90 mins (& On). Max is 24 hours.
+//
+// Args:
+// minutes: The number of minutes the timer should be set for.
+void IRGreeAC::setTimer(const uint16_t minutes) {
+ // Clear the previous settings.
+ remote_state[1] &= ~kGreeTimer1Mask;
+ remote_state[2] &= ~kGreeTimerHoursMask;
+ uint16_t mins = std::min(kGreeTimerMax, minutes); // Bounds check.
+ setTimerEnabled(mins >= 30); // Timer is enabled when >= 30 mins.
+ uint8_t hours = mins / 60;
+ uint8_t halfhour = (mins % 60) < 30 ? 0 : 1;
+ // Set the "tens" digit of hours & the half hour.
+ remote_state[1] |= (((hours / 10) << 1) | halfhour) << 4;
+ // Set the "units" digit of hours.
+ remote_state[2] |= (hours % 10);
+}
// Convert a standard A/C mode into its native mode.
uint8_t IRGreeAC::convertMode(const stdAc::opmode_t mode) {
@@ -356,79 +450,92 @@ uint8_t IRGreeAC::convertSwingV(const stdAc::swingv_t swingv) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRGreeAC::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kGreeCool: return stdAc::opmode_t::kCool;
+ case kGreeHeat: return stdAc::opmode_t::kHeat;
+ case kGreeDry: return stdAc::opmode_t::kDry;
+ case kGreeFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRGreeAC::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kGreeFanMax: return stdAc::fanspeed_t::kMax;
+ case kGreeFanMax - 1: return stdAc::fanspeed_t::kMedium;
+ case kGreeFanMin: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingv_t IRGreeAC::toCommonSwingV(const uint8_t pos) {
+ switch (pos) {
+ case kGreeSwingUp: return stdAc::swingv_t::kHighest;
+ case kGreeSwingMiddleUp: return stdAc::swingv_t::kHigh;
+ case kGreeSwingMiddle: return stdAc::swingv_t::kMiddle;
+ case kGreeSwingMiddleDown: return stdAc::swingv_t::kLow;
+ case kGreeSwingDown: return stdAc::swingv_t::kLowest;
+ default: return stdAc::swingv_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRGreeAC::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::GREE;
+ result.model = this->getModel();
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ if (this->getSwingVerticalAuto())
+ result.swingv = stdAc::swingv_t::kAuto;
+ else
+ result.swingv = this->toCommonSwingV(this->getSwingVerticalPosition());
+ result.turbo = this->getTurbo();
+ result.light = this->getLight();
+ result.clean = this->getXFan();
+ result.sleep = this->getSleep() ? 0 : -1;
+ // Not supported.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.quiet = false;
+ result.econo = false;
+ result.filter = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRGreeAC::toString() {
+String IRGreeAC::toString(void) {
String result = "";
-#else
-std::string IRGreeAC::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kGreeAuto:
- result += F(" (AUTO)");
- break;
- case kGreeCool:
- result += F(" (COOL)");
- break;
- case kGreeHeat:
- result += F(" (HEAT)");
- break;
- case kGreeDry:
- result += F(" (DRY)");
- break;
- case kGreeFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
+ result.reserve(150); // Reserve some heap for the string to reduce fragging.
+ result += addIntToString(getModel(), F("Model"), false);
+ switch (getModel()) {
+ case gree_ac_remote_model_t::YAW1F: result += F(" (YAW1F)"); break;
+ case gree_ac_remote_model_t::YBOFB: result += F(" (YBOFB)"); break;
+ default: result += F(" (UNKNOWN)");
}
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case 0:
- result += F(" (AUTO)");
- break;
- case kGreeFanMax:
- result += F(" (MAX)");
- break;
- }
- result += F(", Turbo: ");
- if (getTurbo())
- result += F("On");
- else
- result += F("Off");
- result += F(", XFan: ");
- if (getXFan())
- result += F("On");
- else
- result += F("Off");
- result += F(", Light: ");
- if (getLight())
- result += F("On");
- else
- result += F("Off");
- result += F(", Sleep: ");
- if (getSleep())
- result += F("On");
- else
- result += F("Off");
- result += F(", Swing Vertical Mode: ");
- if (getSwingVerticalAuto())
- result += F("Auto");
- else
- result += F("Manual");
- result += F(", Swing Vertical Pos: ");
- result += uint64ToString(getSwingVerticalPosition());
+ result += addBoolToString(getPower(), F("Power"));
+ result += addModeToString(getMode(), kGreeAuto, kGreeCool, kGreeHeat,
+ kGreeDry, kGreeFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kGreeFanMax, kGreeFanMin, kGreeFanAuto,
+ kGreeFanAuto, kGreeFanMed);
+ result += addBoolToString(getTurbo(), F("Turbo"));
+ result += addBoolToString(getIFeel(), F("IFeel"));
+ result += addBoolToString(getWiFi(), F("WiFi"));
+ result += addBoolToString(getXFan(), F("XFan"));
+ result += addBoolToString(getLight(), F("Light"));
+ result += addBoolToString(getSleep(), F("Sleep"));
+ result += addLabeledString(getSwingVerticalAuto() ? F("Auto") : F("Manual"),
+ F("Swing Vertical Mode"));
+ result += addIntToString(getSwingVerticalPosition(), F("Swing Vertical Pos"));
switch (getSwingVerticalPosition()) {
case kGreeSwingLastPos:
result += F(" (Last Pos)");
@@ -437,6 +544,11 @@ std::string IRGreeAC::toString() {
result += F(" (Auto)");
break;
}
+ result += F(", Timer: ");
+ if (getTimerEnabled())
+ result += minsToString(getTimer());
+ else
+ result += F("Off");
return result;
}
@@ -458,72 +570,50 @@ bool IRrecv::decodeGree(decode_results* results, uint16_t nbits, bool strict) {
if (strict && nbits != kGreeBits)
return false; // Not strictly a Gree message.
- uint32_t data;
uint16_t offset = kStartOffset;
// There are two blocks back-to-back in a full Gree IR message
// sequence.
- int8_t state_pos = 0;
- match_result_t data_result;
- // Header
- if (!matchMark(results->rawbuf[offset++], kGreeHdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kGreeHdrSpace)) return false;
- // Data Block #1 (32 bits)
- data_result =
- matchData(&(results->rawbuf[offset]), 32, kGreeBitMark, kGreeOneSpace,
- kGreeBitMark, kGreeZeroSpace, kTolerance, kMarkExcess, false);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Record Data Block #1 in the state.
- for (uint16_t i = 0; i < 4; i++, data >>= 8)
- results->state[state_pos + i] = data & 0xFF;
- state_pos += 4;
+ uint16_t used;
+ // Header + Data Block #1 (32 bits)
+ used = matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits / 2,
+ kGreeHdrMark, kGreeHdrSpace,
+ kGreeBitMark, kGreeOneSpace,
+ kGreeBitMark, kGreeZeroSpace,
+ 0, 0, false,
+ _tolerance, kMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
// Block #1 footer (3 bits, B010)
+ match_result_t data_result;
data_result = matchData(&(results->rawbuf[offset]), kGreeBlockFooterBits,
kGreeBitMark, kGreeOneSpace, kGreeBitMark,
- kGreeZeroSpace, kTolerance, kMarkExcess, false);
+ kGreeZeroSpace, _tolerance, kMarkExcess, false);
if (data_result.success == false) return false;
if (data_result.data != kGreeBlockFooter) return false;
offset += data_result.used;
- // Inter-block gap.
- if (!matchMark(results->rawbuf[offset++], kGreeBitMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kGreeMsgSpace)) return false;
-
- // Data Block #2 (32 bits)
- data_result =
- matchData(&(results->rawbuf[offset]), 32, kGreeBitMark, kGreeOneSpace,
- kGreeBitMark, kGreeZeroSpace, kTolerance, kMarkExcess, false);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Record Data Block #2 in the state.
- for (uint16_t i = 0; i < 4; i++, data >>= 8)
- results->state[state_pos + i] = data & 0xFF;
- state_pos += 4;
-
- // Footer.
- if (!matchMark(results->rawbuf[offset++], kGreeBitMark)) return false;
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kGreeMsgSpace))
- return false;
+ // Inter-block gap + Data Block #2 (32 bits) + Footer
+ if (!matchGeneric(results->rawbuf + offset, results->state + 4,
+ results->rawlen - offset, nbits / 2,
+ kGreeBitMark, kGreeMsgSpace,
+ kGreeBitMark, kGreeOneSpace,
+ kGreeBitMark, kGreeZeroSpace,
+ kGreeBitMark, kGreeMsgSpace, true,
+ _tolerance, kMarkExcess, false)) return false;
// Compliance
if (strict) {
- // Correct size/length)
- if (state_pos != kGreeStateLength) return false;
// Verify the message's checksum is correct.
if (!IRGreeAC::validChecksum(results->state)) return false;
}
// Success
results->decode_type = GREE;
- results->bits = state_pos * 8;
+ results->bits = nbits;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Gree.h b/lib/IRremoteESP8266-2.6.5/src/ir_Gree.h
new file mode 100644
index 000000000..a399d50d5
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Gree.h
@@ -0,0 +1,173 @@
+// Copyright 2016 David Conran
+// Gree A/C
+//
+// Supports:
+// Brand: Ultimate, Model: Heat Pump
+// Brand: EKOKAI, Model: A/C
+// Brand: RusClimate, Model: EACS/I-09HAR_X/N3 A/C
+// Brand: RusClimate, Model: YAW1F remote
+// Brand: Green, Model: YBOFB remote
+// Brand: Green, Model: YBOFB2 remote
+
+#ifndef IR_GREE_H_
+#define IR_GREE_H_
+
+#define __STDC_LIMIT_MACROS
+#include
+#ifndef UNIT_TEST
+#include
+#endif
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#ifdef UNIT_TEST
+#include "IRsend_test.h"
+#endif
+
+// Constants
+enum gree_ac_remote_model_t {
+ YAW1F = 1, // (1) Ultimate, EKOKAI, RusClimate (Default)
+ YBOFB, // (2) Green, YBOFB2, YAPOF3
+};
+
+const uint8_t kGreeAuto = 0;
+const uint8_t kGreeCool = 1;
+const uint8_t kGreeDry = 2;
+const uint8_t kGreeFan = 3;
+const uint8_t kGreeHeat = 4;
+
+// Byte 0
+const uint8_t kGreeModeMask = 0b00000111;
+const uint8_t kGreePower1Mask = 0b00001000;
+const uint8_t kGreeFanMask = 0b00110000;
+const uint8_t kGreeFanAuto = 0;
+const uint8_t kGreeFanMin = 1;
+const uint8_t kGreeFanMed = 2;
+const uint8_t kGreeFanMax = 3;
+const uint8_t kGreeSwingAutoMask = 0b01000000;
+const uint8_t kGreeSleepMask = 0b10000000;
+// Byte 1
+const uint8_t kGreeTempMask = 0b00001111;
+const uint8_t kGreeMinTemp = 16; // Celsius
+const uint8_t kGreeMaxTemp = 30; // Celsius
+const uint8_t kGreeTimerEnabledBit = 0b10000000;
+const uint8_t kGreeTimerHalfHrBit = 0b00010000;
+const uint8_t kGreeTimerTensHrMask = 0b01100000;
+const uint8_t kGreeTimer1Mask = kGreeTimerTensHrMask | kGreeTimerHalfHrBit;
+const uint16_t kGreeTimerMax = 24 * 60;
+
+// Byte 2
+const uint8_t kGreeTimerHoursMask = 0b00001111;
+const uint8_t kGreeTurboMask = 0b00010000;
+const uint8_t kGreeLightMask = 0b00100000;
+// This might not be used. See #814
+const uint8_t kGreePower2Mask = 0b01000000;
+const uint8_t kGreeXfanMask = 0b10000000;
+// Byte 4
+const uint8_t kGreeSwingPosMask = 0b00001111;
+// byte 5
+const uint8_t kGreeIFeelMask = 0b00000100;
+const uint8_t kGreeWiFiMask = 0b01000000;
+
+const uint8_t kGreeSwingLastPos = 0b00000000;
+const uint8_t kGreeSwingAuto = 0b00000001;
+const uint8_t kGreeSwingUp = 0b00000010;
+const uint8_t kGreeSwingMiddleUp = 0b00000011;
+const uint8_t kGreeSwingMiddle = 0b00000100;
+const uint8_t kGreeSwingMiddleDown = 0b00000101;
+const uint8_t kGreeSwingDown = 0b00000110;
+const uint8_t kGreeSwingDownAuto = 0b00000111;
+const uint8_t kGreeSwingMiddleAuto = 0b00001001;
+const uint8_t kGreeSwingUpAuto = 0b00001011;
+
+// Legacy defines.
+#define GREE_AUTO kGreeAuto
+#define GREE_COOL kGreeCool
+#define GREE_DRY kGreeDry
+#define GREE_FAN kGreeFan
+#define GREE_HEAT kGreeHeat
+#define GREE_MIN_TEMP kGreeMinTemp
+#define GREE_MAX_TEMP kGreeMaxTemp
+#define GREE_FAN_MAX kGreeFanMax
+#define GREE_SWING_LAST_POS kGreeSwingLastPos
+#define GREE_SWING_AUTO kGreeSwingAuto
+#define GREE_SWING_UP kGreeSwingUp
+#define GREE_SWING_MIDDLE_UP kGreeSwingMiddleUp
+#define GREE_SWING_MIDDLE kGreeSwingMiddle
+#define GREE_SWING_MIDDLE_DOWN kGreeSwingMiddleDown
+#define GREE_SWING_DOWN kGreeSwingDown
+#define GREE_SWING_DOWN_AUTO kGreeSwingDownAuto
+#define GREE_SWING_MIDDLE_AUTO kGreeSwingMiddleAuto
+#define GREE_SWING_UP_AUTO kGreeSwingUpAuto
+
+// Classes
+class IRGreeAC {
+ public:
+ explicit IRGreeAC(
+ const uint16_t pin,
+ const gree_ac_remote_model_t model = gree_ac_remote_model_t::YAW1F,
+ const bool inverted = false, const bool use_modulation = true);
+
+ void stateReset(void);
+#if SEND_GREE
+ void send(const uint16_t repeat = kGreeDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif // SEND_GREE
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setModel(const gree_ac_remote_model_t model);
+ gree_ac_remote_model_t getModel(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp(void);
+ void setFan(const uint8_t speed);
+ uint8_t getFan(void);
+ void setMode(const uint8_t new_mode);
+ uint8_t getMode(void);
+ void setLight(const bool on);
+ bool getLight(void);
+ void setXFan(const bool on);
+ bool getXFan(void);
+ void setSleep(const bool on);
+ bool getSleep(void);
+ void setTurbo(const bool on);
+ bool getTurbo(void);
+ void setIFeel(const bool on);
+ bool getIFeel(void);
+ void setWiFi(const bool on);
+ bool getWiFi(void);
+ void setSwingVertical(const bool automatic, const uint8_t position);
+ bool getSwingVerticalAuto(void);
+ uint8_t getSwingVerticalPosition(void);
+ uint16_t getTimer(void);
+ void setTimer(const uint16_t minutes);
+ uint8_t convertMode(const stdAc::opmode_t mode);
+ uint8_t convertFan(const stdAc::fanspeed_t speed);
+ uint8_t convertSwingV(const stdAc::swingv_t swingv);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ static stdAc::swingv_t toCommonSwingV(const uint8_t pos);
+ stdAc::state_t toCommon(void);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t new_code[]);
+ static bool validChecksum(const uint8_t state[],
+ const uint16_t length = kGreeStateLength);
+ String toString(void);
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else // UNIT_TEST
+ IRsendTest _irsend;
+#endif // UNIT_TEST
+ // The state of the IR remote in IR code form.
+ uint8_t remote_state[kGreeStateLength];
+ gree_ac_remote_model_t _model;
+ void checksum(const uint16_t length = kGreeStateLength);
+ void fixup(void);
+ void setTimerEnabled(const bool on);
+ bool getTimerEnabled(void);
+};
+
+#endif // IR_GREE_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Haier.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Haier.cpp
similarity index 66%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Haier.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Haier.cpp
index f76bb3447..d2b947f9e 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Haier.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Haier.cpp
@@ -1,4 +1,5 @@
// Copyright 2018 crankyoldgit
+// Code to emulate Haier protocol compatible devices.
// The specifics of reverse engineering the protocols details:
// * HSU07-HEA03 by kuzin2006.
// * YR-W02/HSU-09HMC203 by non7top.
@@ -6,27 +7,19 @@
#include "ir_Haier.h"
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRutils.h"
-// HH HH AAA IIIII EEEEEEE RRRRRR
-// HH HH AAAAA III EE RR RR
-// HHHHHHH AA AA III EEEEE RRRRRR
-// HH HH AAAAAAA III EE RR RR
-// HH HH AA AA IIIII EEEEEEE RR RR
-
// Supported devices:
// * Haier HSU07-HEA03 Remote control.
// * Haier YR-W02 Remote control
// * Haier HSU-09HMC203 A/C unit.
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/404
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/404
// https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0
-// https://github.com/markszabo/IRremoteESP8266/issues/485
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/485
// https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods
// Constants
@@ -37,6 +30,14 @@ const uint16_t kHaierAcOneSpace = 1650;
const uint16_t kHaierAcZeroSpace = 650;
const uint32_t kHaierAcMinGap = 150000; // Completely made up value.
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addFanToString;
+using irutils::addTempToString;
+using irutils::minsToString;
+
#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02)
// Send a Haier A/C message. (HSU07-HEA03 remote)
//
@@ -47,8 +48,8 @@ const uint32_t kHaierAcMinGap = 150000; // Completely made up value.
//
// Status: STABLE / Known to be working.
//
-void IRsend::sendHaierAC(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
+void IRsend::sendHaierAC(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kHaierACStateLength) return;
for (uint16_t r = 0; r <= repeat; r++) {
@@ -74,16 +75,18 @@ void IRsend::sendHaierAC(unsigned char data[], uint16_t nbytes,
//
// Status: Alpha / Untested on a real device.
//
-void IRsend::sendHaierACYRW02(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
+void IRsend::sendHaierACYRW02(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes >= kHaierACYRW02StateLength) sendHaierAC(data, nbytes, repeat);
}
#endif // SEND_HAIER_AC_YRW02
// Class for emulating a Haier HSU07-HEA03 remote
-IRHaierAC::IRHaierAC(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRHaierAC::IRHaierAC(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
-void IRHaierAC::begin() { _irsend.begin(); }
+void IRHaierAC::begin(void) { _irsend.begin(); }
#if SEND_HAIER_AC
void IRHaierAC::send(const uint16_t repeat) {
@@ -92,7 +95,7 @@ void IRHaierAC::send(const uint16_t repeat) {
}
#endif // SEND_HAIER_AC
-void IRHaierAC::checksum() {
+void IRHaierAC::checksum(void) {
remote_state[8] = sumBytes(remote_state, kHaierACStateLength - 1);
}
@@ -101,13 +104,12 @@ bool IRHaierAC::validChecksum(uint8_t state[], const uint16_t length) {
return (state[length - 1] == sumBytes(state, length - 1));
}
-void IRHaierAC::stateReset() {
+void IRHaierAC::stateReset(void) {
for (uint8_t i = 1; i < kHaierACStateLength; i++) remote_state[i] = 0x0;
remote_state[0] = kHaierAcPrefix;
remote_state[2] = 0x20;
remote_state[4] = 0x0C;
remote_state[5] = 0xC0;
- remote_state[6] = 0x20;
setTemp(kHaierAcDefTemp);
setFan(kHaierAcFanAuto);
@@ -115,18 +117,18 @@ void IRHaierAC::stateReset() {
setCommand(kHaierAcCmdOn);
}
-uint8_t* IRHaierAC::getRaw() {
+uint8_t* IRHaierAC::getRaw(void) {
checksum();
return remote_state;
}
-void IRHaierAC::setRaw(uint8_t new_code[]) {
+void IRHaierAC::setRaw(const uint8_t new_code[]) {
for (uint8_t i = 0; i < kHaierACStateLength; i++) {
remote_state[i] = new_code[i];
}
}
-void IRHaierAC::setCommand(uint8_t state) {
+void IRHaierAC::setCommand(const uint8_t state) {
remote_state[1] &= 0b11110000;
switch (state) {
case kHaierAcCmdOff:
@@ -144,9 +146,9 @@ void IRHaierAC::setCommand(uint8_t state) {
}
}
-uint8_t IRHaierAC::getCommand() { return remote_state[1] & (0b00001111); }
+uint8_t IRHaierAC::getCommand(void) { return remote_state[1] & (0b00001111); }
-void IRHaierAC::setFan(uint8_t speed) {
+void IRHaierAC::setFan(const uint8_t speed) {
uint8_t new_speed = kHaierAcFanAuto;
switch (speed) {
case kHaierAcFanLow:
@@ -167,7 +169,7 @@ void IRHaierAC::setFan(uint8_t speed) {
remote_state[5] |= new_speed;
}
-uint8_t IRHaierAC::getFan() {
+uint8_t IRHaierAC::getFan(void) {
switch (remote_state[5] & 0b00000011) {
case 1:
return kHaierAcFanMed;
@@ -185,11 +187,13 @@ void IRHaierAC::setMode(uint8_t mode) {
setCommand(kHaierAcCmdMode);
if (mode > kHaierAcFan) // If out of range, default to auto mode.
new_mode = kHaierAcAuto;
- remote_state[7] &= 0b00011111;
- remote_state[7] |= (new_mode << 5);
+ remote_state[6] &= ~kHaierAcModeMask;
+ remote_state[6] |= (new_mode << 5);
}
-uint8_t IRHaierAC::getMode() { return (remote_state[7] & 0b11100000) >> 5; }
+uint8_t IRHaierAC::getMode(void) {
+ return (remote_state[6] & kHaierAcModeMask) >> 5;
+}
void IRHaierAC::setTemp(const uint8_t celsius) {
uint8_t temp = celsius;
@@ -209,45 +213,47 @@ void IRHaierAC::setTemp(const uint8_t celsius) {
remote_state[1] |= ((temp - kHaierAcMinTemp) << 4);
}
-uint8_t IRHaierAC::getTemp() {
+uint8_t IRHaierAC::getTemp(void) {
return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp;
}
-void IRHaierAC::setHealth(bool state) {
+void IRHaierAC::setHealth(const bool on) {
setCommand(kHaierAcCmdHealth);
remote_state[4] &= 0b11011111;
- remote_state[4] |= (state << 5);
+ remote_state[4] |= (on << 5);
}
bool IRHaierAC::getHealth(void) { return remote_state[4] & (1 << 5); }
-void IRHaierAC::setSleep(bool state) {
+void IRHaierAC::setSleep(const bool on) {
setCommand(kHaierAcCmdSleep);
- remote_state[7] &= 0b10111111;
- remote_state[7] |= (state << 6);
+ if (on)
+ remote_state[7] |= kHaierAcSleepBit;
+ else
+ remote_state[7] &= ~kHaierAcSleepBit;
}
-bool IRHaierAC::getSleep(void) { return remote_state[7] & 0b01000000; }
+bool IRHaierAC::getSleep(void) { return remote_state[7] & kHaierAcSleepBit; }
uint16_t IRHaierAC::getTime(const uint8_t ptr[]) {
return (ptr[0] & 0b00011111) * 60 + (ptr[1] & 0b00111111);
}
-int16_t IRHaierAC::getOnTimer() {
+int16_t IRHaierAC::getOnTimer(void) {
if (remote_state[3] & 0b10000000) // Check if the timer is turned on.
return getTime(remote_state + 6);
else
return -1;
}
-int16_t IRHaierAC::getOffTimer() {
+int16_t IRHaierAC::getOffTimer(void) {
if (remote_state[3] & 0b01000000) // Check if the timer is turned on.
return getTime(remote_state + 4);
else
return -1;
}
-uint16_t IRHaierAC::getCurrTime() { return getTime(remote_state + 2); }
+uint16_t IRHaierAC::getCurrTime(void) { return getTime(remote_state + 2); }
void IRHaierAC::setTime(uint8_t ptr[], const uint16_t nr_mins) {
uint16_t mins = nr_mins;
@@ -273,7 +279,7 @@ void IRHaierAC::setOffTimer(const uint16_t nr_mins) {
setTime(remote_state + 4, nr_mins);
}
-void IRHaierAC::cancelTimers() {
+void IRHaierAC::cancelTimers(void) {
setCommand(kHaierAcCmdTimerCancel);
remote_state[3] &= 0b00111111;
}
@@ -282,7 +288,9 @@ void IRHaierAC::setCurrTime(const uint16_t nr_mins) {
setTime(remote_state + 2, nr_mins);
}
-uint8_t IRHaierAC::getSwing() { return (remote_state[2] & 0b11000000) >> 6; }
+uint8_t IRHaierAC::getSwing(void) {
+ return (remote_state[2] & 0b11000000) >> 6;
+}
void IRHaierAC::setSwing(const uint8_t state) {
if (state == getSwing()) return; // Nothing to do.
@@ -298,23 +306,6 @@ void IRHaierAC::setSwing(const uint8_t state) {
}
}
-// Convert a Haier time into a human readable string.
-#ifdef ARDUINO
-String IRHaierAC::timeToString(const uint16_t nr_mins) {
- String result = "";
-#else
-std::string IRHaierAC::timeToString(const uint16_t nr_mins) {
- std::string result = "";
-#endif // ARDUINO
-
- if (nr_mins / 24 < 10) result += '0'; // Zero pad.
- result += uint64ToString(nr_mins / 60);
- result += ':';
- if (nr_mins % 60 < 10) result += '0'; // Zero pad.
- result += uint64ToString(nr_mins % 60);
- return result;
-}
-
// Convert a standard A/C mode into its native mode.
uint8_t IRHaierAC::convertMode(const stdAc::opmode_t mode) {
switch (mode) {
@@ -364,17 +355,69 @@ uint8_t IRHaierAC::convertSwingV(const stdAc::swingv_t position) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRHaierAC::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kHaierAcCool: return stdAc::opmode_t::kCool;
+ case kHaierAcHeat: return stdAc::opmode_t::kHeat;
+ case kHaierAcDry: return stdAc::opmode_t::kDry;
+ case kHaierAcFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRHaierAC::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kHaierAcFanHigh: return stdAc::fanspeed_t::kMax;
+ case kHaierAcFanMed: return stdAc::fanspeed_t::kMedium;
+ case kHaierAcFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingv_t IRHaierAC::toCommonSwingV(const uint8_t pos) {
+ switch (pos) {
+ case kHaierAcSwingUp: return stdAc::swingv_t::kHighest;
+ case kHaierAcSwingDown: return stdAc::swingv_t::kLowest;
+ case kHaierAcSwingOff: return stdAc::swingv_t::kOff;
+ default: return stdAc::swingv_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRHaierAC::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::HAIER_AC;
+ result.model = -1; // No models used.
+ result.power = true;
+ if (this->getCommand() == kHaierAcCmdOff) result.power = false;
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->toCommonSwingV(this->getSwing());
+ result.filter = this->getHealth();
+ result.sleep = this->getSleep() ? 0 : -1;
+ // Not supported.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.quiet = false;
+ result.turbo = false;
+ result.econo = false;
+ result.light = false;
+ result.clean = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRHaierAC::toString() {
+String IRHaierAC::toString(void) {
String result = "";
-#else
-std::string IRHaierAC::toString() {
- std::string result = "";
-#endif // ARDUINO
+ result.reserve(150); // Reserve some heap for the string to reduce fragging.
uint8_t cmd = getCommand();
- result += F("Command: ");
- result += uint64ToString(cmd);
+ result += addIntToString(cmd, F("Command"), false);
result += F(" (");
switch (cmd) {
case kHaierAcCmdOff:
@@ -414,41 +457,12 @@ std::string IRHaierAC::toString() {
result += F("Unknown");
}
result += ')';
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kHaierAcAuto:
- result += F(" (AUTO)");
- break;
- case kHaierAcCool:
- result += F(" (COOL)");
- break;
- case kHaierAcHeat:
- result += F(" (HEAT)");
- break;
- case kHaierAcDry:
- result += F(" (DRY)");
- break;
- case kHaierAcFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kHaierAcFanAuto:
- result += F(" (AUTO)");
- break;
- case kHaierAcFanHigh:
- result += F(" (MAX)");
- break;
- }
- result += F(", Swing: ");
- result += uint64ToString(getSwing());
+ result += addModeToString(getMode(), kHaierAcAuto, kHaierAcCool, kHaierAcHeat,
+ kHaierAcDry, kHaierAcFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kHaierAcFanHigh, kHaierAcFanLow,
+ kHaierAcFanAuto, kHaierAcFanAuto, kHaierAcFanMed);
+ result += addIntToString(getSwing(), F("Swing"));
result += F(" (");
switch (getSwing()) {
case kHaierAcSwingOff:
@@ -467,37 +481,24 @@ std::string IRHaierAC::toString() {
result += F("Unknown");
}
result += ')';
- result += F(", Sleep: ");
- if (getSleep())
- result += F("On");
- else
- result += F("Off");
- result += F(", Health: ");
- if (getHealth())
- result += F("On");
- else
- result += F("Off");
- result += F(", Current Time: ");
- result += timeToString(getCurrTime());
- result += F(", On Timer: ");
- if (getOnTimer() >= 0)
- result += timeToString(getOnTimer());
- else
- result += F("Off");
- result += F(", Off Timer: ");
- if (getOffTimer() >= 0)
- result += timeToString(getOffTimer());
- else
- result += F("Off");
-
+ result += addBoolToString(getSleep(), F("Sleep"));
+ result += addBoolToString(getHealth(), F("Health"));
+ result += addLabeledString(minsToString(getCurrTime()), F("Current Time"));
+ result += addLabeledString(
+ getOnTimer() >= 0 ? minsToString(getOnTimer()) : F("Off"), F("On Timer"));
+ result += addLabeledString(
+ getOffTimer() >= 0 ? minsToString(getOffTimer()) : F("Off"),
+ F("Off Timer"));
return result;
}
// End of IRHaierAC class.
// Class for emulating a Haier YRW02 remote
-IRHaierACYRW02::IRHaierACYRW02(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRHaierACYRW02::IRHaierACYRW02(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
-void IRHaierACYRW02::begin() { _irsend.begin(); }
+void IRHaierACYRW02::begin(void) { _irsend.begin(); }
#if SEND_HAIER_AC_YRW02
void IRHaierACYRW02::send(const uint16_t repeat) {
@@ -506,7 +507,7 @@ void IRHaierACYRW02::send(const uint16_t repeat) {
}
#endif // SEND_HAIER_AC_YRW02
-void IRHaierACYRW02::checksum() {
+void IRHaierACYRW02::checksum(void) {
remote_state[kHaierACYRW02StateLength - 1] =
sumBytes(remote_state, kHaierACYRW02StateLength - 1);
}
@@ -516,7 +517,7 @@ bool IRHaierACYRW02::validChecksum(uint8_t state[], const uint16_t length) {
return (state[length - 1] == sumBytes(state, length - 1));
}
-void IRHaierACYRW02::stateReset() {
+void IRHaierACYRW02::stateReset(void) {
for (uint8_t i = 1; i < kHaierACYRW02StateLength; i++) remote_state[i] = 0x0;
remote_state[0] = kHaierAcYrw02Prefix;
@@ -530,12 +531,12 @@ void IRHaierACYRW02::stateReset() {
setPower(true);
}
-uint8_t* IRHaierACYRW02::getRaw() {
+uint8_t* IRHaierACYRW02::getRaw(void) {
checksum();
return remote_state;
}
-void IRHaierACYRW02::setRaw(uint8_t new_code[]) {
+void IRHaierACYRW02::setRaw(const uint8_t new_code[]) {
for (uint8_t i = 0; i < kHaierACYRW02StateLength; i++) {
remote_state[i] = new_code[i];
}
@@ -557,7 +558,9 @@ void IRHaierACYRW02::setButton(uint8_t button) {
}
}
-uint8_t IRHaierACYRW02::getButton() { return remote_state[12] & (0b00001111); }
+uint8_t IRHaierACYRW02::getButton(void) {
+ return remote_state[12] & 0b00001111;
+}
void IRHaierACYRW02::setMode(uint8_t mode) {
uint8_t new_mode = mode;
@@ -576,10 +579,10 @@ void IRHaierACYRW02::setMode(uint8_t mode) {
remote_state[7] |= (new_mode << 4);
}
-uint8_t IRHaierACYRW02::getMode() { return remote_state[7] >> 4; }
+uint8_t IRHaierACYRW02::getMode(void) { return remote_state[7] >> 4; }
-void IRHaierACYRW02::setTemp(const uint8_t celcius) {
- uint8_t temp = celcius;
+void IRHaierACYRW02::setTemp(const uint8_t celsius) {
+ uint8_t temp = celsius;
if (temp < kHaierAcMinTemp)
temp = kHaierAcMinTemp;
else if (temp > kHaierAcMaxTemp)
@@ -596,43 +599,47 @@ void IRHaierACYRW02::setTemp(const uint8_t celcius) {
remote_state[1] |= ((temp - kHaierAcMinTemp) << 4);
}
-uint8_t IRHaierACYRW02::getTemp() {
+uint8_t IRHaierACYRW02::getTemp(void) {
return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp;
}
-void IRHaierACYRW02::setHealth(bool state) {
+void IRHaierACYRW02::setHealth(const bool on) {
setButton(kHaierAcYrw02ButtonHealth);
remote_state[3] &= 0b11111101;
- remote_state[3] |= (state << 1);
+ remote_state[3] |= (on << 1);
}
bool IRHaierACYRW02::getHealth(void) { return remote_state[3] & 0b00000010; }
-bool IRHaierACYRW02::getPower() { return remote_state[4] & kHaierAcYrw02Power; }
+bool IRHaierACYRW02::getPower(void) {
+ return remote_state[4] & kHaierAcYrw02Power;
+}
-void IRHaierACYRW02::setPower(bool state) {
+void IRHaierACYRW02::setPower(const bool on) {
setButton(kHaierAcYrw02ButtonPower);
- if (state)
+ if (on)
remote_state[4] |= kHaierAcYrw02Power;
else
remote_state[4] &= ~kHaierAcYrw02Power;
}
-void IRHaierACYRW02::on() { setPower(true); }
+void IRHaierACYRW02::on(void) { setPower(true); }
-void IRHaierACYRW02::off() { setPower(false); }
+void IRHaierACYRW02::off(void) { setPower(false); }
-bool IRHaierACYRW02::getSleep() { return remote_state[8] & kHaierAcYrw02Sleep; }
+bool IRHaierACYRW02::getSleep(void) {
+ return remote_state[8] & kHaierAcYrw02Sleep;
+}
-void IRHaierACYRW02::setSleep(bool state) {
+void IRHaierACYRW02::setSleep(const bool on) {
setButton(kHaierAcYrw02ButtonSleep);
- if (state)
+ if (on)
remote_state[8] |= kHaierAcYrw02Sleep;
else
remote_state[8] &= ~kHaierAcYrw02Sleep;
}
-uint8_t IRHaierACYRW02::getTurbo() { return remote_state[6] >> 6; }
+uint8_t IRHaierACYRW02::getTurbo(void) { return remote_state[6] >> 6; }
void IRHaierACYRW02::setTurbo(uint8_t speed) {
switch (speed) {
@@ -645,7 +652,7 @@ void IRHaierACYRW02::setTurbo(uint8_t speed) {
}
}
-uint8_t IRHaierACYRW02::getFan() { return remote_state[5] >> 4; }
+uint8_t IRHaierACYRW02::getFan(void) { return remote_state[5] >> 4; }
void IRHaierACYRW02::setFan(uint8_t speed) {
switch (speed) {
@@ -659,7 +666,7 @@ void IRHaierACYRW02::setFan(uint8_t speed) {
}
}
-uint8_t IRHaierACYRW02::getSwing() { return remote_state[1] & 0b00001111; }
+uint8_t IRHaierACYRW02::getSwing(void) { return remote_state[1] & 0b00001111; }
void IRHaierACYRW02::setSwing(uint8_t state) {
uint8_t newstate = state;
@@ -739,22 +746,71 @@ uint8_t IRHaierACYRW02::convertSwingV(const stdAc::swingv_t position) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRHaierACYRW02::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kHaierAcYrw02Cool: return stdAc::opmode_t::kCool;
+ case kHaierAcYrw02Heat: return stdAc::opmode_t::kHeat;
+ case kHaierAcYrw02Dry: return stdAc::opmode_t::kDry;
+ case kHaierAcYrw02Fan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRHaierACYRW02::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kHaierAcYrw02FanHigh: return stdAc::fanspeed_t::kMax;
+ case kHaierAcYrw02FanMed: return stdAc::fanspeed_t::kMedium;
+ case kHaierAcYrw02FanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingv_t IRHaierACYRW02::toCommonSwingV(const uint8_t pos) {
+ switch (pos) {
+ case kHaierAcYrw02SwingTop: return stdAc::swingv_t::kHighest;
+ case kHaierAcYrw02SwingMiddle: return stdAc::swingv_t::kMiddle;
+ case kHaierAcYrw02SwingDown: return stdAc::swingv_t::kLow;
+ case kHaierAcYrw02SwingBottom: return stdAc::swingv_t::kLowest;
+ case kHaierAcYrw02SwingOff: return stdAc::swingv_t::kOff;
+ default: return stdAc::swingv_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRHaierACYRW02::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::HAIER_AC_YRW02;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->toCommonSwingV(this->getSwing());
+ result.filter = this->getHealth();
+ result.sleep = this->getSleep() ? 0 : -1;
+ // Not supported.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.quiet = false;
+ result.turbo = false;
+ result.econo = false;
+ result.light = false;
+ result.clean = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRHaierACYRW02::toString() {
+String IRHaierACYRW02::toString(void) {
String result = "";
-#else
-std::string IRHaierACYRW02::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
+ result.reserve(130); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
uint8_t cmd = getButton();
- result += F(", Button: ");
- result += uint64ToString(cmd);
+ result += addIntToString(cmd, F("Button"));
result += F(" (");
switch (cmd) {
case kHaierAcYrw02ButtonPower:
@@ -788,49 +844,14 @@ std::string IRHaierACYRW02::toString() {
result += F("Unknown");
}
result += ')';
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kHaierAcYrw02Auto:
- result += F(" (Auto)");
- break;
- case kHaierAcYrw02Cool:
- result += F(" (Cool)");
- break;
- case kHaierAcYrw02Heat:
- result += F(" (Heat)");
- break;
- case kHaierAcYrw02Dry:
- result += F(" (Dry)");
- break;
- case kHaierAcYrw02Fan:
- result += F(" (Fan)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kHaierAcYrw02FanAuto:
- result += F(" (Auto)");
- break;
- case kHaierAcYrw02FanHigh:
- result += F(" (High)");
- break;
- case kHaierAcYrw02FanLow:
- result += F(" (Low)");
- break;
- case kHaierAcYrw02FanMed:
- result += F(" (Med)");
- break;
- default:
- result += F(" (Unknown)");
- }
- result += F(", Turbo: ");
- result += uint64ToString(getTurbo());
+ result += addModeToString(getMode(), kHaierAcYrw02Auto, kHaierAcYrw02Cool,
+ kHaierAcYrw02Heat, kHaierAcYrw02Dry,
+ kHaierAcYrw02Fan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kHaierAcYrw02FanHigh, kHaierAcYrw02FanLow,
+ kHaierAcYrw02FanAuto, kHaierAcYrw02FanAuto,
+ kHaierAcYrw02FanMed);
+ result += addIntToString(getTurbo(), F("Turbo"));
result += F(" (");
switch (getTurbo()) {
case kHaierAcYrw02TurboOff:
@@ -846,8 +867,7 @@ std::string IRHaierACYRW02::toString() {
result += F("Unknown");
}
result += ')';
- result += F(", Swing: ");
- result += uint64ToString(getSwing());
+ result += addIntToString(getSwing(), F("Swing"));
result += F(" (");
switch (getSwing()) {
case kHaierAcYrw02SwingOff:
@@ -872,17 +892,8 @@ std::string IRHaierACYRW02::toString() {
result += F("Unknown");
}
result += ')';
- result += F(", Sleep: ");
- if (getSleep())
- result += F("On");
- else
- result += F("Off");
- result += F(", Health: ");
- if (getHealth())
- result += F("On");
- else
- result += F("Off");
-
+ result += addBoolToString(getSleep(), F("Sleep"));
+ result += addBoolToString(getHealth(), F("Health"));
return result;
}
// End of IRHaierACYRW02 class.
@@ -901,9 +912,6 @@ std::string IRHaierACYRW02::toString() {
//
bool IRrecv::decodeHaierAC(decode_results* results, uint16_t nbits,
bool strict) {
- if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte.
- return false;
-
if (strict) {
if (nbits != kHaierACBits)
return false; // Not strictly a HAIER_AC message.
@@ -914,27 +922,18 @@ bool IRrecv::decodeHaierAC(decode_results* results, uint16_t nbits,
uint16_t offset = kStartOffset;
- // Header
+ // Pre-Header
if (!matchMark(results->rawbuf[offset++], kHaierAcHdr)) return false;
if (!matchSpace(results->rawbuf[offset++], kHaierAcHdr)) return false;
- if (!matchMark(results->rawbuf[offset++], kHaierAcHdr)) return false;
- if (!matchSpace(results->rawbuf[offset++], kHaierAcHdrGap)) return false;
- // Data
- for (uint16_t i = 0; i < nbits / 8; i++) {
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), 8, kHaierAcBitMark,
- kHaierAcOneSpace, kHaierAcBitMark, kHaierAcZeroSpace);
- if (data_result.success == false) return false;
- offset += data_result.used;
- results->state[i] = (uint8_t)data_result.data;
- }
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kHaierAcBitMark)) return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kHaierAcMinGap))
- return false;
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kHaierAcHdr, kHaierAcHdrGap,
+ kHaierAcBitMark, kHaierAcOneSpace,
+ kHaierAcBitMark, kHaierAcZeroSpace,
+ kHaierAcBitMark, kHaierAcMinGap, true,
+ _tolerance, kMarkExcess)) return false;
// Compliance
if (strict) {
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Haier.h b/lib/IRremoteESP8266-2.6.5/src/ir_Haier.h
similarity index 78%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Haier.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Haier.h
index 8f7b35196..ea5f67ab3 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Haier.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Haier.h
@@ -1,13 +1,16 @@
// Copyright 2018 crankyoldgit
// The specifics of reverse engineering the protocol details by kuzin2006
+// Supports:
+// Brand: Haier, Model: HSU07-HEA03 remote
+// Brand: Haier, Model: YR-W02 remote
+// Brand: Haier, Model: HSU-09HMC203 A/C
+
#ifndef IR_HAIER_H_
#define IR_HAIER_H_
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -15,16 +18,10 @@
#include "IRsend_test.h"
#endif
-// HH HH AAA IIIII EEEEEEE RRRRRR
-// HH HH AAAAA III EE RR RR
-// HHHHHHH AA AA III EEEEE RRRRRR
-// HH HH AAAAAAA III EE RR RR
-// HH HH AA AA IIIII EEEEEEE RR RR
-
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/404
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/404
// https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0
-// https://github.com/markszabo/IRremoteESP8266/issues/485
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/485
// https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods
// Constants
@@ -56,6 +53,7 @@ const uint8_t kHaierAcSwingDown = 0b00000010;
const uint8_t kHaierAcSwingChg = 0b00000011;
// Byte 6
+const uint8_t kHaierAcModeMask = 0b11100000;
const uint8_t kHaierAcAuto = 0;
const uint8_t kHaierAcCool = 1;
const uint8_t kHaierAcDry = 2;
@@ -69,6 +67,9 @@ const uint8_t kHaierAcFanHigh = 3;
const uint16_t kHaierAcMaxTime = (23 * 60) + 59;
+// Byte 7
+const uint8_t kHaierAcSleepBit = 0b01000000;
+
// Legacy Haier AC defines.
#define HAIER_AC_MIN_TEMP kHaierAcMinTemp
#define HAIER_AC_DEF_TEMP kHaierAcDefTemp
@@ -186,57 +187,56 @@ const uint8_t kHaierAcYrw02ButtonSleep = 0xB;
class IRHaierAC {
public:
- explicit IRHaierAC(uint16_t pin);
+ explicit IRHaierAC(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
#if SEND_HAIER_AC
void send(const uint16_t repeat = kHaierAcDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_HAIER_AC
- void begin();
+ void begin(void);
void setCommand(const uint8_t command);
- uint8_t getCommand();
+ uint8_t getCommand(void);
void setTemp(const uint8_t temp);
- uint8_t getTemp();
+ uint8_t getTemp(void);
void setFan(const uint8_t speed);
- uint8_t getFan();
+ uint8_t getFan(void);
- uint8_t getMode();
+ uint8_t getMode(void);
void setMode(const uint8_t mode);
- bool getSleep();
- void setSleep(const bool state);
- bool getHealth();
- void setHealth(const bool state);
+ bool getSleep(void);
+ void setSleep(const bool on);
+ bool getHealth(void);
+ void setHealth(const bool on);
- int16_t getOnTimer();
+ int16_t getOnTimer(void);
void setOnTimer(const uint16_t mins);
- int16_t getOffTimer();
+ int16_t getOffTimer(void);
void setOffTimer(const uint16_t mins);
- void cancelTimers();
+ void cancelTimers(void);
- uint16_t getCurrTime();
+ uint16_t getCurrTime(void);
void setCurrTime(const uint16_t mins);
- uint8_t getSwing();
+ uint8_t getSwing(void);
void setSwing(const uint8_t state);
- uint8_t* getRaw();
- void setRaw(uint8_t new_code[]);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t new_code[]);
static bool validChecksum(uint8_t state[],
const uint16_t length = kHaierACStateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
uint8_t convertSwingV(const stdAc::swingv_t position);
-
-#ifdef ARDUINO
- String toString();
- static String timeToString(const uint16_t nr_mins);
-#else
- std::string toString();
- static std::string timeToString(const uint16_t nr_mins);
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ static stdAc::swingv_t toCommonSwingV(const uint8_t pos);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -245,61 +245,62 @@ class IRHaierAC {
IRsendTest _irsend;
#endif
uint8_t remote_state[kHaierACStateLength];
- void stateReset();
- void checksum();
+ void stateReset(void);
+ void checksum(void);
static uint16_t getTime(const uint8_t ptr[]);
static void setTime(uint8_t ptr[], const uint16_t nr_mins);
};
class IRHaierACYRW02 {
public:
- explicit IRHaierACYRW02(uint16_t pin);
+ explicit IRHaierACYRW02(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
#if SEND_HAIER_AC_YRW02
void send(const uint16_t repeat = kHaierAcYrw02DefaultRepeat);
#endif // SEND_HAIER_AC_YRW02
- void begin();
+ void begin(void);
void setButton(const uint8_t button);
- uint8_t getButton();
+ uint8_t getButton(void);
void setTemp(const uint8_t temp);
- uint8_t getTemp();
+ uint8_t getTemp(void);
void setFan(const uint8_t speed);
- uint8_t getFan();
+ uint8_t getFan(void);
- uint8_t getMode();
+ uint8_t getMode(void);
void setMode(const uint8_t mode);
- bool getPower();
- void setPower(const bool state);
- void on();
- void off();
+ bool getPower(void);
+ void setPower(const bool on);
+ void on(void);
+ void off(void);
- bool getSleep();
- void setSleep(const bool state);
- bool getHealth();
- void setHealth(const bool state);
+ bool getSleep(void);
+ void setSleep(const bool on);
+ bool getHealth(void);
+ void setHealth(const bool on);
- uint8_t getTurbo();
+ uint8_t getTurbo(void);
void setTurbo(const uint8_t speed);
- uint8_t getSwing();
+ uint8_t getSwing(void);
void setSwing(const uint8_t state);
- uint8_t* getRaw();
- void setRaw(uint8_t new_code[]);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t new_code[]);
static bool validChecksum(uint8_t state[],
const uint16_t length = kHaierACYRW02StateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
uint8_t convertSwingV(const stdAc::swingv_t position);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ static stdAc::swingv_t toCommonSwingV(const uint8_t pos);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -308,8 +309,8 @@ class IRHaierACYRW02 {
IRsendTest _irsend;
#endif
uint8_t remote_state[kHaierACYRW02StateLength];
- void stateReset();
- void checksum();
+ void stateReset(void);
+ void checksum(void);
};
#endif // IR_HAIER_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.cpp
similarity index 63%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.cpp
index b88189f4a..0550816a9 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.cpp
@@ -15,14 +15,8 @@
#include "IRsend.h"
#include "IRutils.h"
-// HH HH IIIII TTTTTTT AAA CCCCC HH HH IIIII
-// HH HH III TTT AAAAA CC C HH HH III
-// HHHHHHH III TTT AA AA CC HHHHHHH III
-// HH HH III TTT AAAAAAA CC C HH HH III
-// HH HH IIIII TTT AA AA CCCCC HH HH IIIII
-
// Constants
-// Ref: https://github.com/markszabo/IRremoteESP8266/issues/417
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/417
const uint16_t kHitachiAcHdrMark = 3300;
const uint16_t kHitachiAcHdrSpace = 1700;
const uint16_t kHitachiAc1HdrMark = 3400;
@@ -32,6 +26,13 @@ const uint16_t kHitachiAcOneSpace = 1250;
const uint16_t kHitachiAcZeroSpace = 500;
const uint32_t kHitachiAcMinGap = kDefaultMessageGap; // Just a guess.
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addFanToString;
+using irutils::addTempToString;
+
#if (SEND_HITACHI_AC || SEND_HITACHI_AC2)
// Send a Hitachi A/C message.
//
@@ -43,9 +44,9 @@ const uint32_t kHitachiAcMinGap = kDefaultMessageGap; // Just a guess.
// Status: ALPHA / Untested.
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/417
-void IRsend::sendHitachiAC(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/417
+void IRsend::sendHitachiAC(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kHitachiAcStateLength)
return; // Not enough bytes to send a proper message.
sendGeneric(kHitachiAcHdrMark, kHitachiAcHdrSpace, kHitachiAcBitMark,
@@ -69,10 +70,10 @@ void IRsend::sendHitachiAC(unsigned char data[], uint16_t nbytes,
// Status: BETA / Appears to work.
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/453
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/453
// Basically the same as sendHitatchiAC() except different size and header.
-void IRsend::sendHitachiAC1(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
+void IRsend::sendHitachiAC1(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kHitachiAc1StateLength)
return; // Not enough bytes to send a proper message.
sendGeneric(kHitachiAc1HdrMark, kHitachiAc1HdrSpace, kHitachiAcBitMark,
@@ -96,10 +97,10 @@ void IRsend::sendHitachiAC1(unsigned char data[], uint16_t nbytes,
// Status: BETA / Appears to work.
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/417
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/417
// Basically the same as sendHitatchiAC() except different size.
-void IRsend::sendHitachiAC2(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
+void IRsend::sendHitachiAC2(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kHitachiAc2StateLength)
return; // Not enough bytes to send a proper message.
sendHitachiAC(data, nbytes, repeat);
@@ -110,9 +111,11 @@ void IRsend::sendHitachiAC2(unsigned char data[], uint16_t nbytes,
// Inspired by:
// https://github.com/ToniA/arduino-heatpumpir/blob/master/HitachiHeatpumpIR.cpp
-IRHitachiAc::IRHitachiAc(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRHitachiAc::IRHitachiAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
-void IRHitachiAc::stateReset() {
+void IRHitachiAc::stateReset(void) {
remote_state[0] = 0x80;
remote_state[1] = 0x08;
remote_state[2] = 0x0C;
@@ -130,7 +133,7 @@ void IRHitachiAc::stateReset() {
setTemp(23);
}
-void IRHitachiAc::begin() { _irsend.begin(); }
+void IRHitachiAc::begin(void) { _irsend.begin(); }
uint8_t IRHitachiAc::calcChecksum(const uint8_t state[],
const uint16_t length) {
@@ -148,7 +151,7 @@ bool IRHitachiAc::validChecksum(const uint8_t state[], const uint16_t length) {
return (state[length - 1] == calcChecksum(state, length));
}
-uint8_t *IRHitachiAc::getRaw() {
+uint8_t *IRHitachiAc::getRaw(void) {
checksum();
return remote_state;
}
@@ -165,7 +168,7 @@ void IRHitachiAc::send(const uint16_t repeat) {
}
#endif // SEND_HITACHI_AC
-bool IRHitachiAc::getPower() { return (remote_state[17] & 0x01); }
+bool IRHitachiAc::getPower(void) { return (remote_state[17] & 0x01); }
void IRHitachiAc::setPower(const bool on) {
if (on)
@@ -174,11 +177,11 @@ void IRHitachiAc::setPower(const bool on) {
remote_state[17] &= 0xFE;
}
-void IRHitachiAc::on() { setPower(true); }
+void IRHitachiAc::on(void) { setPower(true); }
-void IRHitachiAc::off() { setPower(false); }
+void IRHitachiAc::off(void) { setPower(false); }
-uint8_t IRHitachiAc::getMode() { return reverseBits(remote_state[10], 8); }
+uint8_t IRHitachiAc::getMode(void) { return reverseBits(remote_state[10], 8); }
void IRHitachiAc::setMode(const uint8_t mode) {
uint8_t newmode = mode;
@@ -200,7 +203,9 @@ void IRHitachiAc::setMode(const uint8_t mode) {
setFan(getFan()); // Reset the fan speed after the mode change.
}
-uint8_t IRHitachiAc::getTemp() { return reverseBits(remote_state[11], 8) >> 1; }
+uint8_t IRHitachiAc::getTemp(void) {
+ return reverseBits(remote_state[11], 8) >> 1;
+}
void IRHitachiAc::setTemp(const uint8_t celsius) {
uint8_t temp;
@@ -220,7 +225,7 @@ void IRHitachiAc::setTemp(const uint8_t celsius) {
remote_state[9] = 0x10;
}
-uint8_t IRHitachiAc::getFan() { return reverseBits(remote_state[13], 8); }
+uint8_t IRHitachiAc::getFan(void) { return reverseBits(remote_state[13], 8); }
void IRHitachiAc::setFan(const uint8_t speed) {
uint8_t fanmin = kHitachiAcFanAuto;
@@ -239,7 +244,7 @@ void IRHitachiAc::setFan(const uint8_t speed) {
remote_state[13] = reverseBits(newspeed, 8);
}
-bool IRHitachiAc::getSwingVertical() { return remote_state[14] & 0x80; }
+bool IRHitachiAc::getSwingVertical(void) { return remote_state[14] & 0x80; }
void IRHitachiAc::setSwingVertical(const bool on) {
if (on)
@@ -248,7 +253,7 @@ void IRHitachiAc::setSwingVertical(const bool on) {
remote_state[14] &= 0x7F;
}
-bool IRHitachiAc::getSwingHorizontal() { return remote_state[15] & 0x80; }
+bool IRHitachiAc::getSwingHorizontal(void) { return remote_state[15] & 0x80; }
void IRHitachiAc::setSwingHorizontal(const bool on) {
if (on)
@@ -291,68 +296,68 @@ uint8_t IRHitachiAc::convertFan(const stdAc::fanspeed_t speed) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRHitachiAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kHitachiAcCool: return stdAc::opmode_t::kCool;
+ case kHitachiAcHeat: return stdAc::opmode_t::kHeat;
+ case kHitachiAcDry: return stdAc::opmode_t::kDry;
+ case kHitachiAcFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRHitachiAc::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kHitachiAcFanHigh: return stdAc::fanspeed_t::kMax;
+ case kHitachiAcFanHigh - 1: return stdAc::fanspeed_t::kHigh;
+ case kHitachiAcFanLow + 1: return stdAc::fanspeed_t::kMedium;
+ case kHitachiAcFanLow: return stdAc::fanspeed_t::kLow;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRHitachiAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::HITACHI_AC;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwingVertical() ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.swingh = this->getSwingHorizontal() ? stdAc::swingh_t::kAuto :
+ stdAc::swingh_t::kOff;
+ // Not supported.
+ result.quiet = false;
+ result.turbo = false;
+ result.clean = false;
+ result.econo = false;
+ result.filter = false;
+ result.light = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRHitachiAc::toString() {
+String IRHitachiAc::toString(void) {
String result = "";
-#else
-std::string IRHitachiAc::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kHitachiAcAuto:
- result += F(" (AUTO)");
- break;
- case kHitachiAcCool:
- result += F(" (COOL)");
- break;
- case kHitachiAcHeat:
- result += F(" (HEAT)");
- break;
- case kHitachiAcDry:
- result += F(" (DRY)");
- break;
- case kHitachiAcFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kHitachiAcFanAuto:
- result += F(" (AUTO)");
- break;
- case kHitachiAcFanLow:
- result += F(" (LOW)");
- break;
- case kHitachiAcFanHigh:
- result += F(" (HIGH)");
- break;
- default:
- result += F(" (UNKNOWN)");
- break;
- }
- result += F(", Swing (Vertical): ");
- if (getSwingVertical())
- result += F("On");
- else
- result += F("Off");
- result += F(", Swing (Horizontal): ");
- if (getSwingHorizontal())
- result += F("On");
- else
- result += F("Off");
+ result.reserve(110); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kHitachiAcAuto, kHitachiAcCool,
+ kHitachiAcHeat, kHitachiAcDry, kHitachiAcFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kHitachiAcFanHigh, kHitachiAcFanLow,
+ kHitachiAcFanAuto, kHitachiAcFanAuto,
+ kHitachiAcFanMed);
+ result += addBoolToString(getSwingVertical(), F("Swing (Vertical)"));
+ result += addBoolToString(getSwingHorizontal(), F("Swing (Horizontal)"));
return result;
}
@@ -373,11 +378,11 @@ std::string IRHitachiAc::toString() {
// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/417
-// https://github.com/markszabo/IRremoteESP8266/issues/453
-bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t nbits,
- bool strict) {
- const uint8_t kTolerance = 30;
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/417
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/453
+bool IRrecv::decodeHitachiAC(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ const uint8_t k_tolerance = _tolerance + 5;
if (results->rawlen < 2 * nbits + kHeader + kFooter - 1)
return false; // Can't possibly be a valid HitachiAC message.
if (strict) {
@@ -391,57 +396,33 @@ bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t nbits,
}
}
uint16_t offset = kStartOffset;
- uint16_t dataBitsSoFar = 0;
- match_result_t data_result;
-
- // Header
+ uint16_t hmark;
+ uint32_t hspace;
if (nbits == kHitachiAc1Bits) {
- if (!matchMark(results->rawbuf[offset++], kHitachiAc1HdrMark, kTolerance))
- return false;
- if (!matchSpace(results->rawbuf[offset++], kHitachiAc1HdrSpace, kTolerance))
- return false;
- } else { // Everything else.
- if (!matchMark(results->rawbuf[offset++], kHitachiAcHdrMark, kTolerance))
- return false;
- if (!matchSpace(results->rawbuf[offset++], kHitachiAcHdrSpace, kTolerance))
- return false;
+ hmark = kHitachiAc1HdrMark;
+ hspace = kHitachiAc1HdrSpace;
+ } else {
+ hmark = kHitachiAcHdrMark;
+ hspace = kHitachiAcHdrSpace;
}
- // Data
- // Keep reading bytes until we either run out of message or state to fill.
- for (uint16_t i = 0; offset <= results->rawlen - 16 && i < nbits / 8;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- data_result = matchData(&(results->rawbuf[offset]), 8, kHitachiAcBitMark,
- kHitachiAcOneSpace, kHitachiAcBitMark,
- kHitachiAcZeroSpace, kTolerance);
- if (data_result.success == false) break; // Fail
- results->state[i] = (uint8_t)data_result.data;
- }
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kHitachiAcBitMark, kTolerance))
- return false;
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kHitachiAcMinGap, kTolerance))
- return false;
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ hmark, hspace,
+ kHitachiAcBitMark, kHitachiAcOneSpace,
+ kHitachiAcBitMark, kHitachiAcZeroSpace,
+ kHitachiAcBitMark, kHitachiAcMinGap, true,
+ k_tolerance)) return false;
// Compliance
if (strict) {
- // Re-check we got the correct size/length due to the way we read the data.
- switch (dataBitsSoFar / 8) {
- case kHitachiAcStateLength:
- case kHitachiAc1StateLength:
- case kHitachiAc2StateLength:
- break; // Continue
- default:
- return false;
- }
- if (dataBitsSoFar / 8 == kHitachiAcStateLength &&
+ if (nbits / 8 == kHitachiAcStateLength &&
!IRHitachiAc::validChecksum(results->state, kHitachiAcStateLength))
return false;
}
// Success
- switch (dataBitsSoFar) {
+ switch (nbits) {
case kHitachiAc1Bits:
results->decode_type = HITACHI_AC1;
break;
@@ -452,7 +433,7 @@ bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t nbits,
default:
results->decode_type = HITACHI_AC;
}
- results->bits = dataBitsSoFar;
+ results->bits = nbits;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.h b/lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.h
similarity index 68%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.h
index 532717447..b9bfd391c 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.h
@@ -2,6 +2,11 @@
//
// Copyright 2018 David Conran
+// Supports:
+// Brand: Hitachi, Model: RAS-35THA6 remote
+// Brand: Hitachi, Model: LT0541-HTA remote
+// Brand: Hitachi, Model: Series VI A/C (Circa 2007)
+
#ifndef IR_HITACHI_H_
#define IR_HITACHI_H_
@@ -9,8 +14,6 @@
#include
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -26,6 +29,7 @@ const uint8_t kHitachiAcDry = 5;
const uint8_t kHitachiAcFan = 0xC;
const uint8_t kHitachiAcFanAuto = 1;
const uint8_t kHitachiAcFanLow = 2;
+const uint8_t kHitachiAcFanMed = 3;
const uint8_t kHitachiAcFanHigh = 5;
const uint8_t kHitachiAcMinTemp = 16; // 16C
const uint8_t kHitachiAcMaxTemp = 32; // 32C
@@ -34,28 +38,30 @@ const uint8_t kHitachiAcAutoTemp = 23; // 23C
// Classes
class IRHitachiAc {
public:
- explicit IRHitachiAc(uint16_t pin);
+ explicit IRHitachiAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
- void stateReset();
+ void stateReset(void);
#if SEND_HITACHI_AC
void send(const uint16_t repeat = kHitachiAcDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_HITACHI_AC
- void begin();
- void on();
- void off();
+ void begin(void);
+ void on(void);
+ void off(void);
void setPower(const bool on);
- bool getPower();
+ bool getPower(void);
void setTemp(const uint8_t temp);
- uint8_t getTemp();
+ uint8_t getTemp(void);
void setFan(const uint8_t speed);
- uint8_t getFan();
+ uint8_t getFan(void);
void setMode(const uint8_t mode);
- uint8_t getMode();
+ uint8_t getMode(void);
void setSwingVertical(const bool on);
- bool getSwingVertical();
+ bool getSwingVertical(void);
void setSwingHorizontal(const bool on);
- bool getSwingHorizontal();
- uint8_t* getRaw();
+ bool getSwingHorizontal(void);
+ uint8_t* getRaw(void);
void setRaw(const uint8_t new_code[],
const uint16_t length = kHitachiAcStateLength);
static bool validChecksum(const uint8_t state[],
@@ -64,11 +70,10 @@ class IRHitachiAc {
const uint16_t length = kHitachiAcStateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Inax.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Inax.cpp
new file mode 100644
index 000000000..073580fae
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Inax.cpp
@@ -0,0 +1,83 @@
+// Copyright 2019 David Conran (crankyoldgit)
+// Support for an IR controlled Robot Toilet
+
+#include
+#include "IRrecv.h"
+#include "IRsend.h"
+#include "IRutils.h"
+
+// Supports:
+// Brand: Lixil, Model: Inax DT-BA283 Toilet
+
+// Documentation:
+// https://www.lixil-manual.com/GCW-1365-16050/GCW-1365-16050.pdf
+
+// Constants
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/706
+const uint16_t kInaxTick = 500;
+const uint16_t kInaxHdrMark = 9000;
+const uint16_t kInaxHdrSpace = 4500;
+const uint16_t kInaxBitMark = 560;
+const uint16_t kInaxOneSpace = 1675;
+const uint16_t kInaxZeroSpace = kInaxBitMark;
+const uint16_t kInaxMinGap = 40000;
+
+#if SEND_INAX
+// Send a Inax Toilet formatted message.
+//
+// Args:
+// data: The message to be sent.
+// nbits: The bit size of the message being sent. typically kInaxBits.
+// repeat: The number of times the message is to be repeated.
+//
+// Status: BETA / Should be working.
+//
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/706
+void IRsend::sendInax(const uint64_t data, const uint16_t nbits,
+ const uint16_t repeat) {
+ sendGeneric(kInaxHdrMark, kInaxHdrSpace,
+ kInaxBitMark, kInaxOneSpace,
+ kInaxBitMark, kInaxZeroSpace,
+ kInaxBitMark, kInaxMinGap,
+ data, nbits, 38, true, repeat, kDutyDefault);
+}
+#endif
+
+#if DECODE_INAX
+// Decode the supplied Inax Toilet message.
+//
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion.
+// Typically kInaxBits.
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: Stable / Known working.
+//
+bool IRrecv::decodeInax(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ if (strict && nbits != kInaxBits)
+ return false; // We expect Inax to be a certain sized message.
+
+ uint64_t data = 0;
+ uint16_t offset = kStartOffset;
+
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kInaxHdrMark, kInaxHdrSpace,
+ kInaxBitMark, kInaxOneSpace,
+ kInaxBitMark, kInaxZeroSpace,
+ kInaxBitMark, kInaxMinGap, true)) return false;
+ // Success
+ results->bits = nbits;
+ results->value = data;
+ results->decode_type = INAX;
+ results->command = 0;
+ results->address = 0;
+ return true;
+}
+#endif
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_JVC.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_JVC.cpp
similarity index 78%
rename from lib/IRremoteESP8266-2.6.0/src/ir_JVC.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_JVC.cpp
index 47df29dc4..7038e9d3e 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_JVC.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_JVC.cpp
@@ -7,12 +7,6 @@
#include "IRtimer.h"
#include "IRutils.h"
-// JJJJJ V V CCCC
-// J V V C
-// J V V C
-// J J V V C
-// J V CCCC
-
// JVC originally added by Kristian Lauszus
// (Thanks to zenwheel and other people at the original blog post)
@@ -119,40 +113,23 @@ bool IRrecv::decodeJVC(decode_results *results, uint16_t nbits, bool strict) {
uint16_t offset = kStartOffset;
bool isRepeat = true;
- uint32_t m_tick;
- uint32_t s_tick;
// Header
// (Optional as repeat codes don't have the header)
if (matchMark(results->rawbuf[offset], kJvcHdrMark)) {
isRepeat = false;
- m_tick = results->rawbuf[offset++] * kRawTick / kJvcHdrMarkTicks;
+ offset++;
if (results->rawlen < 2 * nbits + 4)
return false; // Can't possibly be a valid JVC message with a header.
- if (!matchSpace(results->rawbuf[offset], kJvcHdrSpace)) return false;
- s_tick = results->rawbuf[offset++] * kRawTick / kJvcHdrSpaceTicks;
- } else {
- // We can't easily auto-calibrate as there is no header, so assume
- // the default tick time.
- m_tick = kJvcTick;
- s_tick = kJvcTick;
+ if (!matchSpace(results->rawbuf[offset++], kJvcHdrSpace)) return false;
}
- // Data
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits, kJvcBitMarkTicks * m_tick,
- kJvcOneSpaceTicks * s_tick, kJvcBitMarkTicks * m_tick,
- kJvcZeroSpaceTicks * s_tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kJvcBitMarkTicks * m_tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kJvcMinGapTicks * s_tick))
- return false;
-
+ // Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ 0, 0,
+ kJvcBitMark, kJvcOneSpace,
+ kJvcBitMark, kJvcZeroSpace,
+ kJvcBitMark, kJvcMinGap, true)) return false;
// Success
results->decode_type = JVC;
results->bits = nbits;
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.cpp
similarity index 58%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.cpp
index c69f4cb8a..0af521b15 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.cpp
@@ -24,12 +24,6 @@
#include "IRsend.h"
#include "IRutils.h"
-// KK KK EEEEEEE LL VV VV IIIII NN NN AAA TTTTTTT OOOOO RRRRRR
-// KK KK EE LL VV VV III NNN NN AAAAA TTT OO OO RR RR
-// KKKK EEEEE LL VV VV III NN N NN AA AA TTT OO OO RRRRRR
-// KK KK EE LL VV VV III NN NNN AAAAAAA TTT OO OO RR RR
-// KK KK EEEEEEE LLLLLLL VVV IIIII NN NN AA AA TTT OOOO0 RR RR
-
// Constants
const uint16_t kKelvinatorTick = 85;
@@ -72,6 +66,13 @@ const uint8_t kKelvinatorXfan = 1 << kKelvinatorXfanOffset;
const uint8_t kKelvinatorTurboOffset = 4;
const uint8_t kKelvinatorTurbo = 1 << kKelvinatorTurboOffset;
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addFanToString;
+using irutils::addTempToString;
+
#if SEND_KELVINATOR
// Send a Kelvinator A/C message.
//
@@ -82,8 +83,8 @@ const uint8_t kKelvinatorTurbo = 1 << kKelvinatorTurboOffset;
//
// Status: STABLE / Known working.
//
-void IRsend::sendKelvinator(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
+void IRsend::sendKelvinator(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kKelvinatorStateLength)
return; // Not enough bytes to send a proper message.
@@ -124,36 +125,38 @@ void IRsend::sendKelvinator(unsigned char data[], uint16_t nbytes,
}
#endif // SEND_KELVINATOR
-IRKelvinatorAC::IRKelvinatorAC(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRKelvinatorAC::IRKelvinatorAC(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
-void IRKelvinatorAC::stateReset() {
+void IRKelvinatorAC::stateReset(void) {
for (uint8_t i = 0; i < kKelvinatorStateLength; i++) remote_state[i] = 0x0;
remote_state[3] = 0x50;
remote_state[11] = 0x70;
}
-void IRKelvinatorAC::begin() { _irsend.begin(); }
+void IRKelvinatorAC::begin(void) { _irsend.begin(); }
-void IRKelvinatorAC::fixup() {
+void IRKelvinatorAC::fixup(void) {
// X-Fan mode is only valid in COOL or DRY modes.
- if (getMode() != kKelvinatorCool && getMode() != kKelvinatorDry)
- setXFan(false);
- checksum(); // Calculate the checksums
+ if (this->getMode() != kKelvinatorCool && this->getMode() != kKelvinatorDry)
+ this->setXFan(false);
+ this->checksum(); // Calculate the checksums
}
#if SEND_KELVINATOR
void IRKelvinatorAC::send(const uint16_t repeat) {
- fixup(); // Ensure correct settings before sending.
+ this->fixup(); // Ensure correct settings before sending.
_irsend.sendKelvinator(remote_state, kKelvinatorStateLength, repeat);
}
#endif // SEND_KELVINATOR
-uint8_t *IRKelvinatorAC::getRaw() {
- fixup(); // Ensure correct settings before sending.
+uint8_t *IRKelvinatorAC::getRaw(void) {
+ this->fixup(); // Ensure correct settings before sending.
return remote_state;
}
-void IRKelvinatorAC::setRaw(uint8_t new_code[]) {
+void IRKelvinatorAC::setRaw(const uint8_t new_code[]) {
for (uint8_t i = 0; i < kKelvinatorStateLength; i++) {
remote_state[i] = new_code[i];
}
@@ -196,46 +199,46 @@ bool IRKelvinatorAC::validChecksum(const uint8_t state[],
return true;
}
-void IRKelvinatorAC::on() {
+void IRKelvinatorAC::on(void) {
remote_state[0] |= kKelvinatorPower;
remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
}
-void IRKelvinatorAC::off() {
+void IRKelvinatorAC::off(void) {
remote_state[0] &= ~kKelvinatorPower;
remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
}
-void IRKelvinatorAC::setPower(bool state) {
- if (state)
- on();
+void IRKelvinatorAC::setPower(const bool on) {
+ if (on)
+ this->on();
else
- off();
+ this->off();
}
-bool IRKelvinatorAC::getPower() {
- return ((remote_state[0] & kKelvinatorPower) != 0);
+bool IRKelvinatorAC::getPower(void) {
+ return remote_state[0] & kKelvinatorPower;
}
// Set the temp. in deg C
-void IRKelvinatorAC::setTemp(uint8_t temp) {
- temp = std::max(kKelvinatorMinTemp, temp);
+void IRKelvinatorAC::setTemp(const uint8_t degrees) {
+ uint8_t temp = std::max(kKelvinatorMinTemp, degrees);
temp = std::min(kKelvinatorMaxTemp, temp);
remote_state[1] = (remote_state[1] & 0xF0U) | (temp - kKelvinatorMinTemp);
remote_state[9] = remote_state[1]; // Duplicate to the 2nd command chunk.
}
// Return the set temp. in deg C
-uint8_t IRKelvinatorAC::getTemp() {
+uint8_t IRKelvinatorAC::getTemp(void) {
return ((remote_state[1] & 0xFU) + kKelvinatorMinTemp);
}
// Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed
-void IRKelvinatorAC::setFan(uint8_t fan) {
- fan = std::min(kKelvinatorFanMax, fan); // Bounds check
+void IRKelvinatorAC::setFan(const uint8_t speed) {
+ uint8_t fan = std::min(kKelvinatorFanMax, speed); // Bounds check
// Only change things if we need to.
- if (fan != getFan()) {
+ if (fan != this->getFan()) {
// Set the basic fan values.
uint8_t fan_basic = std::min(kKelvinatorBasicFanMax, fan);
remote_state[0] = (remote_state[0] & kKelvinatorBasicFanMask) |
@@ -244,108 +247,117 @@ void IRKelvinatorAC::setFan(uint8_t fan) {
// Set the advanced(?) fan value.
remote_state[14] =
(remote_state[14] & kKelvinatorFanMask) | (fan << kKelvinatorFanOffset);
- setTurbo(false); // Turbo mode is turned off if we change the fan settings.
+ // Turbo mode is turned off if we change the fan settings.
+ this->setTurbo(false);
}
}
-uint8_t IRKelvinatorAC::getFan() {
+uint8_t IRKelvinatorAC::getFan(void) {
return ((remote_state[14] & ~kKelvinatorFanMask) >> kKelvinatorFanOffset);
}
-uint8_t IRKelvinatorAC::getMode() {
+uint8_t IRKelvinatorAC::getMode(void) {
return (remote_state[0] & ~kKelvinatorModeMask);
}
-void IRKelvinatorAC::setMode(uint8_t mode) {
- // If we get an unexpected mode, default to AUTO.
- if (mode > kKelvinatorHeat) mode = kKelvinatorAuto;
- remote_state[0] = (remote_state[0] & kKelvinatorModeMask) | mode;
- remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
- if (mode == kKelvinatorAuto || kKelvinatorDry)
- // When the remote is set to Auto or Dry, it defaults to 25C and doesn't
- // show it.
- setTemp(kKelvinatorAutoTemp);
+void IRKelvinatorAC::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kKelvinatorAuto:
+ case kKelvinatorDry:
+ // When the remote is set to Auto or Dry, it defaults to 25C and doesn't
+ // show it.
+ this->setTemp(kKelvinatorAutoTemp);
+ // FALL-THRU
+ case kKelvinatorHeat:
+ case kKelvinatorCool:
+ case kKelvinatorFan:
+ remote_state[0] = (remote_state[0] & kKelvinatorModeMask) | mode;
+ remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
+ break;
+ default: // If we get an unexpected mode, default to AUTO.
+ this->setMode(kKelvinatorAuto);
+ }
}
-void IRKelvinatorAC::setSwingVertical(bool state) {
- if (state) {
+void IRKelvinatorAC::setSwingVertical(const bool on) {
+ if (on) {
remote_state[0] |= kKelvinatorVentSwing;
remote_state[4] |= kKelvinatorVentSwingV;
} else {
remote_state[4] &= ~kKelvinatorVentSwingV;
- if (!getSwingHorizontal()) remote_state[0] &= ~kKelvinatorVentSwing;
+ if (!this->getSwingHorizontal()) remote_state[0] &= ~kKelvinatorVentSwing;
}
remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
}
-bool IRKelvinatorAC::getSwingVertical() {
- return ((remote_state[4] & kKelvinatorVentSwingV) != 0);
+bool IRKelvinatorAC::getSwingVertical(void) {
+ return remote_state[4] & kKelvinatorVentSwingV;
}
-void IRKelvinatorAC::setSwingHorizontal(bool state) {
- if (state) {
+void IRKelvinatorAC::setSwingHorizontal(const bool on) {
+ if (on) {
remote_state[0] |= kKelvinatorVentSwing;
remote_state[4] |= kKelvinatorVentSwingH;
} else {
remote_state[4] &= ~kKelvinatorVentSwingH;
- if (!getSwingVertical()) remote_state[0] &= ~kKelvinatorVentSwing;
+ if (!this->getSwingVertical()) remote_state[0] &= ~kKelvinatorVentSwing;
}
remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
}
-bool IRKelvinatorAC::getSwingHorizontal() {
- return ((remote_state[4] & kKelvinatorVentSwingH) != 0);
+bool IRKelvinatorAC::getSwingHorizontal(void) {
+ return remote_state[4] & kKelvinatorVentSwingH;
}
-void IRKelvinatorAC::setQuiet(bool state) {
+void IRKelvinatorAC::setQuiet(const bool on) {
remote_state[12] &= ~kKelvinatorQuiet;
- remote_state[12] |= (state << kKelvinatorQuietOffset);
+ remote_state[12] |= (on << kKelvinatorQuietOffset);
}
-bool IRKelvinatorAC::getQuiet() {
- return ((remote_state[12] & kKelvinatorQuiet) != 0);
+bool IRKelvinatorAC::getQuiet(void) {
+ return remote_state[12] & kKelvinatorQuiet;
}
-void IRKelvinatorAC::setIonFilter(bool state) {
+void IRKelvinatorAC::setIonFilter(const bool on) {
remote_state[2] &= ~kKelvinatorIonFilter;
- remote_state[2] |= (state << kKelvinatorIonFilterOffset);
+ remote_state[2] |= (on << kKelvinatorIonFilterOffset);
remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk.
}
-bool IRKelvinatorAC::getIonFilter() {
- return ((remote_state[2] & kKelvinatorIonFilter) != 0);
+bool IRKelvinatorAC::getIonFilter(void) {
+ return remote_state[2] & kKelvinatorIonFilter;
}
-void IRKelvinatorAC::setLight(bool state) {
+void IRKelvinatorAC::setLight(const bool on) {
remote_state[2] &= ~kKelvinatorLight;
- remote_state[2] |= (state << kKelvinatorLightOffset);
+ remote_state[2] |= (on << kKelvinatorLightOffset);
remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk.
}
-bool IRKelvinatorAC::getLight() {
- return ((remote_state[2] & kKelvinatorLight) != 0);
+bool IRKelvinatorAC::getLight(void) {
+ return remote_state[2] & kKelvinatorLight;
}
// Note: XFan mode is only valid in Cool or Dry mode.
-void IRKelvinatorAC::setXFan(bool state) {
+void IRKelvinatorAC::setXFan(const bool on) {
remote_state[2] &= ~kKelvinatorXfan;
- remote_state[2] |= (state << kKelvinatorXfanOffset);
+ remote_state[2] |= (on << kKelvinatorXfanOffset);
remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk.
}
-bool IRKelvinatorAC::getXFan() {
- return ((remote_state[2] & kKelvinatorXfan) != 0);
+bool IRKelvinatorAC::getXFan(void) {
+ return remote_state[2] & kKelvinatorXfan;
}
// Note: Turbo mode is turned off if the fan speed is changed.
-void IRKelvinatorAC::setTurbo(bool state) {
+void IRKelvinatorAC::setTurbo(const bool on) {
remote_state[2] &= ~kKelvinatorTurbo;
- remote_state[2] |= (state << kKelvinatorTurboOffset);
+ remote_state[2] |= (on << kKelvinatorTurboOffset);
remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk.
}
-bool IRKelvinatorAC::getTurbo() {
- return ((remote_state[2] & kKelvinatorTurbo) != 0);
+bool IRKelvinatorAC::getTurbo(void) {
+ return remote_state[2] & kKelvinatorTurbo;
}
// Convert a standard A/C mode into its native mode.
@@ -364,87 +376,67 @@ uint8_t IRKelvinatorAC::convertMode(const stdAc::opmode_t mode) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRKelvinatorAC::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kKelvinatorCool: return stdAc::opmode_t::kCool;
+ case kKelvinatorHeat: return stdAc::opmode_t::kHeat;
+ case kKelvinatorDry: return stdAc::opmode_t::kDry;
+ case kKelvinatorFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRKelvinatorAC::toCommonFanSpeed(const uint8_t speed) {
+ return (stdAc::fanspeed_t)speed;
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRKelvinatorAC::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::KELVINATOR;
+ result.model = -1; // Unused.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwingVertical() ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.swingh = this->getSwingHorizontal() ? stdAc::swingh_t::kAuto :
+ stdAc::swingh_t::kOff;
+ result.quiet = this->getQuiet();
+ result.turbo = this->getTurbo();
+ result.light = this->getLight();
+ result.filter = this->getIonFilter();
+ result.clean = this->getXFan();
+ // Not supported.
+ result.econo = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRKelvinatorAC::toString() {
+String IRKelvinatorAC::toString(void) {
String result = "";
-#else
-std::string IRKelvinatorAC::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kKelvinatorAuto:
- result += F(" (AUTO)");
- break;
- case kKelvinatorCool:
- result += F(" (COOL)");
- break;
- case kKelvinatorHeat:
- result += F(" (HEAT)");
- break;
- case kKelvinatorDry:
- result += F(" (DRY)");
- break;
- case kKelvinatorFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kKelvinatorFanAuto:
- result += F(" (AUTO)");
- break;
- case kKelvinatorFanMax:
- result += F(" (MAX)");
- break;
- }
- result += F(", Turbo: ");
- if (getTurbo())
- result += F("On");
- else
- result += F("Off");
- result += F(", Quiet: ");
- if (getQuiet())
- result += F("On");
- else
- result += F("Off");
- result += F(", XFan: ");
- if (getXFan())
- result += F("On");
- else
- result += F("Off");
- result += F(", IonFilter: ");
- if (getIonFilter())
- result += F("On");
- else
- result += F("Off");
- result += F(", Light: ");
- if (getLight())
- result += F("On");
- else
- result += F("Off");
- result += F(", Swing (Horizontal): ");
- if (getSwingHorizontal())
- result += F("On");
- else
- result += F("Off");
- result += F(", Swing (Vertical): ");
- if (getSwingVertical())
- result += F("On");
- else
- result += F("Off");
+ result.reserve(160); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kKelvinatorAuto, kKelvinatorCool,
+ kKelvinatorHeat, kKelvinatorDry, kKelvinatorFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kKelvinatorFanMax, kKelvinatorFanMin,
+ kKelvinatorFanAuto, kKelvinatorFanAuto,
+ kKelvinatorBasicFanMax);
+ result += addBoolToString(getTurbo(), F("Turbo"));
+ result += addBoolToString(getQuiet(), F("Quiet"));
+ result += addBoolToString(getXFan(), F("XFan"));
+ result += addBoolToString(getIonFilter(), F("IonFilter"));
+ result += addBoolToString(getLight(), F("Light"));
+ result += addBoolToString(getSwingHorizontal(), F("Swing (Horizontal)"));
+ result += addBoolToString(getSwingVertical(), F("Swing (Vertical)"));
return result;
}
@@ -458,7 +450,7 @@ std::string IRKelvinatorAC::toString() {
// Returns:
// boolean: True if it can decode it, false if it can't.
//
-// Status: ALPHA / Untested.
+// Status: STABLE / Known working.
bool IRrecv::decodeKelvinator(decode_results *results, uint16_t nbits,
bool strict) {
if (results->rawlen <
@@ -467,101 +459,60 @@ bool IRrecv::decodeKelvinator(decode_results *results, uint16_t nbits,
if (strict && nbits != kKelvinatorBits)
return false; // Not strictly a Kelvinator message.
- uint32_t data;
uint16_t offset = kStartOffset;
// There are two messages back-to-back in a full Kelvinator IR message
// sequence.
- int8_t state_pos = 0;
+ int8_t pos = 0;
for (uint8_t s = 0; s < 2; s++) {
match_result_t data_result;
- // Header
- if (!matchMark(results->rawbuf[offset], kKelvinatorHdrMark)) return false;
- // Calculate how long the lowest tick time is based on the header mark.
- uint32_t mark_tick =
- results->rawbuf[offset++] * kRawTick / kKelvinatorHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kKelvinatorHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t space_tick =
- results->rawbuf[offset++] * kRawTick / kKelvinatorHdrSpaceTicks;
-
- // Data (Command) (32 bits)
- data_result = matchData(
- &(results->rawbuf[offset]), 32, kKelvinatorBitMarkTicks * mark_tick,
- kKelvinatorOneSpaceTicks * space_tick,
- kKelvinatorBitMarkTicks * mark_tick,
- kKelvinatorZeroSpaceTicks * space_tick, kTolerance, kMarkExcess, false);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Record command data in the state.
- for (uint16_t i = 0; i < 4; i++, data >>= 8)
- results->state[state_pos + i] = data & 0xFF;
- state_pos += 4;
+ uint16_t used;
+ // Header + Data Block #1 (32 bits)
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, 32,
+ kKelvinatorHdrMark, kKelvinatorHdrSpace,
+ kKelvinatorBitMark, kKelvinatorOneSpace,
+ kKelvinatorBitMark, kKelvinatorZeroSpace,
+ 0, 0, false,
+ _tolerance, kMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
+ pos += 4;
// Command data footer (3 bits, B010)
data_result = matchData(
&(results->rawbuf[offset]), kKelvinatorCmdFooterBits,
- kKelvinatorBitMarkTicks * mark_tick,
- kKelvinatorOneSpaceTicks * space_tick,
- kKelvinatorBitMarkTicks * mark_tick,
- kKelvinatorZeroSpaceTicks * space_tick, kTolerance, kMarkExcess, false);
+ kKelvinatorBitMark, kKelvinatorOneSpace,
+ kKelvinatorBitMark, kKelvinatorZeroSpace,
+ _tolerance, kMarkExcess, false);
if (data_result.success == false) return false;
if (data_result.data != kKelvinatorCmdFooter) return false;
offset += data_result.used;
- // Interdata gap.
- if (!matchMark(results->rawbuf[offset++],
- kKelvinatorBitMarkTicks * mark_tick))
- return false;
- if (!matchSpace(results->rawbuf[offset++],
- kKelvinatorGapSpaceTicks * space_tick))
- return false;
-
- // Data (Options) (32 bits)
- data_result = matchData(
- &(results->rawbuf[offset]), 32, kKelvinatorBitMarkTicks * mark_tick,
- kKelvinatorOneSpaceTicks * space_tick,
- kKelvinatorBitMarkTicks * mark_tick,
- kKelvinatorZeroSpaceTicks * space_tick, kTolerance, kMarkExcess, false);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Record option data in the state.
- for (uint16_t i = 0; i < 4; i++, data >>= 8)
- results->state[state_pos + i] = data & 0xFF;
- state_pos += 4;
-
- // Inter-sequence gap. (Double length gap)
- if (!matchMark(results->rawbuf[offset++],
- kKelvinatorBitMarkTicks * mark_tick))
- return false;
- if (s == 0) {
- if (!matchSpace(results->rawbuf[offset++],
- kKelvinatorGapSpaceTicks * space_tick * 2))
- return false;
- } else {
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset],
- kKelvinatorGapSpaceTicks * 2 * space_tick))
- return false;
- }
+ // Gap + Data (Options) (32 bits)
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, 32,
+ kKelvinatorBitMark, kKelvinatorGapSpace,
+ kKelvinatorBitMark, kKelvinatorOneSpace,
+ kKelvinatorBitMark, kKelvinatorZeroSpace,
+ kKelvinatorBitMark, kKelvinatorGapSpace * 2,
+ s > 0,
+ _tolerance, kMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
+ pos += 4;
}
// Compliance
if (strict) {
- // Correct size/length)
- if (state_pos != kKelvinatorStateLength) return false;
// Verify the message's checksum is correct.
if (!IRKelvinatorAC::validChecksum(results->state)) return false;
}
// Success
- results->decode_type = KELVINATOR;
- results->bits = state_pos * 8;
+ results->decode_type = decode_type_t::KELVINATOR;
+ results->bits = nbits;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.h b/lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.h
similarity index 71%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.h
index ce830c70a..fac26bf2e 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.h
@@ -2,6 +2,19 @@
//
// Copyright 2016 David Conran
+// Supports:
+// Brand: Kelvinator, Model: YALIF Remote
+// Brand: Kelvinator, Model: KSV26CRC A/C
+// Brand: Kelvinator, Model: KSV26HRC A/C
+// Brand: Kelvinator, Model: KSV35CRC A/C
+// Brand: Kelvinator, Model: KSV35HRC A/C
+// Brand: Kelvinator, Model: KSV53HRC A/C
+// Brand: Kelvinator, Model: KSV62HRC A/C
+// Brand: Kelvinator, Model: KSV70CRC A/C
+// Brand: Kelvinator, Model: KSV70HRC A/C
+// Brand: Kelvinator, Model: KSV80HRC A/C
+// Brand: Green, Model: YAPOF3 remote
+
#ifndef IR_KELVINATOR_H_
#define IR_KELVINATOR_H_
@@ -9,8 +22,6 @@
#include
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -18,12 +29,6 @@
#include "IRsend_test.h"
#endif
-// KK KK EEEEEEE LL VV VV IIIII NN NN AAA TTTTTTT OOOOO RRRRRR
-// KK KK EE LL VV VV III NNN NN AAAAA TTT OO OO RR RR
-// KKKK EEEEE LL VV VV III NN N NN AA AA TTT OO OO RRRRRR
-// KK KK EE LL VV VV III NN NNN AAAAAAA TTT OO OO RR RR
-// KK KK EEEEEEE LLLLLLL VVV IIIII NN NN AA AA TTT OOOO0 RR RR
-
// Constants
const uint8_t kKelvinatorAuto = 0;
const uint8_t kKelvinatorCool = 1;
@@ -32,6 +37,7 @@ const uint8_t kKelvinatorFan = 3;
const uint8_t kKelvinatorHeat = 4;
const uint8_t kKelvinatorBasicFanMax = 3;
const uint8_t kKelvinatorFanAuto = 0;
+const uint8_t kKelvinatorFanMin = 1;
const uint8_t kKelvinatorFanMax = 5;
const uint8_t kKelvinatorMinTemp = 16; // 16C
const uint8_t kKelvinatorMaxTemp = 30; // 30C
@@ -129,49 +135,50 @@ const uint8_t kKelvinatorAutoTemp = 25; // 25C
// Classes
class IRKelvinatorAC {
public:
- explicit IRKelvinatorAC(uint16_t pin);
+ explicit IRKelvinatorAC(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
- void stateReset();
+ void stateReset(void);
#if SEND_KELVINATOR
void send(const uint16_t repeat = kKelvinatorDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_KELVINATOR
- void begin();
- void on();
- void off();
- void setPower(bool state);
- bool getPower();
- void setTemp(uint8_t temp);
- uint8_t getTemp();
- void setFan(uint8_t fan);
- uint8_t getFan();
- void setMode(uint8_t mode);
- uint8_t getMode();
- void setSwingVertical(bool state);
- bool getSwingVertical();
- void setSwingHorizontal(bool state);
- bool getSwingHorizontal();
- void setQuiet(bool state);
- bool getQuiet();
- void setIonFilter(bool state);
- bool getIonFilter();
- void setLight(bool state);
- bool getLight();
- void setXFan(bool state);
- bool getXFan();
- void setTurbo(bool state);
- bool getTurbo();
- uint8_t* getRaw();
- void setRaw(uint8_t new_code[]);
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t degrees);
+ uint8_t getTemp(void);
+ void setFan(const uint8_t speed);
+ uint8_t getFan(void);
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ void setSwingVertical(const bool on);
+ bool getSwingVertical(void);
+ void setSwingHorizontal(const bool on);
+ bool getSwingHorizontal(void);
+ void setQuiet(const bool on);
+ bool getQuiet(void);
+ void setIonFilter(const bool on);
+ bool getIonFilter(void);
+ void setLight(const bool on);
+ bool getLight(void);
+ void setXFan(const bool on);
+ bool getXFan(void);
+ void setTurbo(const bool on);
+ bool getTurbo(void);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t new_code[]);
static uint8_t calcBlockChecksum(
const uint8_t* block, const uint16_t length = kKelvinatorStateLength / 2);
static bool validChecksum(const uint8_t state[],
const uint16_t length = kKelvinatorStateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -182,7 +189,7 @@ class IRKelvinatorAC {
// The state of the IR remote in IR code form.
uint8_t remote_state[kKelvinatorStateLength];
void checksum(const uint16_t length = kKelvinatorStateLength);
- void fixup();
+ void fixup(void);
};
#endif // IR_KELVINATOR_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_LG.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_LG.cpp
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/src/ir_LG.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_LG.cpp
index 36c85ff15..124256e9f 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_LG.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_LG.cpp
@@ -2,25 +2,18 @@
// Copyright 2015 cheaplin
// Copyright 2017, 2018 David Conran
+// Supports:
+// Brand: LG, Model: 6711A20083V remote
+// Brand: LG, Model: AKB74395308 remote
+
#include "ir_LG.h"
#include
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
-// L GGGG
-// L G
-// L G GG
-// L G G
-// LLLLL GGG
-
// LG decode originally added by Darryl Smith (based on the JVC protocol)
// LG send originally added by https://github.com/chaeplin
-//
-// Known supported devices:
-// IR Remotes:
-// 6711A20083V
-// AKB74395308
// Constants
const uint16_t kLgTick = 50;
@@ -244,7 +237,7 @@ bool IRrecv::decodeLG(decode_results *results, uint16_t nbits, bool strict) {
match_result_t data_result =
matchData(&(results->rawbuf[offset]), nbits, bitmarkticks * m_tick,
kLgOneSpaceTicks * s_tick, bitmarkticks * m_tick,
- kLgZeroSpaceTicks * s_tick, kTolerance, 0);
+ kLgZeroSpaceTicks * s_tick, _tolerance, 0);
if (data_result.success == false) return false;
data = data_result.data;
offset += data_result.used;
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_LG.h b/lib/IRremoteESP8266-2.6.5/src/ir_LG.h
new file mode 100644
index 000000000..01f81e2c1
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_LG.h
@@ -0,0 +1,15 @@
+// Copyright 2017 David Conran
+
+// Supports:
+// Brand: LG, Model: 6711A20083V remote
+// Brand: LG, Model: AKB74395308 remote
+
+#ifndef IR_LG_H_
+#define IR_LG_H_
+
+#define __STDC_LIMIT_MACROS
+#include
+
+uint8_t calcLGChecksum(uint16_t data);
+
+#endif // IR_LG_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Lasertag.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Lasertag.cpp
similarity index 91%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Lasertag.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Lasertag.cpp
index b1cbdc9b1..f52b7477a 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Lasertag.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Lasertag.cpp
@@ -1,16 +1,11 @@
// Copyright 2017 David Conran
+// Lasertag
#include
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
-// LL AAA SSSSS EEEEEEE RRRRRR TTTTTTT AAA GGGG
-// LL AAAAA SS EE RR RR TTT AAAAA GG GG
-// LL AA AA SSSSS EEEEE RRRRRR TTT AA AA GG
-// LL AAAAAAA SS EE RR RR TTT AAAAAAA GG GG
-// LLLLLLL AA AA SSSSS EEEEEEE RR RR TTT AA AA GGGGGG
-
// Constants
const uint16_t kLasertagMinSamples = 13;
const uint16_t kLasertagTick = 333;
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Lego.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Lego.cpp
similarity index 74%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Lego.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Lego.cpp
index b051aba51..932a568d0 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Lego.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Lego.cpp
@@ -8,12 +8,12 @@
// LEGO
// (LEGO is a Registrated Trademark of the Lego Group.)
//
-// Supported Devices:
-// - LEGO Power Functions IR Receiver
+// Supports:
+// Brand: LEGO Power Functions, Model: IR Receiver
//
// Ref:
-// - https://github.com/markszabo/IRremoteESP8266/issues/641
-// - https://github.com/markszabo/IRremoteESP8266/files/2974525/LEGO_Power_Functions_RC_v120.pdf
+// - https://github.com/crankyoldgit/IRremoteESP8266/issues/641
+// - https://github.com/crankyoldgit/IRremoteESP8266/files/2974525/LEGO_Power_Functions_RC_v120.pdf
// Constants
const uint16_t kLegoPfBitMark = 158;
@@ -81,32 +81,17 @@ bool IRrecv::decodeLegoPf(decode_results* results,
uint64_t data = 0;
uint16_t offset = kStartOffset;
- match_result_t data_result;
-
- // Header
- if (!matchMark(results->rawbuf[offset++], kLegoPfBitMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kLegoPfHdrSpace)) return false;
- // Data (Typically 16 bits)
- data_result =
- matchData(&(results->rawbuf[offset]), nbits,
- kLegoPfBitMark, kLegoPfOneSpace,
- kLegoPfBitMark, kLegoPfZeroSpace,
- kTolerance, kMarkExcess, true);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
- uint16_t actualBits = data_result.used / 2;
-
- // Footer.
- if (!matchMark(results->rawbuf[offset++], kLegoPfBitMark)) return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kLegoPfMinCommandLength))
- return false;
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kLegoPfBitMark, kLegoPfHdrSpace,
+ kLegoPfBitMark, kLegoPfOneSpace,
+ kLegoPfBitMark, kLegoPfZeroSpace,
+ kLegoPfBitMark, kLegoPfMinCommandLength,
+ true)) return false;
// Compliance
- if (actualBits < nbits) return false;
if (strict) {
- if (actualBits != nbits) return false; // Not as we expected.
// Verify the Longitudinal Redundancy Check (LRC)
uint16_t lrc_data = data;
uint8_t lrc = 0xF;
@@ -119,7 +104,7 @@ bool IRrecv::decodeLegoPf(decode_results* results,
// Success
results->decode_type = LEGOPF;
- results->bits = actualBits;
+ results->bits = nbits;
results->value = data;
results->address = ((data >> (nbits - 4)) & 0b11) + 1; // Channel Id
results->command = (data >> 4) & 0xFF; // Stuff between Channel Id and LRC.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Lutron.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Lutron.cpp
similarity index 90%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Lutron.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Lutron.cpp
index 00eb9383b..7c9835047 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Lutron.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Lutron.cpp
@@ -1,4 +1,5 @@
// Copyright 2018 David Conran
+// Lutron
#define __STDC_LIMIT_MACROS
#include
@@ -7,12 +8,6 @@
#include "IRsend.h"
#include "IRutils.h"
-// LL UU UU TTTTTTT RRRRRR OOOOO NN NN
-// LL UU UU TTT RR RR OO OO NNN NN
-// LL UU UU TTT RRRRRR OO OO NN N NN
-// LL UU UU TTT RR RR OO OO NN NNN
-// LLLLLLL UUUUU TTT RR RR OOOO0 NN NN
-
// Notes:
// The Lutron protocol uses a sort of Run Length encoding to encode
// its data. There is no header or footer per-se.
@@ -22,7 +17,7 @@
// Constants
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/515
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/515
const uint16_t kLutronTick = 2288;
const uint32_t kLutronGap = 150000; // Completely made up value.
const uint16_t kLutronDelta = 400; // +/- 300 usecs.
@@ -42,7 +37,7 @@ const uint16_t kLutronDelta = 400; // +/- 300 usecs.
// So, assume the 1 and only have a normal payload of 35 bits.
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/515
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/515
void IRsend::sendLutron(uint64_t data, uint16_t nbits, uint16_t repeat) {
enableIROut(40000, 40); // 40Khz & 40% dutycycle.
for (uint16_t r = 0; r <= repeat; r++) {
@@ -73,7 +68,7 @@ void IRsend::sendLutron(uint64_t data, uint16_t nbits, uint16_t repeat) {
// Notes:
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/515
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/515
bool IRrecv::decodeLutron(decode_results *results, uint16_t nbits,
bool strict) {
// Technically the smallest number of entries for the smallest message is '1'.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_MWM.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_MWM.cpp
similarity index 94%
rename from lib/IRremoteESP8266-2.6.0/src/ir_MWM.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_MWM.cpp
index 61eac49e2..b747b224b 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_MWM.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_MWM.cpp
@@ -1,4 +1,7 @@
// Copyright 2018 Brett T. Warden
+
+// MWM
+
// derived from ir_Lasertag.cpp, Copyright 2017 David Conran
#include
@@ -6,12 +9,6 @@
#include "IRsend.h"
#include "IRutils.h"
-// MM MM WW WW MM MM
-// MMM MMM WW WW MMM MMM
-// MM M MM WW W WW MM M MM
-// MM MM WWW WWW MM MM
-// MM MM WW WW MM MM
-
// Constants
const uint16_t kMWMMinSamples = 6; // Msgs are >=3 bytes, bytes have >=2
// samples
@@ -37,7 +34,8 @@ const int16_t kMark = 0;
//
// Status: Implemented.
//
-void IRsend::sendMWM(uint8_t data[], uint16_t nbytes, uint16_t repeat) {
+void IRsend::sendMWM(const uint8_t data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < 3) return; // Shortest possible message is 3 bytes
// Set 38kHz IR carrier frequency & a 1/4 (25%) duty cycle.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Magiquest.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Magiquest.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Magiquest.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Magiquest.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Magiquest.h b/lib/IRremoteESP8266-2.6.5/src/ir_Magiquest.h
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Magiquest.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Magiquest.h
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Midea.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Midea.cpp
similarity index 56%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Midea.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Midea.cpp
index 8d5d9494f..80744c9cb 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Midea.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Midea.cpp
@@ -1,4 +1,5 @@
// Copyright 2017 bwze, crankyoldgit
+// Midea
#include "ir_Midea.h"
#include
@@ -9,12 +10,6 @@
#include "IRsend.h"
#include "IRutils.h"
-// MM MM IIIII DDDDD EEEEEEE AAA
-// MMM MMM III DD DD EE AAAAA
-// MM MM MM III DD DD EEEEE AA AA
-// MM MM III DD DD EE AAAAAAA
-// MM MM IIIII DDDDDD EEEEEEE AA AA
-
// Midea A/C added by (send) bwze/crankyoldgit & (decode) crankyoldgit
//
// Equipment it seems compatible with:
@@ -42,6 +37,13 @@ const uint16_t kMideaMinGapTicks =
const uint16_t kMideaMinGap = kMideaMinGapTicks * kMideaTick;
const uint8_t kMideaTolerance = 30; // Percent
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
#if SEND_MIDEA
// Send a Midea message
//
@@ -91,81 +93,116 @@ void IRsend::sendMidea(uint64_t data, uint16_t nbits, uint16_t repeat) {
// Warning: Consider this very alpha code.
// Initialise the object.
-IRMideaAC::IRMideaAC(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRMideaAC::IRMideaAC(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
// Reset the state of the remote to a known good state/sequence.
-void IRMideaAC::stateReset() {
+void IRMideaAC::stateReset(void) {
// Power On, Mode Auto, Fan Auto, Temp = 25C/77F
remote_state = 0xA1826FFFFF62;
+ _SwingVToggle = false;
}
// Configure the pin for output.
-void IRMideaAC::begin() { _irsend.begin(); }
+void IRMideaAC::begin(void) { _irsend.begin(); }
#if SEND_MIDEA
// Send the current desired state to the IR LED.
void IRMideaAC::send(const uint16_t repeat) {
- checksum(); // Ensure correct checksum before sending.
+ this->checksum(); // Ensure correct checksum before sending.
_irsend.sendMidea(remote_state, kMideaBits, repeat);
+ // Handle toggling the swing if we need to.
+ if (_SwingVToggle && !isSwingVToggle()) {
+ _irsend.sendMidea(kMideaACToggleSwingV, kMideaBits, repeat);
+ }
+ _SwingVToggle = false; // The toggle message has been sent, so reset.
}
#endif // SEND_MIDEA
// Return a pointer to the internal state date of the remote.
-uint64_t IRMideaAC::getRaw() {
- checksum();
+uint64_t IRMideaAC::getRaw(void) {
+ this->checksum();
return remote_state & kMideaACStateMask;
}
// Override the internal state with the new state.
-void IRMideaAC::setRaw(uint64_t newState) {
+void IRMideaAC::setRaw(const uint64_t newState) {
remote_state = newState & kMideaACStateMask;
}
// Set the requested power state of the A/C to off.
-void IRMideaAC::on() { remote_state |= kMideaACPower; }
+void IRMideaAC::on(void) { remote_state |= kMideaACPower; }
// Set the requested power state of the A/C to off.
-void IRMideaAC::off() { remote_state &= (kMideaACStateMask ^ kMideaACPower); }
+void IRMideaAC::off(void) {
+ remote_state &= (kMideaACStateMask ^ kMideaACPower);
+}
// Set the requested power state of the A/C.
-void IRMideaAC::setPower(const bool state) {
- if (state)
- on();
+void IRMideaAC::setPower(const bool on) {
+ if (on)
+ this->on();
else
- off();
+ this->off();
}
// Return the requested power state of the A/C.
-bool IRMideaAC::getPower() { return (remote_state & kMideaACPower); }
+bool IRMideaAC::getPower(void) { return (remote_state & kMideaACPower); }
+
+// Returns true if we want the A/C unit to work natively in Celsius.
+bool IRMideaAC::getUseCelsius(void) {
+ return !(remote_state & kMideaACCelsiusBit);
+}
+
+// Set the A/C unit to use Celsius natively.
+void IRMideaAC::setUseCelsius(const bool on) {
+ if (on != getUseCelsius()) { // We need to change.
+ uint8_t native_temp = getTemp(!on); // Get the old native temp.
+ if (on)
+ remote_state &= ~kMideaACCelsiusBit; // Clear the bit
+ else
+ remote_state |= kMideaACCelsiusBit; // Set the bit
+ setTemp(native_temp, !on); // Reset temp using the old native temp.
+ }
+}
// Set the temperature.
// Args:
// temp: Temp. in degrees.
// useCelsius: Degree type to use. Celsius (true) or Fahrenheit (false)
void IRMideaAC::setTemp(const uint8_t temp, const bool useCelsius) {
- uint8_t new_temp = temp;
+ uint8_t max_temp = kMideaACMaxTempF;
+ uint8_t min_temp = kMideaACMinTempF;
if (useCelsius) {
- new_temp = std::max(kMideaACMinTempC, new_temp);
- new_temp = std::min(kMideaACMaxTempC, new_temp);
- new_temp = (uint8_t)((new_temp * 1.8) + 32.5); // 0.5 so we rounding.
+ max_temp = kMideaACMaxTempC;
+ min_temp = kMideaACMinTempC;
}
- new_temp = std::max(kMideaACMinTempF, new_temp);
- new_temp = std::min(kMideaACMaxTempF, new_temp);
- new_temp -= kMideaACMinTempF;
+ uint8_t new_temp = std::min(max_temp, std::max(min_temp, temp));
+ if (getUseCelsius() && !useCelsius) // Native is in C, new_temp is in F
+ new_temp = fahrenheitToCelsius(new_temp) - kMideaACMinTempC;
+ else if (!getUseCelsius() && useCelsius) // Native is in F, new_temp is in C
+ new_temp = celsiusToFahrenheit(new_temp) - kMideaACMinTempF;
+ else // Native and desired are the same units.
+ new_temp -= min_temp;
+ // Set the actual data.
remote_state &= kMideaACTempMask;
remote_state |= ((uint64_t)new_temp << 24);
}
// Return the set temp.
// Args:
-// useCelsius: Flag indicating if the results are in Celsius or Fahrenheit.
+// celsius: Flag indicating if the results are in Celsius or Fahrenheit.
// Returns:
// A uint8_t containing the temperature.
-uint8_t IRMideaAC::getTemp(const bool useCelsius) {
- uint8_t temp = ((remote_state >> 24) & 0x1F) + kMideaACMinTempF;
- if (useCelsius) {
- temp = (uint8_t)((temp - 32) / 1.8);
- }
+uint8_t IRMideaAC::getTemp(const bool celsius) {
+ uint8_t temp = ((remote_state >> 24) & 0x1F);
+ if (getUseCelsius())
+ temp += kMideaACMinTempC;
+ else
+ temp += kMideaACMinTempF;
+ if (celsius && !getUseCelsius()) temp = fahrenheitToCelsius(temp) + 0.5;
+ if (!celsius && getUseCelsius()) temp = celsiusToFahrenheit(temp);
return temp;
}
@@ -187,42 +224,54 @@ void IRMideaAC::setFan(const uint8_t fan) {
}
// Return the requested state of the unit's fan.
-uint8_t IRMideaAC::getFan() { return (remote_state >> 35) & 0b111; }
+uint8_t IRMideaAC::getFan(void) { return (remote_state >> 35) & 0b111; }
// Get the requested climate operation mode of the a/c unit.
// Returns:
// A uint8_t containing the A/C mode.
-uint8_t IRMideaAC::getMode() { return ((remote_state >> 32) & 0b111); }
+uint8_t IRMideaAC::getMode(void) { return ((remote_state >> 32) & 0b111); }
// Set the requested climate operation mode of the a/c unit.
void IRMideaAC::setMode(const uint8_t mode) {
- // If we get an unexpected mode, default to AUTO.
- uint64_t new_mode;
switch (mode) {
case kMideaACAuto:
case kMideaACCool:
case kMideaACHeat:
case kMideaACDry:
case kMideaACFan:
- new_mode = mode;
- break;
+ remote_state &= kMideaACModeMask;
+ remote_state |= ((uint64_t)mode << 32);
+ return;
default:
- new_mode = kMideaACAuto;
+ this->setMode(kMideaACAuto);
}
- remote_state &= kMideaACModeMask;
- remote_state |= (new_mode << 32);
}
// Set the Sleep state of the A/C.
-void IRMideaAC::setSleep(const bool state) {
- if (state)
+void IRMideaAC::setSleep(const bool on) {
+ if (on)
remote_state |= kMideaACSleep;
else
remote_state &= (kMideaACStateMask ^ kMideaACSleep);
}
// Return the Sleep state of the A/C.
-bool IRMideaAC::getSleep() { return (remote_state & kMideaACSleep); }
+bool IRMideaAC::getSleep(void) { return (remote_state & kMideaACSleep); }
+
+// Set the A/C to toggle the vertical swing toggle for the next send.
+void IRMideaAC::setSwingVToggle(const bool on) {
+ _SwingVToggle = on;
+}
+
+// Return if the message/state is just a Swing V toggle message/command.
+bool IRMideaAC::isSwingVToggle(void) {
+ return remote_state == kMideaACToggleSwingV;
+}
+// Return the Swing V toggle state of the A/C.
+bool IRMideaAC::getSwingVToggle(void) {
+ _SwingVToggle |= isSwingVToggle();
+ return _SwingVToggle;
+}
// Calculate the checksum for a given array.
// Args:
@@ -251,7 +300,7 @@ bool IRMideaAC::validChecksum(const uint64_t state) {
}
// Calculate & set the checksum for the current internal state of the remote.
-void IRMideaAC::checksum() {
+void IRMideaAC::checksum(void) {
// Stored the checksum value in the last byte.
remote_state &= kMideaACChecksumMask;
remote_state |= calcChecksum(remote_state);
@@ -290,65 +339,81 @@ uint8_t IRMideaAC::convertFan(const stdAc::fanspeed_t speed) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRMideaAC::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kMideaACCool: return stdAc::opmode_t::kCool;
+ case kMideaACHeat: return stdAc::opmode_t::kHeat;
+ case kMideaACDry: return stdAc::opmode_t::kDry;
+ case kMideaACFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRMideaAC::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kMideaACFanHigh: return stdAc::fanspeed_t::kMax;
+ case kMideaACFanMed: return stdAc::fanspeed_t::kMedium;
+ case kMideaACFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRMideaAC::toCommon(const stdAc::state_t *prev) {
+ stdAc::state_t result;
+ if (prev != NULL) {
+ result = *prev;
+ } else {
+ // Fixed/Not supported/Non-zero defaults.
+ result.protocol = decode_type_t::MIDEA;
+ result.model = -1; // No models used.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.swingv = stdAc::swingv_t::kOff;
+ result.quiet = false;
+ result.turbo = false;
+ result.clean = false;
+ result.econo = false;
+ result.filter = false;
+ result.light = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ }
+ if (this->isSwingVToggle()) {
+ result.swingv = result.swingv != stdAc::swingv_t::kOff ?
+ stdAc::swingv_t::kAuto : stdAc::swingv_t::kOff;
+ return result;
+ }
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = this->getUseCelsius();
+ result.degrees = this->getTemp(result.celsius);
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.sleep = this->getSleep() ? 0 : -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRMideaAC::toString() {
+String IRMideaAC::toString(void) {
String result = "";
-#else
-std::string IRMideaAC::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kMideaACAuto:
- result += F(" (AUTO)");
- break;
- case kMideaACCool:
- result += F(" (COOL)");
- break;
- case kMideaACHeat:
- result += F(" (HEAT)");
- break;
- case kMideaACDry:
- result += F(" (DRY)");
- break;
- case kMideaACFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
+ result.reserve(100); // Reserve some heap for the string to reduce fragging.
+ if (!isSwingVToggle()) {
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kMideaACAuto, kMideaACCool,
+ kMideaACHeat, kMideaACDry, kMideaACFan);
+ result += addBoolToString(getUseCelsius(), F("Celsius"));
+ result += addTempToString(getTemp(true));
+ result += '/';
+ result += uint64ToString(getTemp(false));
+ result += 'F';
+ result += addFanToString(getFan(), kMideaACFanHigh, kMideaACFanLow,
+ kMideaACFanAuto, kMideaACFanAuto, kMideaACFanMed);
+ result += addBoolToString(getSleep(), F("Sleep"));
}
- result += F(", Temp: ");
- result += uint64ToString(getTemp(true));
- result += F("C/");
- result += uint64ToString(getTemp(false));
- result += F("F, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kMideaACFanAuto:
- result += F(" (AUTO)");
- break;
- case kMideaACFanLow:
- result += F(" (LOW)");
- break;
- case kMideaACFanMed:
- result += F(" (MED)");
- break;
- case kMideaACFanHigh:
- result += F(" (HI)");
- break;
- }
- result += F(", Sleep: ");
- if (getSleep())
- result += F("On");
- else
- result += F("Off");
+ result += addBoolToString(getSwingVToggle(), F("Swing(V) Toggle"),
+ !isSwingVToggle());
return result;
}
@@ -365,9 +430,6 @@ std::string IRMideaAC::toString() {
// Status: Alpha / Needs testing against a real device.
//
bool IRrecv::decodeMidea(decode_results *results, uint16_t nbits, bool strict) {
- if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte.
- return false;
-
uint8_t min_nr_of_messages = 1;
if (strict) {
if (nbits != kMideaBits) return false; // Not strictly a MIDEA message.
@@ -388,35 +450,16 @@ bool IRrecv::decodeMidea(decode_results *results, uint16_t nbits, bool strict) {
return false; // We can't possibly capture a Midea packet that big.
for (uint8_t i = 0; i < min_nr_of_messages; i++) {
- // Header
- if (!matchMark(results->rawbuf[offset], kMideaHdrMark)) return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kMideaHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kMideaHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t s_tick =
- results->rawbuf[offset++] * kRawTick / kMideaHdrSpaceTicks;
-
- // Data (Normal)
- match_result_t data_result = matchData(
- &(results->rawbuf[offset]), nbits, kMideaBitMarkTicks * m_tick,
- kMideaOneSpaceTicks * s_tick, kMideaBitMarkTicks * m_tick,
- kMideaZeroSpaceTicks * s_tick, kMideaTolerance);
- if (data_result.success == false) return false;
- offset += data_result.used;
- if (i % 2 == 0)
- data = data_result.data;
- else
- inverted = data_result.data;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kMideaBitMarkTicks * m_tick,
- kMideaTolerance))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kMideaMinGapTicks * s_tick,
- kMideaTolerance))
- return false;
+ // Match Header + Data + Footer
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, i % 2 ? &inverted : &data,
+ results->rawlen - offset, nbits,
+ kMideaHdrMark, kMideaHdrSpace,
+ kMideaBitMark, kMideaOneSpace,
+ kMideaBitMark, kMideaZeroSpace,
+ kMideaBitMark, kMideaMinGap, false, kMideaTolerance);
+ if (!used) return false;
+ offset += used;
}
// Compliance
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Midea.h b/lib/IRremoteESP8266-2.6.5/src/ir_Midea.h
similarity index 60%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Midea.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Midea.h
index ab14eb252..289821778 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Midea.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Midea.h
@@ -1,4 +1,12 @@
// Copyright 2017 David Conran
+// Midea
+
+// Supports:
+// Brand: Pioneer System, Model: RYBO12GMFILCAD A/C (12K BTU)
+// Brand: Pioneer System, Model: RUBO18GMFILCAD A/C (18K BTU)
+// Brand: Comfee, Model: MPD1-12CRN7 A/C
+// Brand: Keystone, Model: RG57H4(B)BGEF remote
+
#ifndef IR_MIDEA_H_
#define IR_MIDEA_H_
@@ -6,8 +14,6 @@
#include
#ifdef ARDUINO
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -15,12 +21,6 @@
#include "IRsend_test.h"
#endif
-// MM MM IIIII DDDDD EEEEEEE AAA
-// MMM MMM III DD DD EE AAAAA
-// MM MM MM III DD DD EEEEE AA AA
-// MM MM III DD DD EE AAAAAAA
-// MM MM IIIII DDDDDD EEEEEEE AA AA
-
// Midea added by crankyoldgit & bwze
// Ref:
// https://docs.google.com/spreadsheets/d/1TZh4jWrx4h9zzpYUI9aYXMl1fYOiqu-xVuOOMqagxrs/edit?usp=sharing
@@ -39,13 +39,15 @@ const uint64_t kMideaACPower = 1ULL << 39;
const uint64_t kMideaACSleep = 1ULL << 38;
const uint8_t kMideaACMinTempF = 62; // Fahrenheit
const uint8_t kMideaACMaxTempF = 86; // Fahrenheit
-const uint8_t kMideaACMinTempC = 16; // Celsius
+const uint8_t kMideaACMinTempC = 17; // Celsius
const uint8_t kMideaACMaxTempC = 30; // Celsius
-const uint64_t kMideaACStateMask = 0x0000FFFFFFFFFFFF;
-const uint64_t kMideaACTempMask = 0x0000FFFFE0FFFFFF;
-const uint64_t kMideaACFanMask = 0x0000FFC7FFFFFFFF;
-const uint64_t kMideaACModeMask = 0x0000FFF8FFFFFFFF;
+const uint64_t kMideaACStateMask = 0x0000FFFFFFFFFFFF;
+const uint64_t kMideaACCelsiusBit = 0x0000000020000000;
+const uint64_t kMideaACTempMask = 0x0000FFFFE0FFFFFF;
+const uint64_t kMideaACFanMask = 0x0000FFC7FFFFFFFF;
+const uint64_t kMideaACModeMask = 0x0000FFF8FFFFFFFF;
const uint64_t kMideaACChecksumMask = 0x0000FFFFFFFFFF00;
+const uint64_t kMideaACToggleSwingV = 0x0000A201FFFFFF7C;
// Legacy defines. (Deprecated)
#define MIDEA_AC_COOL kMideaACCool
@@ -66,35 +68,41 @@ const uint64_t kMideaACChecksumMask = 0x0000FFFFFFFFFF00;
class IRMideaAC {
public:
- explicit IRMideaAC(uint16_t pin);
+ explicit IRMideaAC(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
- void stateReset();
+ void stateReset(void);
#if SEND_MIDEA
void send(const uint16_t repeat = kMideaMinRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_MIDEA
- void begin();
- void on();
- void off();
- void setPower(const bool state);
- bool getPower();
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ bool getUseCelsius(void);
+ void setUseCelsius(const bool celsius);
void setTemp(const uint8_t temp, const bool useCelsius = false);
uint8_t getTemp(const bool useCelsius = false);
void setFan(const uint8_t fan);
- uint8_t getFan();
+ uint8_t getFan(void);
void setMode(const uint8_t mode);
- uint8_t getMode();
- void setRaw(uint64_t newState);
- uint64_t getRaw();
+ uint8_t getMode(void);
+ void setRaw(const uint64_t newState);
+ uint64_t getRaw(void);
static bool validChecksum(const uint64_t state);
- void setSleep(const bool state);
- bool getSleep();
+ void setSleep(const bool on);
+ bool getSleep(void);
+ bool isSwingVToggle(void);
+ void setSwingVToggle(const bool on);
+ bool getSwingVToggle(void);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(const stdAc::state_t *prev = NULL);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -103,7 +111,8 @@ class IRMideaAC {
IRsendTest _irsend;
#endif
uint64_t remote_state;
- void checksum();
+ bool _SwingVToggle;
+ void checksum(void);
static uint8_t calcChecksum(const uint64_t state);
};
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.cpp
similarity index 66%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.cpp
index ca9bef5d9..c78b1d21a 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.cpp
@@ -2,6 +2,8 @@
// Copyright 2017-2018 David Conran
// Copyright 2018 Denes Varga
+// Mitsubishi
+
#include "ir_Mitsubishi.h"
#include
#ifndef ARDUINO
@@ -11,12 +13,6 @@
#include "IRsend.h"
#include "IRutils.h"
-// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII
-// M M M I T S U U B B I S H H I
-// M M M I T SSS U U BBBB I SSS HHHHH I
-// M M I T S U U B B I S H H I
-// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII
-
// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote
// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran
@@ -42,7 +38,7 @@ const uint16_t kMitsubishiMinGap = kMitsubishiMinGapTicks * kMitsubishiTick;
// Mitsubishi Projector (HC3000)
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/441
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/441
const uint16_t kMitsubishi2HdrMark = 8400;
const uint16_t kMitsubishi2HdrSpace = kMitsubishi2HdrMark / 2;
@@ -63,6 +59,14 @@ const uint16_t kMitsubishiAcZeroSpace = 420;
const uint16_t kMitsubishiAcRptMark = 440;
const uint16_t kMitsubishiAcRptSpace = 17100;
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+using irutils::minsToString;
+
#if SEND_MITSUBISHI
// Send a Mitsubishi message
//
@@ -105,44 +109,23 @@ void IRsend::sendMitsubishi(uint64_t data, uint16_t nbits, uint16_t repeat) {
// GlobalCache's Control Tower's Mitsubishi TV data.
bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits,
bool strict) {
- if (results->rawlen < 2 * nbits + kFooter - 1)
- return false; // Shorter than shortest possibly expected.
if (strict && nbits != kMitsubishiBits)
return false; // Request is out of spec.
uint16_t offset = kStartOffset;
uint64_t data = 0;
- // No Header
- // But try to auto-calibrate off the initial mark signal.
- if (!matchMark(results->rawbuf[offset], kMitsubishiBitMark, 30)) return false;
- // Calculate how long the common tick time is based on the initial mark.
- uint32_t tick = results->rawbuf[offset] * kRawTick / kMitsubishiBitMarkTicks;
-
- // Data
- match_result_t data_result = matchData(
- &(results->rawbuf[offset]), nbits, kMitsubishiBitMarkTicks * tick,
- kMitsubishiOneSpaceTicks * tick, kMitsubishiBitMarkTicks * tick,
- kMitsubishiZeroSpaceTicks * tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
- uint16_t actualBits = data_result.used / 2;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kMitsubishiBitMarkTicks * tick, 30))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kMitsubishiMinGapTicks * tick))
- return false;
-
- // Compliance
- if (actualBits < nbits) return false;
- if (strict && actualBits != nbits) return false; // Not as we expected.
-
+ // Match Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ 0, 0, // No header
+ kMitsubishiBitMark, kMitsubishiOneSpace,
+ kMitsubishiBitMark, kMitsubishiZeroSpace,
+ kMitsubishiBitMark, kMitsubishiMinGap,
+ true, 30)) return false;
// Success
results->decode_type = MITSUBISHI;
- results->bits = actualBits;
+ results->bits = nbits;
results->value = data;
results->address = 0;
results->command = 0;
@@ -168,7 +151,7 @@ bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits,
// i.e. Allegedly, the real remote requires the "Off" button pressed twice.
// You will need to add a suitable gap yourself.
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/441
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/441
void IRsend::sendMitsubishi2(uint64_t data, uint16_t nbits, uint16_t repeat) {
for (uint16_t i = 0; i <= repeat; i++) {
// First half of the data.
@@ -203,7 +186,7 @@ void IRsend::sendMitsubishi2(uint64_t data, uint16_t nbits, uint16_t repeat) {
// * Mitsubishi HC3000 projector's remote.
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/441
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/441
bool IRrecv::decodeMitsubishi2(decode_results *results, uint16_t nbits,
bool strict) {
if (results->rawlen < 2 * nbits + kHeader + (kFooter * 2) - 1)
@@ -212,47 +195,34 @@ bool IRrecv::decodeMitsubishi2(decode_results *results, uint16_t nbits,
return false; // Request is out of spec.
uint16_t offset = kStartOffset;
- uint64_t data = 0;
- uint16_t actualBits = 0;
+ results->value = 0;
// Header
if (!matchMark(results->rawbuf[offset++], kMitsubishi2HdrMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kMitsubishi2HdrSpace))
return false;
- for (uint8_t i = 1; i <= 2; i++) {
- // Data
- match_result_t data_result = matchData(
- &(results->rawbuf[offset]), nbits / 2, kMitsubishi2BitMark,
- kMitsubishi2OneSpace, kMitsubishi2BitMark, kMitsubishi2ZeroSpace);
- if (data_result.success == false) return false;
- data <<= nbits / 2;
- data += data_result.data;
- offset += data_result.used;
- actualBits += data_result.used / 2;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kMitsubishi2BitMark))
- return false;
- if (i % 2) { // Every odd data block, we expect a HDR space.
- if (!matchSpace(results->rawbuf[offset++], kMitsubishi2HdrSpace))
- return false;
- } else { // Every even data block, we expect Min Gap or end of the message.
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kMitsubishi2MinGap))
- return false;
- }
+ for (uint8_t i = 0; i < 2; i++) {
+ // Match Data + Footer
+ uint16_t used;
+ uint64_t data = 0;
+ used = matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits / 2,
+ 0, 0, // No header
+ kMitsubishi2BitMark, kMitsubishi2OneSpace,
+ kMitsubishi2BitMark, kMitsubishi2ZeroSpace,
+ kMitsubishi2BitMark, kMitsubishi2HdrSpace,
+ i % 2);
+ if (!used) return false;
+ offset += used;
+ results->value <<= (nbits / 2);
+ results->value += data;
}
- // Compliance
- if (actualBits < nbits) return false;
- if (strict && actualBits != nbits) return false; // Not as we expected.
-
// Success
results->decode_type = MITSUBISHI2;
- results->bits = actualBits;
- results->value = data;
- results->address = data >> actualBits / 2;
- results->command = data & ((1 << (actualBits / 2)) - 1);
+ results->bits = nbits;
+ results->address = results->value >> (nbits / 2);
+ results->command = results->value & ((1 << (nbits / 2)) - 1);
return true;
}
#endif // DECODE_MITSUBISHI2
@@ -268,8 +238,8 @@ bool IRrecv::decodeMitsubishi2(decode_results *results, uint16_t nbits,
//
// Status: BETA / Appears to be working.
//
-void IRsend::sendMitsubishiAC(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
+void IRsend::sendMitsubishiAC(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kMitsubishiACStateLength)
return; // Not enough bytes to send a proper message.
@@ -313,7 +283,7 @@ bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits,
do {
failure = false;
// Header:
- // Somtime happens that junk signals arrives before the real message
+ // Sometime happens that junk signals arrives before the real message
bool headerFound = false;
while (!headerFound &&
offset < (results->rawlen - (kMitsubishiACBits * 2 + 2))) {
@@ -332,7 +302,7 @@ bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits,
data_result =
matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark,
kMitsubishiAcOneSpace, kMitsubishiAcBitMark,
- kMitsubishiAcZeroSpace, kTolerance, kMarkExcess, false);
+ kMitsubishiAcZeroSpace, _tolerance, kMarkExcess, false);
if (data_result.success == false) {
failure = true;
DPRINT("Byte decode failed at #");
@@ -395,7 +365,7 @@ bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits,
data_result =
matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark,
kMitsubishiAcOneSpace, kMitsubishiAcBitMark,
- kMitsubishiAcZeroSpace, kTolerance, kMarkExcess, false);
+ kMitsubishiAcZeroSpace, _tolerance, kMarkExcess, false);
if (data_result.success == false ||
data_result.data != results->state[i]) {
DPRINTLN("Repeat payload error.");
@@ -420,10 +390,12 @@ bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits,
// Equipment it seems compatible with:
// *
// Initialise the object.
-IRMitsubishiAC::IRMitsubishiAC(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRMitsubishiAC::IRMitsubishiAC(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
// Reset the state of the remote to a known good state/sequence.
-void IRMitsubishiAC::stateReset() {
+void IRMitsubishiAC::stateReset(void) {
// The state of the IR remote in IR code form.
// Known good state obtained from:
// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L108
@@ -445,39 +417,39 @@ void IRMitsubishiAC::stateReset() {
for (uint8_t i = 11; i < kMitsubishiACStateLength - 1; i++)
remote_state[i] = 0;
remote_state[kMitsubishiACStateLength - 1] = 0x1F;
- checksum(); // Calculate the checksum
+ this->checksum(); // Calculate the checksum
}
// Configure the pin for output.
-void IRMitsubishiAC::begin() { _irsend.begin(); }
+void IRMitsubishiAC::begin(void) { _irsend.begin(); }
#if SEND_MITSUBISHI_AC
// Send the current desired state to the IR LED.
void IRMitsubishiAC::send(const uint16_t repeat) {
- checksum(); // Ensure correct checksum before sending.
+ this->checksum(); // Ensure correct checksum before sending.
_irsend.sendMitsubishiAC(remote_state, kMitsubishiACStateLength, repeat);
}
#endif // SEND_MITSUBISHI_AC
// Return a pointer to the internal state date of the remote.
-uint8_t *IRMitsubishiAC::getRaw() {
- checksum();
+uint8_t *IRMitsubishiAC::getRaw(void) {
+ this->checksum();
return remote_state;
}
-void IRMitsubishiAC::setRaw(uint8_t *data) {
+void IRMitsubishiAC::setRaw(const uint8_t *data) {
for (uint8_t i = 0; i < (kMitsubishiACStateLength - 1); i++) {
remote_state[i] = data[i];
}
- checksum();
+ this->checksum();
}
// Calculate the checksum for the current internal state of the remote.
-void IRMitsubishiAC::checksum() {
- remote_state[17] = calculateChecksum(remote_state);
+void IRMitsubishiAC::checksum(void) {
+ remote_state[17] = this->calculateChecksum(remote_state);
}
-uint8_t IRMitsubishiAC::calculateChecksum(uint8_t *data) {
+uint8_t IRMitsubishiAC::calculateChecksum(const uint8_t *data) {
uint8_t sum = 0;
// Checksum is simple addition of all previous bytes stored
// as an 8 bit value.
@@ -486,45 +458,46 @@ uint8_t IRMitsubishiAC::calculateChecksum(uint8_t *data) {
}
// Set the requested power state of the A/C to off.
-void IRMitsubishiAC::on() {
+void IRMitsubishiAC::on(void) {
// state = ON;
remote_state[5] |= kMitsubishiAcPower;
}
// Set the requested power state of the A/C to off.
-void IRMitsubishiAC::off() {
+void IRMitsubishiAC::off(void) {
// state = OFF;
remote_state[5] &= ~kMitsubishiAcPower;
}
// Set the requested power state of the A/C.
-void IRMitsubishiAC::setPower(bool state) {
- if (state)
- on();
+void IRMitsubishiAC::setPower(bool on) {
+ if (on)
+ this->on();
else
- off();
+ this->off();
}
// Return the requested power state of the A/C.
-bool IRMitsubishiAC::getPower() {
+bool IRMitsubishiAC::getPower(void) {
return ((remote_state[5] & kMitsubishiAcPower) != 0);
}
// Set the temp. in deg C
-void IRMitsubishiAC::setTemp(uint8_t temp) {
- temp = std::max((uint8_t)kMitsubishiAcMinTemp, temp);
+void IRMitsubishiAC::setTemp(const uint8_t degrees) {
+ uint8_t temp = std::max((uint8_t)kMitsubishiAcMinTemp, degrees);
temp = std::min((uint8_t)kMitsubishiAcMaxTemp, temp);
remote_state[7] = temp - kMitsubishiAcMinTemp;
}
// Return the set temp. in deg C
-uint8_t IRMitsubishiAC::getTemp() {
+uint8_t IRMitsubishiAC::getTemp(void) {
return (remote_state[7] + kMitsubishiAcMinTemp);
}
// Set the speed of the fan, 0-6.
// 0 is auto, 1-5 is the speed, 6 is silent.
-void IRMitsubishiAC::setFan(uint8_t fan) {
+void IRMitsubishiAC::setFan(const uint8_t speed) {
+ uint8_t fan = speed;
// Bounds check
if (fan > kMitsubishiAcFanSilent)
fan = kMitsubishiAcFanMax; // Set the fan to maximum if out of range.
@@ -539,17 +512,17 @@ void IRMitsubishiAC::setFan(uint8_t fan) {
}
// Return the requested state of the unit's fan.
-uint8_t IRMitsubishiAC::getFan() {
+uint8_t IRMitsubishiAC::getFan(void) {
uint8_t fan = remote_state[9] & 0b111;
if (fan == kMitsubishiAcFanMax) return kMitsubishiAcFanSilent;
return fan;
}
// Return the requested climate operation mode of the a/c unit.
-uint8_t IRMitsubishiAC::getMode() { return (remote_state[6]); }
+uint8_t IRMitsubishiAC::getMode(void) { return (remote_state[6]); }
// Set the requested climate operation mode of the a/c unit.
-void IRMitsubishiAC::setMode(uint8_t mode) {
+void IRMitsubishiAC::setMode(const uint8_t mode) {
// If we get an unexpected mode, default to AUTO.
switch (mode) {
case kMitsubishiAcAuto:
@@ -565,48 +538,67 @@ void IRMitsubishiAC::setMode(uint8_t mode) {
remote_state[8] = 0b00110000;
break;
default:
- mode = kMitsubishiAcAuto;
- remote_state[8] = 0b00110000;
+ this->setMode(kMitsubishiAcAuto);
+ return;
}
remote_state[6] = mode;
}
// Set the requested vane operation mode of the a/c unit.
-void IRMitsubishiAC::setVane(uint8_t mode) {
- mode = std::min(mode, (uint8_t)0b111); // bounds check
- mode |= 0b1000;
- mode <<= 3;
+void IRMitsubishiAC::setVane(const uint8_t position) {
+ uint8_t pos = std::min(position, (uint8_t)0b111); // bounds check
+ pos |= 0b1000;
+ pos <<= 3;
remote_state[9] &= 0b11000111; // Clear the previous setting.
- remote_state[9] |= mode;
+ remote_state[9] |= pos;
+}
+
+// Set the requested wide-vane operation mode of the a/c unit.
+void IRMitsubishiAC::setWideVane(const uint8_t position) {
+ uint8_t pos = std::min(position, kMitsubishiAcWideVaneAuto); // bounds check
+ pos <<= 4;
+ remote_state[8] &= 0b00001111; // Clear the previous setting.
+ remote_state[8] |= pos;
}
// Return the requested vane operation mode of the a/c unit.
-uint8_t IRMitsubishiAC::getVane() {
+uint8_t IRMitsubishiAC::getVane(void) {
return ((remote_state[9] & 0b00111000) >> 3);
}
+// Return the requested wide vane operation mode of the a/c unit.
+uint8_t IRMitsubishiAC::getWideVane(void) {
+ return (remote_state[8] >> 4);
+}
+
// Return the clock setting of the message. 1=1/6 hour. e.g. 4pm = 48
-uint8_t IRMitsubishiAC::getClock() { return remote_state[10]; }
+uint8_t IRMitsubishiAC::getClock(void) { return remote_state[10]; }
// Set the current time. 1 = 1/6 hour. e.g. 6am = 36.
-void IRMitsubishiAC::setClock(uint8_t clock) { remote_state[10] = clock; }
+void IRMitsubishiAC::setClock(const uint8_t clock) {
+ remote_state[10] = clock;
+}
// Return the desired start time. 1 = 1/6 hour. e.g. 1am = 6
-uint8_t IRMitsubishiAC::getStartClock() { return remote_state[12]; }
+uint8_t IRMitsubishiAC::getStartClock(void) { return remote_state[12]; }
-// Set the desired start tiem of the AC. 1 = 1/6 hour. e.g. 8pm = 120
-void IRMitsubishiAC::setStartClock(uint8_t clock) { remote_state[12] = clock; }
+// Set the desired start time of the AC. 1 = 1/6 hour. e.g. 8pm = 120
+void IRMitsubishiAC::setStartClock(const uint8_t clock) {
+ remote_state[12] = clock;
+}
// Return the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132
-uint8_t IRMitsubishiAC::getStopClock() { return remote_state[11]; }
+uint8_t IRMitsubishiAC::getStopClock(void) { return remote_state[11]; }
// Set the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132
-void IRMitsubishiAC::setStopClock(uint8_t clock) { remote_state[11] = clock; }
+void IRMitsubishiAC::setStopClock(const uint8_t clock) {
+ remote_state[11] = clock;
+}
// Return the timer setting. Possible values: kMitsubishiAcNoTimer,
// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer,
// kMitsubishiAcStartStopTimer
-uint8_t IRMitsubishiAC::getTimer() { return remote_state[13] & 0b111; }
+uint8_t IRMitsubishiAC::getTimer(void) { return remote_state[13] & 0b111; }
// Set the timer setting. Possible values: kMitsubishiAcNoTimer,
// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer,
@@ -651,78 +643,131 @@ uint8_t IRMitsubishiAC::convertFan(const stdAc::fanspeed_t speed) {
uint8_t IRMitsubishiAC::convertSwingV(const stdAc::swingv_t position) {
switch (position) {
case stdAc::swingv_t::kHighest:
+ return kMitsubishiAcVaneAutoMove - 6;
case stdAc::swingv_t::kHigh:
+ return kMitsubishiAcVaneAutoMove - 5;
case stdAc::swingv_t::kMiddle:
+ return kMitsubishiAcVaneAutoMove - 4;
case stdAc::swingv_t::kLow:
+ return kMitsubishiAcVaneAutoMove - 3;
case stdAc::swingv_t::kLowest:
- return kMitsubishiAcVaneAutoMove;
+ return kMitsubishiAcVaneAutoMove - 2;
+ case stdAc::swingv_t::kAuto:
+ return kMitsubishiAcVaneAutoMove;
default:
- return kMitsubishiAcVaneAuto;
+ return kMitsubishiAcVaneAuto;
}
}
-#ifdef ARDUINO
-String IRMitsubishiAC::timeToString(uint64_t time) {
- String result = "";
-#else
-std::string IRMitsubishiAC::timeToString(uint64_t time) {
- std::string result = "";
-#endif // ARDUINO
- if (time / 6 < 10) result += '0';
- result += uint64ToString(time / 6);
- result += ':';
- if (time * 10 % 60 < 10) result += '0';
- result += uint64ToString(time * 10 % 60);
+// Convert a standard A/C wide wane swing into its native setting.
+uint8_t IRMitsubishiAC::convertSwingH(const stdAc::swingh_t position) {
+ switch (position) {
+ case stdAc::swingh_t::kLeftMax:
+ return kMitsubishiAcWideVaneAuto - 7;
+ case stdAc::swingh_t::kLeft:
+ return kMitsubishiAcWideVaneAuto - 6;
+ case stdAc::swingh_t::kMiddle:
+ return kMitsubishiAcWideVaneAuto - 5;
+ case stdAc::swingh_t::kRight:
+ return kMitsubishiAcWideVaneAuto - 4;
+ case stdAc::swingh_t::kRightMax:
+ return kMitsubishiAcWideVaneAuto - 3;
+ case stdAc::swingh_t::kWide:
+ return kMitsubishiAcWideVaneAuto - 2;
+ case stdAc::swingh_t::kAuto:
+ return kMitsubishiAcWideVaneAuto;
+ default:
+ return kMitsubishiAcWideVaneAuto - 5;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRMitsubishiAC::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kMitsubishiAcCool: return stdAc::opmode_t::kCool;
+ case kMitsubishiAcHeat: return stdAc::opmode_t::kHeat;
+ case kMitsubishiAcDry: return stdAc::opmode_t::kDry;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRMitsubishiAC::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kMitsubishiAcFanRealMax: return stdAc::fanspeed_t::kMax;
+ case kMitsubishiAcFanRealMax - 1: return stdAc::fanspeed_t::kHigh;
+ case kMitsubishiAcFanRealMax - 2: return stdAc::fanspeed_t::kMedium;
+ case kMitsubishiAcFanRealMax - 3: return stdAc::fanspeed_t::kLow;
+ case kMitsubishiAcFanSilent: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingv_t IRMitsubishiAC::toCommonSwingV(const uint8_t pos) {
+ switch (pos) {
+ case 1: return stdAc::swingv_t::kHighest;
+ case 2: return stdAc::swingv_t::kHigh;
+ case 3: return stdAc::swingv_t::kMiddle;
+ case 4: return stdAc::swingv_t::kLow;
+ case 5: return stdAc::swingv_t::kLowest;
+ default: return stdAc::swingv_t::kAuto;
+ }
+}
+
+// Convert a native horizontal swing to it's common equivalent.
+stdAc::swingh_t IRMitsubishiAC::toCommonSwingH(const uint8_t pos) {
+ switch (pos) {
+ case 1: return stdAc::swingh_t::kLeftMax;
+ case 2: return stdAc::swingh_t::kLeft;
+ case 3: return stdAc::swingh_t::kMiddle;
+ case 4: return stdAc::swingh_t::kRight;
+ case 5: return stdAc::swingh_t::kRightMax;
+ case 6: return stdAc::swingh_t::kWide;
+ default: return stdAc::swingh_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRMitsubishiAC::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::MITSUBISHI_AC;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->toCommonSwingV(this->getVane());
+ result.swingh = this->toCommonSwingH(this->getWideVane());
+ result.quiet = this->getFan() == kMitsubishiAcFanSilent;
+ // Not supported.
+ result.turbo = false;
+ result.clean = false;
+ result.econo = false;
+ result.filter = false;
+ result.light = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
return result;
}
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRMitsubishiAC::toString() {
+String IRMitsubishiAC::toString(void) {
String result = "";
-#else
-std::string IRMitsubishiAC::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- switch (getMode()) {
- case MITSUBISHI_AC_AUTO:
- result += F(" (AUTO)");
- break;
- case MITSUBISHI_AC_COOL:
- result += F(" (COOL)");
- break;
- case MITSUBISHI_AC_DRY:
- result += F(" (DRY)");
- break;
- case MITSUBISHI_AC_HEAT:
- result += F(" (HEAT)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, FAN: ");
- switch (getFan()) {
- case MITSUBISHI_AC_FAN_AUTO:
- result += F("AUTO");
- break;
- case MITSUBISHI_AC_FAN_MAX:
- result += F("MAX");
- break;
- case MITSUBISHI_AC_FAN_SILENT:
- result += F("SILENT");
- break;
- default:
- result += uint64ToString(getFan());
- }
- result += F(", VANE: ");
- switch (getVane()) {
+ result.reserve(110); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kMitsubishiAcAuto, kMitsubishiAcCool,
+ kMitsubishiAcHeat, kMitsubishiAcDry,
+ kMitsubishiAcAuto);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kMitsubishiAcFanRealMax,
+ kMitsubishiAcFanRealMax - 3,
+ kMitsubishiAcFanAuto, kMitsubishiAcFanQuiet,
+ kMitsubishiAcFanRealMax - 2);
+ result += F(", Vane: ");
+ switch (this->getVane()) {
case MITSUBISHI_AC_VANE_AUTO:
result += F("AUTO");
break;
@@ -730,16 +775,21 @@ std::string IRMitsubishiAC::toString() {
result += F("AUTO MOVE");
break;
default:
- result += uint64ToString(getVane());
+ result += uint64ToString(this->getVane());
}
- result += F(", Time: ");
- result += timeToString(getClock());
- result += F(", On timer: ");
- result += timeToString(getStartClock());
- result += F(", Off timer: ");
- result += timeToString(getStopClock());
+ result += F(", Wide Vane: ");
+ switch (this->getWideVane()) {
+ case kMitsubishiAcWideVaneAuto:
+ result += F("AUTO");
+ break;
+ default:
+ result += uint64ToString(this->getWideVane());
+ }
+ result += addLabeledString(minsToString(getClock() * 10), F("Time"));
+ result += addLabeledString(minsToString(getStartClock() * 10), F("On timer"));
+ result += addLabeledString(minsToString(getStopClock() * 10), F("Off timer"));
result += F(", Timer: ");
- switch (getTimer()) {
+ switch (this->getTimer()) {
case kMitsubishiAcNoTimer:
result += '-';
break;
@@ -754,7 +804,7 @@ std::string IRMitsubishiAC::toString() {
break;
default:
result += F("? (");
- result += getTimer();
+ result += this->getTimer();
result += F(")\n");
}
return result;
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.h
similarity index 58%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.h
index c8dca5dbc..ac67082dc 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.h
@@ -1,5 +1,12 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017 David Conran
+
+// Mitsubishi
+
+// Supports:
+// Brand: Mitsubishi, Model: TV
+// Brand: Mitsubishi, Model: HC3000 Projector
+
#ifndef IR_MITSUBISHI_H_
#define IR_MITSUBISHI_H_
@@ -7,8 +14,6 @@
#include
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -16,12 +21,6 @@
#include "IRsend_test.h"
#endif
-// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII
-// M M M I T S U U B B I S H H I
-// M M M I T SSS U U BBBB I SSS HHHHH I
-// M M I T S U U B B I S H H I
-// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII
-
// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote
// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran
@@ -35,6 +34,7 @@ const uint8_t kMitsubishiAcFanAuto = 0;
const uint8_t kMitsubishiAcFanMax = 5;
const uint8_t kMitsubishiAcFanRealMax = 4;
const uint8_t kMitsubishiAcFanSilent = 6;
+const uint8_t kMitsubishiAcFanQuiet = kMitsubishiAcFanSilent;
const uint8_t kMitsubishiAcMinTemp = 16; // 16C
const uint8_t kMitsubishiAcMaxTemp = 31; // 31C
const uint8_t kMitsubishiAcVaneAuto = 0;
@@ -43,6 +43,7 @@ const uint8_t kMitsubishiAcNoTimer = 0;
const uint8_t kMitsubishiAcStartTimer = 5;
const uint8_t kMitsubishiAcStopTimer = 3;
const uint8_t kMitsubishiAcStartStopTimer = 7;
+const uint8_t kMitsubishiAcWideVaneAuto = 8;
// Legacy defines (Deprecated)
#define MITSUBISHI_AC_VANE_AUTO_MOVE kMitsubishiAcVaneAutoMove
@@ -61,59 +62,60 @@ const uint8_t kMitsubishiAcStartStopTimer = 7;
class IRMitsubishiAC {
public:
- explicit IRMitsubishiAC(uint16_t pin);
+ explicit IRMitsubishiAC(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
- static uint8_t calculateChecksum(uint8_t* data);
+ static uint8_t calculateChecksum(const uint8_t* data);
- void stateReset();
+ void stateReset(void);
#if SEND_MITSUBISHI_AC
void send(const uint16_t repeat = kMitsubishiACMinRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_MITSUBISHI_AC
- void begin();
- void on();
- void off();
- void setPower(bool state);
- bool getPower();
- void setTemp(uint8_t temp);
- uint8_t getTemp();
- void setFan(uint8_t fan);
- uint8_t getFan();
- void setMode(uint8_t mode);
- uint8_t getMode();
- void setVane(uint8_t mode);
- uint8_t getVane();
- uint8_t* getRaw();
- void setRaw(uint8_t* data);
- uint8_t getClock();
- void setClock(uint8_t clock);
- uint8_t getStartClock();
- void setStartClock(uint8_t clock);
- uint8_t getStopClock();
- void setStopClock(uint8_t clock);
- uint8_t getTimer();
- void setTimer(uint8_t timer);
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t degrees);
+ uint8_t getTemp(void);
+ void setFan(const uint8_t speed);
+ uint8_t getFan(void);
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ void setVane(const uint8_t position);
+ void setWideVane(const uint8_t position);
+ uint8_t getVane(void);
+ uint8_t getWideVane(void);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t* data);
+ uint8_t getClock(void);
+ void setClock(const uint8_t clock);
+ uint8_t getStartClock(void);
+ void setStartClock(const uint8_t clock);
+ uint8_t getStopClock(void);
+ void setStopClock(const uint8_t clock);
+ uint8_t getTimer(void);
+ void setTimer(const uint8_t timer);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
uint8_t convertSwingV(const stdAc::swingv_t position);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ uint8_t convertSwingH(const stdAc::swingh_t position);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ static stdAc::swingv_t toCommonSwingV(const uint8_t pos);
+ static stdAc::swingh_t toCommonSwingH(const uint8_t pos);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
IRsend _irsend;
#else
IRsendTest _irsend;
-#endif
-#ifdef ARDUINO
- String timeToString(uint64_t time);
-#else
- std::string timeToString(uint64_t time);
#endif
uint8_t remote_state[kMitsubishiACStateLength];
- void checksum();
+ void checksum(void);
};
#endif // IR_MITSUBISHI_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.cpp
similarity index 73%
rename from lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.cpp
index 9048124d4..6b4295991 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.cpp
@@ -22,7 +22,7 @@
#endif
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/660
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/660
// https://github.com/ToniA/Raw-IR-decoder-for-Arduino/blob/master/MitsubishiHeavy.cpp
// https://github.com/ToniA/arduino-heatpumpir/blob/master/MitsubishiHeavyHeatpumpIR.cpp
@@ -34,6 +34,12 @@ const uint16_t kMitsubishiHeavyOneSpace = 420;
const uint16_t kMitsubishiHeavyZeroSpace = 1220;
const uint32_t kMitsubishiHeavyGap = kDefaultMessageGap; // Just a guess.
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
#if SEND_MITSUBISHIHEAVY
// Send a MitsubishiHeavy 88 bit A/C message.
//
@@ -73,10 +79,12 @@ void IRsend::sendMitsubishiHeavy152(const unsigned char data[],
#endif // SEND_MITSUBISHIHEAVY
// Class for decoding and constructing MitsubishiHeavy152 AC messages.
-IRMitsubishiHeavy152Ac::IRMitsubishiHeavy152Ac(
- const uint16_t pin) : _irsend(pin) { stateReset(); }
+IRMitsubishiHeavy152Ac::IRMitsubishiHeavy152Ac(const uint16_t pin,
+ const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
-void IRMitsubishiHeavy152Ac::begin() { _irsend.begin(); }
+void IRMitsubishiHeavy152Ac::begin(void) { _irsend.begin(); }
#if SEND_MITSUBISHIHEAVY
void IRMitsubishiHeavy152Ac::send(const uint16_t repeat) {
@@ -303,7 +311,6 @@ bool IRMitsubishiHeavy152Ac::validChecksum(const uint8_t *state,
return true;
}
-
// Convert a standard A/C mode into its native mode.
uint8_t IRMitsubishiHeavy152Ac::convertMode(const stdAc::opmode_t mode) {
switch (mode) {
@@ -378,68 +385,118 @@ uint8_t IRMitsubishiHeavy152Ac::convertSwingH(const stdAc::swingh_t position) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRMitsubishiHeavy152Ac::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kMitsubishiHeavyCool: return stdAc::opmode_t::kCool;
+ case kMitsubishiHeavyHeat: return stdAc::opmode_t::kHeat;
+ case kMitsubishiHeavyDry: return stdAc::opmode_t::kDry;
+ case kMitsubishiHeavyFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRMitsubishiHeavy152Ac::toCommonFanSpeed(const uint8_t spd) {
+ switch (spd) {
+ case kMitsubishiHeavy152FanMax: return stdAc::fanspeed_t::kMax;
+ case kMitsubishiHeavy152FanHigh: return stdAc::fanspeed_t::kHigh;
+ case kMitsubishiHeavy152FanMed: return stdAc::fanspeed_t::kMedium;
+ case kMitsubishiHeavy152FanLow: return stdAc::fanspeed_t::kLow;
+ case kMitsubishiHeavy152FanEcono: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingh_t IRMitsubishiHeavy152Ac::toCommonSwingH(const uint8_t pos) {
+ switch (pos) {
+ case kMitsubishiHeavy152SwingHLeftMax: return stdAc::swingh_t::kLeftMax;
+ case kMitsubishiHeavy152SwingHLeft: return stdAc::swingh_t::kLeft;
+ case kMitsubishiHeavy152SwingHMiddle: return stdAc::swingh_t::kMiddle;
+ case kMitsubishiHeavy152SwingHRight: return stdAc::swingh_t::kRight;
+ case kMitsubishiHeavy152SwingHRightMax: return stdAc::swingh_t::kRightMax;
+ case kMitsubishiHeavy152SwingHOff: return stdAc::swingh_t::kOff;
+ default: return stdAc::swingh_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingv_t IRMitsubishiHeavy152Ac::toCommonSwingV(const uint8_t pos) {
+ switch (pos) {
+ case kMitsubishiHeavy152SwingVHighest: return stdAc::swingv_t::kHighest;
+ case kMitsubishiHeavy152SwingVHigh: return stdAc::swingv_t::kHigh;
+ case kMitsubishiHeavy152SwingVMiddle: return stdAc::swingv_t::kMiddle;
+ case kMitsubishiHeavy152SwingVLow: return stdAc::swingv_t::kLow;
+ case kMitsubishiHeavy152SwingVLowest: return stdAc::swingv_t::kLowest;
+ case kMitsubishiHeavy152SwingVOff: return stdAc::swingv_t::kOff;
+ default: return stdAc::swingv_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRMitsubishiHeavy152Ac::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::MITSUBISHI_HEAVY_152;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->toCommonSwingV(this->getSwingVertical());
+ result.swingh = this->toCommonSwingH(this->getSwingHorizontal());
+ result.turbo = this->getTurbo();
+ result.econo = this->getEcono();
+ result.clean = this->getClean();
+ result.quiet = this->getSilent();
+ result.filter = this->getFilter();
+ result.sleep = this->getNight() ? 0 : -1;
+ // Not supported.
+ result.light = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
String IRMitsubishiHeavy152Ac::toString(void) {
String result = "";
-#else
-std::string IRMitsubishiHeavy152Ac::toString(void) {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- result += (this->getPower() ? F("On") : F("Off"));
- result += F(", Mode: ");
- result += uint64ToString(this->getMode());
- switch (this->getMode()) {
- case kMitsubishiHeavyAuto:
- result += F(" (Auto)");
- break;
- case kMitsubishiHeavyCool:
- result += F(" (Cool)");
- break;
- case kMitsubishiHeavyHeat:
- result += F(" (Heat)");
- break;
- case kMitsubishiHeavyDry:
- result += F(" (Dry)");
- break;
- case kMitsubishiHeavyFan:
- result += F(" (Fan)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(this->getTemp()) + 'C';
- result += F(", Fan: ");
- result += uint64ToString(this->getFan());
+ result.reserve(180); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kMitsubishiHeavyAuto,
+ kMitsubishiHeavyCool, kMitsubishiHeavyHeat,
+ kMitsubishiHeavyDry, kMitsubishiHeavyFan);
+ result += addTempToString(getTemp());
+ result += addIntToString(getFan(), F("Fan"));
+ result += F(" (");
switch (this->getFan()) {
case kMitsubishiHeavy152FanAuto:
- result += F(" (Auto)");
+ result += F("Auto");
break;
case kMitsubishiHeavy152FanHigh:
- result += F(" (High)");
+ result += F("High");
break;
case kMitsubishiHeavy152FanLow:
- result += F(" (Low)");
+ result += F("Low");
break;
case kMitsubishiHeavy152FanMed:
- result += F(" (Med)");
+ result += F("Medium");
break;
case kMitsubishiHeavy152FanMax:
- result += F(" (Max)");
+ result += F("Max");
break;
case kMitsubishiHeavy152FanEcono:
- result += F(" (Econo)");
+ result += F("Econo");
break;
case kMitsubishiHeavy152FanTurbo:
- result += F(" (Turbo)");
+ result += F("Turbo");
break;
default:
- result += F(" (UNKNOWN)");
+ result += F("UNKNOWN");
}
- result += F(", Swing (V): ");
- result += uint64ToString(this->getSwingVertical());
+ result += ')';
+ result += addIntToString(getSwingVertical(), F("Swing (V)"));
switch (this->getSwingVertical()) {
case kMitsubishiHeavy152SwingVAuto:
result += F(" (Auto)");
@@ -465,8 +522,7 @@ std::string IRMitsubishiHeavy152Ac::toString(void) {
default:
result += F(" (UNKNOWN)");
}
- result += F(", Swing (H): ");
- result += uint64ToString(this->getSwingHorizontal());
+ result += addIntToString(getSwingHorizontal(), F("Swing (H)"));
switch (this->getSwingHorizontal()) {
case kMitsubishiHeavy152SwingHAuto:
result += F(" (Auto)");
@@ -498,29 +554,24 @@ std::string IRMitsubishiHeavy152Ac::toString(void) {
default:
result += F(" (UNKNOWN)");
}
- result += F(", Silent: ");
- result += (this->getSilent() ? F("On") : F("Off"));
- result += F(", Turbo: ");
- result += (this->getTurbo() ? F("On") : F("Off"));
- result += F(", Econo: ");
- result += (this->getEcono() ? F("On") : F("Off"));
- result += F(", Night: ");
- result += (this->getNight() ? F("On") : F("Off"));
- result += F(", Filter: ");
- result += (this->getFilter() ? F("On") : F("Off"));
- result += F(", 3D: ");
- result += (this->get3D() ? F("On") : F("Off"));
- result += F(", Clean: ");
- result += (this->getClean() ? F("On") : F("Off"));
+ result += addBoolToString(getSilent(), F("Silent"));
+ result += addBoolToString(getTurbo(), F("Turbo"));
+ result += addBoolToString(getEcono(), F("Econo"));
+ result += addBoolToString(getNight(), F("Night"));
+ result += addBoolToString(getFilter(), F("Filter"));
+ result += addBoolToString(get3D(), F("3D"));
+ result += addBoolToString(getClean(), F("Clean"));
return result;
}
// Class for decoding and constructing MitsubishiHeavy88 AC messages.
-IRMitsubishiHeavy88Ac::IRMitsubishiHeavy88Ac(
- const uint16_t pin) : _irsend(pin) { stateReset(); }
+IRMitsubishiHeavy88Ac::IRMitsubishiHeavy88Ac(const uint16_t pin,
+ const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
-void IRMitsubishiHeavy88Ac::begin() { _irsend.begin(); }
+void IRMitsubishiHeavy88Ac::begin(void) { _irsend.begin(); }
#if SEND_MITSUBISHIHEAVY
void IRMitsubishiHeavy88Ac::send(const uint16_t repeat) {
@@ -737,7 +788,6 @@ uint8_t IRMitsubishiHeavy88Ac::convertMode(const stdAc::opmode_t mode) {
return IRMitsubishiHeavy152Ac::convertMode(mode);
}
-
// Convert a standard A/C Fan speed into its native fan speed.
uint8_t IRMitsubishiHeavy88Ac::convertFan(const stdAc::fanspeed_t speed) {
switch (speed) {
@@ -796,65 +846,104 @@ uint8_t IRMitsubishiHeavy88Ac::convertSwingH(const stdAc::swingh_t position) {
}
}
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRMitsubishiHeavy88Ac::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kMitsubishiHeavy88FanTurbo: return stdAc::fanspeed_t::kMax;
+ case kMitsubishiHeavy88FanHigh: return stdAc::fanspeed_t::kHigh;
+ case kMitsubishiHeavy88FanMed: return stdAc::fanspeed_t::kMedium;
+ case kMitsubishiHeavy88FanLow: return stdAc::fanspeed_t::kLow;
+ case kMitsubishiHeavy88FanEcono: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingh_t IRMitsubishiHeavy88Ac::toCommonSwingH(const uint8_t pos) {
+ switch (pos) {
+ case kMitsubishiHeavy88SwingHLeftMax: return stdAc::swingh_t::kLeftMax;
+ case kMitsubishiHeavy88SwingHLeft: return stdAc::swingh_t::kLeft;
+ case kMitsubishiHeavy88SwingHMiddle: return stdAc::swingh_t::kMiddle;
+ case kMitsubishiHeavy88SwingHRight: return stdAc::swingh_t::kRight;
+ case kMitsubishiHeavy88SwingHRightMax: return stdAc::swingh_t::kRightMax;
+ case kMitsubishiHeavy88SwingHOff: return stdAc::swingh_t::kOff;
+ default: return stdAc::swingh_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingv_t IRMitsubishiHeavy88Ac::toCommonSwingV(const uint8_t pos) {
+ switch (pos) {
+ case kMitsubishiHeavy88SwingVHighest: return stdAc::swingv_t::kHighest;
+ case kMitsubishiHeavy88SwingVHigh: return stdAc::swingv_t::kHigh;
+ case kMitsubishiHeavy88SwingVMiddle: return stdAc::swingv_t::kMiddle;
+ case kMitsubishiHeavy88SwingVLow: return stdAc::swingv_t::kLow;
+ case kMitsubishiHeavy88SwingVLowest: return stdAc::swingv_t::kLowest;
+ case kMitsubishiHeavy88SwingVOff: return stdAc::swingv_t::kOff;
+ default: return stdAc::swingv_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRMitsubishiHeavy88Ac::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::MITSUBISHI_HEAVY_88;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = IRMitsubishiHeavy152Ac::toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->toCommonSwingV(this->getSwingVertical());
+ result.swingh = this->toCommonSwingH(this->getSwingHorizontal());
+ result.turbo = this->getTurbo();
+ result.econo = this->getEcono();
+ result.clean = this->getClean();
+ // Not supported.
+ result.quiet = false;
+ result.filter = false;
+ result.light = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
String IRMitsubishiHeavy88Ac::toString(void) {
String result = "";
-#else
-std::string IRMitsubishiHeavy88Ac::toString(void) {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- result += (this->getPower() ? F("On") : F("Off"));
- result += F(", Mode: ");
- result += uint64ToString(this->getMode());
- switch (this->getMode()) {
- case kMitsubishiHeavyAuto:
- result += F(" (Auto)");
- break;
- case kMitsubishiHeavyCool:
- result += F(" (Cool)");
- break;
- case kMitsubishiHeavyHeat:
- result += F(" (Heat)");
- break;
- case kMitsubishiHeavyDry:
- result += F(" (Dry)");
- break;
- case kMitsubishiHeavyFan:
- result += F(" (Fan)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(this->getTemp()) + 'C';
- result += F(", Fan: ");
- result += uint64ToString(this->getFan());
+ result.reserve(140); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kMitsubishiHeavyAuto,
+ kMitsubishiHeavyCool, kMitsubishiHeavyHeat,
+ kMitsubishiHeavyDry, kMitsubishiHeavyFan);
+ result += addTempToString(getTemp());
+ result += addIntToString(getFan(), F("Fan"));
+ result += F(" (");
switch (this->getFan()) {
case kMitsubishiHeavy88FanAuto:
- result += F(" (Auto)");
+ result += F("Auto");
break;
case kMitsubishiHeavy88FanHigh:
- result += F(" (High)");
+ result += F("High");
break;
case kMitsubishiHeavy88FanLow:
- result += F(" (Low)");
+ result += F("Low");
break;
case kMitsubishiHeavy88FanMed:
- result += F(" (Med)");
+ result += F("Medium");
break;
case kMitsubishiHeavy88FanEcono:
- result += F(" (Econo)");
+ result += F("Econo");
break;
case kMitsubishiHeavy88FanTurbo:
- result += F(" (Turbo)");
+ result += F("Turbo");
break;
default:
- result += F(" (UNKNOWN)");
+ result += F("UNKNOWN");
}
- result += F(", Swing (V): ");
- result += uint64ToString(this->getSwingVertical());
+ result += ')';
+ result += addIntToString(getSwingVertical(), F("Swing (V)"));
switch (this->getSwingVertical()) {
case kMitsubishiHeavy88SwingVAuto:
result += F(" (Auto)");
@@ -880,8 +969,7 @@ std::string IRMitsubishiHeavy88Ac::toString(void) {
default:
result += F(" (UNKNOWN)");
}
- result += F(", Swing (H): ");
- result += uint64ToString(this->getSwingHorizontal());
+ result += addIntToString(getSwingHorizontal(), F("Swing (H)"));
switch (this->getSwingHorizontal()) {
case kMitsubishiHeavy88SwingHAuto:
result += F(" (Auto)");
@@ -916,14 +1004,10 @@ std::string IRMitsubishiHeavy88Ac::toString(void) {
default:
result += F(" (UNKNOWN)");
}
- result += F(", Turbo: ");
- result += (this->getTurbo() ? F("On") : F("Off"));
- result += F(", Econo: ");
- result += (this->getEcono() ? F("On") : F("Off"));
- result += F(", 3D: ");
- result += (this->get3D() ? F("On") : F("Off"));
- result += F(", Clean: ");
- result += (this->getClean() ? F("On") : F("Off"));
+ result += addBoolToString(getTurbo(), F("Turbo"));
+ result += addBoolToString(getEcono(), F("Econo"));
+ result += addBoolToString(get3D(), F("3D"));
+ result += addBoolToString(getClean(), F("Clean"));
return result;
}
@@ -953,41 +1037,19 @@ bool IRrecv::decodeMitsubishiHeavy(decode_results* results,
}
}
- uint16_t actualBits = 0;
uint16_t offset = kStartOffset;
- match_result_t data_result;
-
- // Header
- if (!matchMark(results->rawbuf[offset++], kMitsubishiHeavyHdrMark))
- return false;
- if (!matchSpace(results->rawbuf[offset++], kMitsubishiHeavyHdrSpace))
- return false;
- // Data
- // Keep reading bytes until we either run out of section or state to fill.
- for (uint16_t i = 0;
- offset <= results->rawlen - 16 && actualBits < nbits;
- i++, actualBits += 8, offset += data_result.used) {
- data_result = matchData(&(results->rawbuf[offset]), 8,
- kMitsubishiHeavyBitMark, kMitsubishiHeavyOneSpace,
- kMitsubishiHeavyBitMark, kMitsubishiHeavyZeroSpace,
- kTolerance, 0, false);
- if (data_result.success == false) {
- DPRINT("DEBUG: offset = ");
- DPRINTLN(offset + data_result.used);
- return false; // Fail
- }
- results->state[i] = data_result.data;
- }
- // Footer.
- if (!matchMark(results->rawbuf[offset++], kMitsubishiHeavyBitMark))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kMitsubishiHeavyGap)) return false;
-
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kMitsubishiHeavyHdrMark, kMitsubishiHeavyHdrSpace,
+ kMitsubishiHeavyBitMark, kMitsubishiHeavyOneSpace,
+ kMitsubishiHeavyBitMark, kMitsubishiHeavyZeroSpace,
+ kMitsubishiHeavyBitMark, kMitsubishiHeavyGap, true,
+ _tolerance, 0, false);
+ if (used == 0) return false;
+ offset += used;
// Compliance
- if (actualBits < nbits) return false;
- if (strict && actualBits != nbits) return false; // Not as we expected.
- switch (actualBits) {
+ switch (nbits) {
case kMitsubishiHeavy88Bits:
if (strict && !(IRMitsubishiHeavy88Ac::checkZjsSig(results->state) &&
IRMitsubishiHeavy88Ac::validChecksum(results->state)))
@@ -1005,7 +1067,7 @@ bool IRrecv::decodeMitsubishiHeavy(decode_results* results,
}
// Success
- results->bits = actualBits;
+ results->bits = nbits;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.h b/lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.h
similarity index 86%
rename from lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.h
index bcd85c6e0..c52eeb951 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.h
@@ -1,12 +1,17 @@
// Copyright 2019 David Conran
+// Supports:
+// Brand: Mitsubishi Heavy Industries, Model: RLA502A700B remote
+// Brand: Mitsubishi Heavy Industries, Model: SRKxxZM-S A/C
+// Brand: Mitsubishi Heavy Industries, Model: SRKxxZMXA-S A/C
+// Brand: Mitsubishi Heavy Industries, Model: RKX502A001C remote
+// Brand: Mitsubishi Heavy Industries, Model: SRKxxZJ-S A/C
+
#ifndef IR_MITSUBISHIHEAVY_H_
#define IR_MITSUBISHIHEAVY_H_
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -15,7 +20,7 @@
#endif
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/660
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/660
// https://github.com/ToniA/Raw-IR-decoder-for-Arduino/blob/master/MitsubishiHeavy.cpp
// https://github.com/ToniA/arduino-heatpumpir/blob/master/MitsubishiHeavyHeatpumpIR.cpp
@@ -117,11 +122,14 @@ const uint8_t kMitsubishiHeavy88SwingVOff = 0b00000000; // 0x00
// Classes
class IRMitsubishiHeavy152Ac {
public:
- explicit IRMitsubishiHeavy152Ac(const uint16_t pin);
+ explicit IRMitsubishiHeavy152Ac(const uint16_t pin,
+ const bool inverted = false,
+ const bool use_modulation = true);
void stateReset(void);
#if SEND_MITSUBISHIHEAVY
void send(const uint16_t repeat = kMitsubishiHeavy152MinRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_MITSUBISHIHEAVY
void begin(void);
void on(void);
@@ -176,11 +184,12 @@ class IRMitsubishiHeavy152Ac {
static uint8_t convertFan(const stdAc::fanspeed_t speed);
static uint8_t convertSwingV(const stdAc::swingv_t position);
static uint8_t convertSwingH(const stdAc::swingh_t position);
-#ifdef ARDUINO
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ static stdAc::swingv_t toCommonSwingV(const uint8_t pos);
+ static stdAc::swingh_t toCommonSwingH(const uint8_t pos);
+ stdAc::state_t toCommon(void);
String toString(void);
-#else // ARDUINO
- std::string toString(void);
-#endif // ARDUINO
#ifndef UNIT_TEST
private:
@@ -190,12 +199,14 @@ class IRMitsubishiHeavy152Ac {
#endif // UNIT_TEST
// The state of the IR remote in IR code form.
uint8_t remote_state[kMitsubishiHeavy152StateLength];
- void checksum();
+ void checksum(void);
};
class IRMitsubishiHeavy88Ac {
public:
- explicit IRMitsubishiHeavy88Ac(const uint16_t pin);
+ explicit IRMitsubishiHeavy88Ac(const uint16_t pin,
+ const bool inverted = false,
+ const bool use_modulation = true);
void stateReset(void);
#if SEND_MITSUBISHIHEAVY
@@ -245,11 +256,11 @@ class IRMitsubishiHeavy88Ac {
static uint8_t convertFan(const stdAc::fanspeed_t speed);
static uint8_t convertSwingV(const stdAc::swingv_t position);
static uint8_t convertSwingH(const stdAc::swingh_t position);
-#ifdef ARDUINO
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ static stdAc::swingv_t toCommonSwingV(const uint8_t pos);
+ static stdAc::swingh_t toCommonSwingH(const uint8_t pos);
+ stdAc::state_t toCommon(void);
String toString(void);
-#else // ARDUINO
- std::string toString(void);
-#endif // ARDUINO
#ifndef UNIT_TEST
private:
@@ -259,6 +270,6 @@ class IRMitsubishiHeavy88Ac {
#endif // UNIT_TEST
// The state of the IR remote in IR code form.
uint8_t remote_state[kMitsubishiHeavy152StateLength];
- void checksum();
+ void checksum(void);
};
#endif // IR_MITSUBISHIHEAVY_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_NEC.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_NEC.cpp
similarity index 78%
rename from lib/IRremoteESP8266-2.6.0/src/ir_NEC.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_NEC.cpp
index 660b51109..03f68c1d9 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_NEC.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_NEC.cpp
@@ -1,6 +1,8 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017 David Conran
+// NEC originally added from https://github.com/shirriff/Arduino-IRremote/
+
#define __STDC_LIMIT_MACROS
#include "ir_NEC.h"
#include
@@ -9,16 +11,7 @@
#include "IRsend.h"
#include "IRutils.h"
-// N N EEEEE CCCC
-// NN N E C
-// N N N EEE C
-// N NN E C
-// N N EEEEE CCCC
-
-// NEC originally added from https://github.com/shirriff/Arduino-IRremote/
-
-#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO || \
- SEND_PIONEER)
+#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO)
// Send a raw NEC(Renesas) formatted message.
//
// Args:
@@ -68,7 +61,7 @@ uint32_t IRsend::encodeNEC(uint16_t address, uint16_t command) {
return (address << 24) + ((address ^ 0xFF) << 16) + command; // Normal.
}
}
-#endif
+#endif // (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO )
#if (DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || DECODE_SANYO)
// Decode the supplied NEC message.
@@ -103,13 +96,11 @@ bool IRrecv::decodeNEC(decode_results *results, uint16_t nbits, bool strict) {
uint16_t offset = kStartOffset;
// Header
- if (!matchMark(results->rawbuf[offset], kNecHdrMark)) return false;
- // Calculate how long the lowest tick time is based on the header mark.
- uint32_t mark_tick = results->rawbuf[offset++] * kRawTick / kNecHdrMarkTicks;
+ if (!matchMark(results->rawbuf[offset++], kNecHdrMark)) return false;
// Check if it is a repeat code.
if (results->rawlen == kNecRptLength &&
matchSpace(results->rawbuf[offset], kNecRptSpace) &&
- matchMark(results->rawbuf[offset + 1], kNecBitMarkTicks * mark_tick)) {
+ matchMark(results->rawbuf[offset + 1], kNecBitMark)) {
results->value = kRepeat;
results->decode_type = NEC;
results->bits = 0;
@@ -119,27 +110,13 @@ bool IRrecv::decodeNEC(decode_results *results, uint16_t nbits, bool strict) {
return true;
}
- // Header (cont.)
- if (!matchSpace(results->rawbuf[offset], kNecHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t space_tick =
- results->rawbuf[offset++] * kRawTick / kNecHdrSpaceTicks;
- // Data
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits, kNecBitMarkTicks * mark_tick,
- kNecOneSpaceTicks * space_tick, kNecBitMarkTicks * mark_tick,
- kNecZeroSpaceTicks * space_tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kNecBitMarkTicks * mark_tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kNecMinGapTicks * space_tick))
- return false;
-
+ // Match Header (cont.) + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ 0, kNecHdrSpace,
+ kNecBitMark, kNecOneSpace,
+ kNecBitMark, kNecZeroSpace,
+ kNecBitMark, kNecMinGap, true)) return false;
// Compliance
// Calculate command and optionally enforce integrity checking.
uint8_t command = (data & 0xFF00) >> 8;
@@ -166,4 +143,4 @@ bool IRrecv::decodeNEC(decode_results *results, uint16_t nbits, bool strict) {
results->address = reverseBits((data >> 16) & UINT16_MAX, 16);
return true;
}
-#endif
+#endif // DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || DECODE_SANYO
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_NEC.h b/lib/IRremoteESP8266-2.6.5/src/ir_NEC.h
similarity index 86%
rename from lib/IRremoteESP8266-2.6.0/src/ir_NEC.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_NEC.h
index c274c104e..e45ff702c 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_NEC.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_NEC.h
@@ -1,19 +1,17 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017, 2018 David Conran
+// NEC originally added from https://github.com/shirriff/Arduino-IRremote/
+
#ifndef IR_NEC_H_
#define IR_NEC_H_
#include
#include "IRremoteESP8266.h"
-// N N EEEEE CCCC
-// NN N E C
-// N N N EEE C
-// N NN E C
-// N N EEEEE CCCC
-
-// NEC originally added from https://github.com/shirriff/Arduino-IRremote/
+// Supports:
+// Brand: Yamaha, Model: RAV561 remote
+// Brand: Yamaha, Model: RXV585B A/V Receiver
// Constants
// Ref:
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.cpp
new file mode 100644
index 000000000..353d43b14
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.cpp
@@ -0,0 +1,554 @@
+// Copyright 2019 David Conran
+
+// Neoclima A/C support
+
+// Analysis by crankyoldgit & AndreyShpilevoy
+// Code by crankyoldgit
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/764
+// https://drive.google.com/file/d/1kjYk4zS9NQcMQhFkak-L4mp4UuaAIesW/view
+
+
+// Supports:
+// Brand: Neoclima, Model: NS-09AHTI A/C
+// Brand: Neoclima, Model: ZH/TY-01 remote
+
+#include "ir_Neoclima.h"
+#include
+#include "IRrecv.h"
+#include "IRsend.h"
+#include "IRutils.h"
+
+// Constants
+
+const uint16_t kNeoclimaHdrMark = 6112;
+const uint16_t kNeoclimaHdrSpace = 7391;
+const uint16_t kNeoclimaBitMark = 537;
+const uint16_t kNeoclimaOneSpace = 1651;
+const uint16_t kNeoclimaZeroSpace = 571;
+const uint32_t kNeoclimaMinGap = kDefaultMessageGap;
+
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
+#if SEND_NEOCLIMA
+// Send a Neoclima message.
+//
+// Args:
+// data: message to be sent.
+// nbytes: Nr. of bytes of the message to be sent.
+// repeat: Nr. of additional times the message is to be sent.
+//
+// Status: Beta / Known to be working.
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/764
+void IRsend::sendNeoclima(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ // Set IR carrier frequency
+ enableIROut(38);
+
+ for (uint16_t i = 0; i <= repeat; i++) {
+ sendGeneric(kNeoclimaHdrMark, kNeoclimaHdrSpace,
+ kNeoclimaBitMark, kNeoclimaOneSpace,
+ kNeoclimaBitMark, kNeoclimaZeroSpace,
+ kNeoclimaBitMark, kNeoclimaHdrSpace,
+ data, nbytes, 38000, false, 0, // Repeats are already handled.
+ 50);
+ // Extra footer.
+ mark(kNeoclimaBitMark);
+ space(kNeoclimaMinGap);
+ }
+}
+#endif // SEND_NEOCLIMA
+
+IRNeoclimaAc::IRNeoclimaAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) {
+ this->stateReset();
+}
+
+void IRNeoclimaAc::stateReset(void) {
+ for (uint8_t i = 0; i < kNeoclimaStateLength; i++)
+ remote_state[i] = 0x0;
+ remote_state[7] = 0x6A;
+ remote_state[8] = 0x00;
+ remote_state[9] = 0x2A;
+ remote_state[10] = 0xA5;
+ // [11] is the checksum.
+}
+
+void IRNeoclimaAc::begin(void) { _irsend.begin(); }
+
+uint8_t IRNeoclimaAc::calcChecksum(const uint8_t state[],
+ const uint16_t length) {
+ if (length == 0) return state[0];
+ return sumBytes(state, length - 1);
+}
+
+bool IRNeoclimaAc::validChecksum(const uint8_t state[], const uint16_t length) {
+ if (length < 2)
+ return true; // No checksum to compare with. Assume okay.
+ return (state[length - 1] == calcChecksum(state, length));
+}
+
+// Update the checksum for the internal state.
+void IRNeoclimaAc::checksum(uint16_t length) {
+ if (length < 2) return;
+ remote_state[length - 1] = calcChecksum(remote_state, length);
+}
+
+#if SEND_NEOCLIMA
+void IRNeoclimaAc::send(const uint16_t repeat) {
+ this->checksum();
+ _irsend.sendNeoclima(remote_state, kNeoclimaStateLength, repeat);
+}
+#endif // SEND_NEOCLIMA
+
+uint8_t *IRNeoclimaAc::getRaw(void) {
+ this->checksum();
+ return remote_state;
+}
+
+void IRNeoclimaAc::setRaw(const uint8_t new_code[], const uint16_t length) {
+ for (uint8_t i = 0; i < length && i < kNeoclimaStateLength; i++)
+ remote_state[i] = new_code[i];
+}
+
+
+void IRNeoclimaAc::setButton(const uint8_t button) {
+ switch (button) {
+ case kNeoclimaButtonPower:
+ case kNeoclimaButtonMode:
+ case kNeoclimaButtonTempUp:
+ case kNeoclimaButtonTempDown:
+ case kNeoclimaButtonSwing:
+ case kNeoclimaButtonFanSpeed:
+ case kNeoclimaButtonAirFlow:
+ case kNeoclimaButtonHold:
+ case kNeoclimaButtonSleep:
+ case kNeoclimaButtonLight:
+ case kNeoclimaButtonEye:
+ case kNeoclimaButtonFollow:
+ case kNeoclimaButtonIon:
+ case kNeoclimaButtonFresh:
+ case kNeoclimaButton8CHeat:
+ case kNeoclimaButtonTurbo:
+ remote_state[5] &= ~kNeoclimaButtonMask;
+ remote_state[5] |= button;
+ break;
+ default:
+ this->setButton(kNeoclimaButtonPower);
+ }
+}
+
+uint8_t IRNeoclimaAc::getButton(void) {
+ return remote_state[5] & kNeoclimaButtonMask;
+}
+
+void IRNeoclimaAc::on(void) { this->setPower(true); }
+
+void IRNeoclimaAc::off(void) { this->setPower(false); }
+
+void IRNeoclimaAc::setPower(const bool on) {
+ this->setButton(kNeoclimaButtonPower);
+ if (on)
+ remote_state[7] |= kNeoclimaPowerMask;
+ else
+ remote_state[7] &= ~kNeoclimaPowerMask;
+}
+
+bool IRNeoclimaAc::getPower(void) {
+ return remote_state[7] & kNeoclimaPowerMask;
+}
+
+void IRNeoclimaAc::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kNeoclimaDry:
+ // In this mode fan speed always LOW
+ this->setFan(kNeoclimaFanLow);
+ // FALL THRU
+ case kNeoclimaAuto:
+ case kNeoclimaCool:
+ case kNeoclimaFan:
+ case kNeoclimaHeat:
+ remote_state[9] &= ~kNeoclimaModeMask;
+ remote_state[9] |= (mode << 5);
+ this->setButton(kNeoclimaButtonMode);
+ break;
+ default:
+ // If we get an unexpected mode, default to AUTO.
+ this->setMode(kNeoclimaAuto);
+ }
+}
+
+uint8_t IRNeoclimaAc::getMode(void) {
+ return (remote_state[9] & kNeoclimaModeMask) >> 5;
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRNeoclimaAc::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kNeoclimaCool;
+ case stdAc::opmode_t::kHeat:
+ return kNeoclimaHeat;
+ case stdAc::opmode_t::kDry:
+ return kNeoclimaDry;
+ case stdAc::opmode_t::kFan:
+ return kNeoclimaFan;
+ default:
+ return kNeoclimaAuto;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRNeoclimaAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kNeoclimaCool: return stdAc::opmode_t::kCool;
+ case kNeoclimaHeat: return stdAc::opmode_t::kHeat;
+ case kNeoclimaDry: return stdAc::opmode_t::kDry;
+ case kNeoclimaFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Set the temp. in deg C
+void IRNeoclimaAc::setTemp(const uint8_t temp) {
+ uint8_t oldtemp = this->getTemp();
+ uint8_t newtemp = std::max(kNeoclimaMinTemp, temp);
+ newtemp = std::min(kNeoclimaMaxTemp, newtemp);
+ if (oldtemp > newtemp)
+ this->setButton(kNeoclimaButtonTempDown);
+ else if (newtemp > oldtemp)
+ this->setButton(kNeoclimaButtonTempUp);
+ remote_state[9] = (remote_state[9] & ~kNeoclimaTempMask) |
+ (newtemp - kNeoclimaMinTemp);
+}
+
+// Return the set temp. in deg C
+uint8_t IRNeoclimaAc::getTemp(void) {
+ return (remote_state[9] & kNeoclimaTempMask) + kNeoclimaMinTemp;
+}
+
+// Set the speed of the fan, 0-3, 0 is auto, 1-3 is the speed
+void IRNeoclimaAc::setFan(const uint8_t speed) {
+ switch (speed) {
+ case kNeoclimaFanAuto:
+ case kNeoclimaFanHigh:
+ case kNeoclimaFanMed:
+ if (this->getMode() == kNeoclimaDry) { // Dry mode only allows low speed.
+ this->setFan(kNeoclimaFanLow);
+ return;
+ }
+ // FALL-THRU
+ case kNeoclimaFanLow:
+ remote_state[7] &= ~kNeoclimaFanMask;
+ remote_state[7] |= (speed << 5);
+ this->setButton(kNeoclimaButtonFanSpeed);
+ break;
+ default:
+ // If we get an unexpected speed, default to Auto.
+ this->setFan(kNeoclimaFanAuto);
+ }
+}
+
+uint8_t IRNeoclimaAc::getFan(void) {
+ return (remote_state[7] & kNeoclimaFanMask) >> 5;
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRNeoclimaAc::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ case stdAc::fanspeed_t::kLow:
+ return kNeoclimaFanLow;
+ case stdAc::fanspeed_t::kMedium:
+ return kNeoclimaFanMed;
+ case stdAc::fanspeed_t::kHigh:
+ case stdAc::fanspeed_t::kMax:
+ return kNeoclimaFanHigh;
+ default:
+ return kNeoclimaFanAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRNeoclimaAc::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kNeoclimaFanHigh: return stdAc::fanspeed_t::kMax;
+ case kNeoclimaFanMed: return stdAc::fanspeed_t::kMedium;
+ case kNeoclimaFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+void IRNeoclimaAc::setSleep(const bool on) {
+ this->setButton(kNeoclimaButtonSleep);
+ if (on)
+ remote_state[7] |= kNeoclimaSleepMask;
+ else
+ remote_state[7] &= ~kNeoclimaSleepMask;
+}
+
+bool IRNeoclimaAc::getSleep(void) {
+ return remote_state[7] & kNeoclimaSleepMask;
+}
+
+// A.k.a. Swing
+void IRNeoclimaAc::setSwingV(const bool on) {
+ this->setButton(kNeoclimaButtonSwing);
+ remote_state[7] &= ~kNeoclimaSwingVMask;
+ remote_state[7] |= on ? kNeoclimaSwingVOn : kNeoclimaSwingVOff;
+}
+
+bool IRNeoclimaAc::getSwingV(void) {
+ return (remote_state[7] & kNeoclimaSwingVMask) == kNeoclimaSwingVOn;
+}
+
+// A.k.a. Air Flow
+void IRNeoclimaAc::setSwingH(const bool on) {
+ this->setButton(kNeoclimaButtonAirFlow);
+ if (on)
+ remote_state[7] &= ~kNeoclimaSwingHMask;
+ else
+ remote_state[7] |= kNeoclimaSwingHMask;
+}
+
+bool IRNeoclimaAc::getSwingH(void) {
+ return !(remote_state[7] & kNeoclimaSwingHMask);
+}
+
+void IRNeoclimaAc::setTurbo(const bool on) {
+ this->setButton(kNeoclimaButtonTurbo);
+ if (on)
+ remote_state[3] |= kNeoclimaTurboMask;
+ else
+ remote_state[3] &= ~kNeoclimaTurboMask;
+}
+
+bool IRNeoclimaAc::getTurbo(void) {
+ return remote_state[3] & kNeoclimaTurboMask;
+}
+
+void IRNeoclimaAc::setFresh(const bool on) {
+ this->setButton(kNeoclimaButtonFresh);
+ if (on)
+ remote_state[5] |= kNeoclimaFreshMask;
+ else
+ remote_state[5] &= ~kNeoclimaFreshMask;
+}
+
+bool IRNeoclimaAc::getFresh(void) {
+ return remote_state[5] & kNeoclimaFreshMask;
+}
+
+void IRNeoclimaAc::setHold(const bool on) {
+ this->setButton(kNeoclimaButtonHold);
+ if (on)
+ remote_state[3] |= kNeoclimaHoldMask;
+ else
+ remote_state[3] &= ~kNeoclimaHoldMask;
+}
+
+bool IRNeoclimaAc::getHold(void) {
+ return remote_state[3] & kNeoclimaHoldMask;
+}
+
+void IRNeoclimaAc::setIon(const bool on) {
+ this->setButton(kNeoclimaButtonIon);
+ if (on)
+ remote_state[1] |= kNeoclimaIonMask;
+ else
+ remote_state[1] &= ~kNeoclimaIonMask;
+}
+
+bool IRNeoclimaAc::getIon(void) {
+ return remote_state[1] & kNeoclimaIonMask;
+}
+
+void IRNeoclimaAc::setLight(const bool on) {
+ this->setButton(kNeoclimaButtonLight);
+ if (on)
+ remote_state[3] |= kNeoclimaLightMask;
+ else
+ remote_state[3] &= ~kNeoclimaLightMask;
+}
+
+bool IRNeoclimaAc::getLight(void) {
+ return remote_state[3] & kNeoclimaLightMask;
+}
+
+// This feature maintains the room temperature steadily at 8°C and prevents the
+// room from freezing by activating the heating operation automatically when
+// nobody is at home over a longer period during severe winter.
+void IRNeoclimaAc::set8CHeat(const bool on) {
+ this->setButton(kNeoclimaButton8CHeat);
+ if (on)
+ remote_state[1] |= kNeoclima8CHeatMask;
+ else
+ remote_state[1] &= ~kNeoclima8CHeatMask;
+}
+
+bool IRNeoclimaAc::get8CHeat(void) {
+ return remote_state[1] & kNeoclima8CHeatMask;
+}
+
+void IRNeoclimaAc::setEye(const bool on) {
+ this->setButton(kNeoclimaButtonEye);
+ if (on)
+ remote_state[3] |= kNeoclimaEyeMask;
+ else
+ remote_state[3] &= ~kNeoclimaEyeMask;
+}
+
+bool IRNeoclimaAc::getEye(void) {
+ return remote_state[3] & kNeoclimaEyeMask;
+}
+
+/* DISABLED
+ TODO(someone): Work out why "on" is either 0x5D or 0x5F
+void IRNeoclimaAc::setFollow(const bool on) {
+ this->setButton(kNeoclimaButtonFollow);
+ if (on)
+ remote_state[8] = kNeoclimaFollowMe;
+ else
+ remote_state[8] = 0;
+}
+*/
+
+bool IRNeoclimaAc::getFollow(void) {
+ return (remote_state[8] & kNeoclimaFollowMe) == kNeoclimaFollowMe;
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRNeoclimaAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::NEOCLIMA;
+ result.model = -1; // No models used.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwingV() ? stdAc::swingv_t::kAuto
+ : stdAc::swingv_t::kOff;
+ result.swingh = this->getSwingH() ? stdAc::swingh_t::kAuto
+ : stdAc::swingh_t::kOff;
+ result.turbo = this->getTurbo();
+ result.light = this->getLight();
+ result.filter = this->getIon();
+ result.sleep = this->getSleep() ? 0 : -1;
+ // Not supported.
+ result.quiet = false;
+ result.econo = false;
+ result.clean = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRNeoclimaAc::toString(void) {
+ String result = "";
+ result.reserve(100); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kNeoclimaAuto, kNeoclimaCool,
+ kNeoclimaHeat, kNeoclimaDry, kNeoclimaFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kNeoclimaFanHigh, kNeoclimaFanLow,
+ kNeoclimaFanAuto, kNeoclimaFanAuto, kNeoclimaFanMed);
+ result += addBoolToString(getSwingV(), F("Swing(V)"));
+ result += addBoolToString(getSwingH(), F("Swing(H)"));
+ result += addBoolToString(getSleep(), F("Sleep"));
+ result += addBoolToString(getTurbo(), F("Turbo"));
+ result += addBoolToString(getHold(), F("Hold"));
+ result += addBoolToString(getIon(), F("Ion"));
+ result += addBoolToString(getEye(), F("Eye"));
+ result += addBoolToString(getLight(), F("Light"));
+ result += addBoolToString(getFollow(), F("Follow"));
+ result += addBoolToString(get8CHeat(), F("8C Heat"));
+ result += addBoolToString(getFresh(), F("Fresh"));
+ result += addIntToString(getButton(), F("Button"));
+ result += F(" (");
+ switch (this->getButton()) {
+ case kNeoclimaButtonPower: result += F("Power"); break;
+ case kNeoclimaButtonMode: result += F("Mode"); break;
+ case kNeoclimaButtonTempUp: result += F("Temp Up"); break;
+ case kNeoclimaButtonTempDown: result += F("Temp Down"); break;
+ case kNeoclimaButtonSwing: result += F("Swing"); break;
+ case kNeoclimaButtonFanSpeed: result += F("Speed"); break;
+ case kNeoclimaButtonAirFlow: result += F("Air Flow"); break;
+ case kNeoclimaButtonHold: result += F("Hold"); break;
+ case kNeoclimaButtonSleep: result += F("Sleep"); break;
+ case kNeoclimaButtonLight: result += F("Light"); break;
+ case kNeoclimaButtonEye: result += F("Eye"); break;
+ case kNeoclimaButtonFollow: result += F("Follow"); break;
+ case kNeoclimaButtonIon: result += F("Ion"); break;
+ case kNeoclimaButtonFresh: result += F("Fresh"); break;
+ case kNeoclimaButton8CHeat: result += F("8C Heat"); break;
+ case kNeoclimaButtonTurbo: result += F("Turbo"); break;
+ default:
+ result += F("Unknown");
+ }
+ result += ')';
+ return result;
+}
+
+#if DECODE_NEOCLIMA
+// Decode the supplied Neoclima message.
+//
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of data bits to expect. Typically kNeoclimaBits.
+// strict: Flag indicating if we should perform strict matching.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: BETA / Known working
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/764
+bool IRrecv::decodeNeoclima(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ // Compliance
+ if (strict && nbits != kNeoclimaBits)
+ return false; // Incorrect nr. of bits per spec.
+
+ uint16_t offset = kStartOffset;
+ // Match Main Header + Data + Footer
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kNeoclimaHdrMark, kNeoclimaHdrSpace,
+ kNeoclimaBitMark, kNeoclimaOneSpace,
+ kNeoclimaBitMark, kNeoclimaZeroSpace,
+ kNeoclimaBitMark, kNeoclimaHdrSpace, false,
+ _tolerance, 0, false);
+ if (!used) return false;
+ offset += used;
+ // Extra footer.
+ uint64_t unused;
+ if (!matchGeneric(results->rawbuf + offset, &unused,
+ results->rawlen - offset, 0, 0, 0, 0, 0, 0, 0,
+ kNeoclimaBitMark, kNeoclimaHdrSpace, true)) return false;
+
+ // Compliance
+ if (strict) {
+ // Check we got a valid checksum.
+ if (!IRNeoclimaAc::validChecksum(results->state, nbits / 8)) return false;
+ }
+
+ // Success
+ results->decode_type = decode_type_t::NEOCLIMA;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_NEOCLIMA
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.h b/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.h
new file mode 100644
index 000000000..9e99c8a9e
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.h
@@ -0,0 +1,154 @@
+// Neoclima A/C
+//
+// Copyright 2019 David Conran
+
+// Analysis by crankyoldgit & AndreyShpilevoy
+
+#ifndef IR_NEOCLIMA_H_
+#define IR_NEOCLIMA_H_
+
+#define __STDC_LIMIT_MACROS
+#include
+#ifndef UNIT_TEST
+#include
+#endif
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#ifdef UNIT_TEST
+#include "IRsend_test.h"
+#endif
+
+// Supports:
+// Brand: Neoclima, Model: NS-09AHTI A/C
+// Brand: Neoclima, Model: ZH/TY-01 remote
+
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/764
+// https://drive.google.com/file/d/1kjYk4zS9NQcMQhFkak-L4mp4UuaAIesW/view
+
+// Constants
+// state[1]
+const uint8_t kNeoclima8CHeatMask = 0b00000010;
+const uint8_t kNeoclimaIonMask = 0b00000100;
+// state[3]
+const uint8_t kNeoclimaLightMask = 0b00000001;
+const uint8_t kNeoclimaHoldMask = 0b00000100;
+const uint8_t kNeoclimaTurboMask = 0b00001000;
+const uint8_t kNeoclimaEyeMask = 0b01000000;
+// state[5]
+const uint8_t kNeoclimaFreshMask = 0b10000000;
+const uint8_t kNeoclimaButtonMask = 0b00011111;
+const uint8_t kNeoclimaButtonPower = 0x00;
+const uint8_t kNeoclimaButtonMode = 0x01;
+const uint8_t kNeoclimaButtonTempUp = 0x02;
+const uint8_t kNeoclimaButtonTempDown = 0x03;
+const uint8_t kNeoclimaButtonSwing = 0x04;
+const uint8_t kNeoclimaButtonFanSpeed = 0x05;
+const uint8_t kNeoclimaButtonAirFlow = 0x07;
+const uint8_t kNeoclimaButtonHold = 0x08;
+const uint8_t kNeoclimaButtonSleep = 0x09;
+const uint8_t kNeoclimaButtonTurbo = 0x0A;
+const uint8_t kNeoclimaButtonLight = 0x0B;
+const uint8_t kNeoclimaButtonEye = 0x0E;
+const uint8_t kNeoclimaButtonFollow = 0x13;
+const uint8_t kNeoclimaButtonIon = 0x14;
+const uint8_t kNeoclimaButtonFresh = 0x15;
+const uint8_t kNeoclimaButton8CHeat = 0x1D;
+// state[7]
+const uint8_t kNeoclimaSleepMask = 0b00000001;
+const uint8_t kNeoclimaPowerMask = 0b00000010;
+const uint8_t kNeoclimaSwingVMask = 0b00001100;
+const uint8_t kNeoclimaSwingVOn = 0b00000100;
+const uint8_t kNeoclimaSwingVOff = 0b00001000;
+const uint8_t kNeoclimaSwingHMask = 0b00010000;
+const uint8_t kNeoclimaFanMask = 0b01100000;
+const uint8_t kNeoclimaFanAuto = 0b00;
+const uint8_t kNeoclimaFanHigh = 0b01;
+const uint8_t kNeoclimaFanMed = 0b10;
+const uint8_t kNeoclimaFanLow = 0b11;
+// state[8]
+const uint8_t kNeoclimaFollowMe = 0x5D; // Also 0x5F
+// state[9]
+const uint8_t kNeoclimaTempMask = 0b00011111;
+const uint8_t kNeoclimaMinTemp = 16; // 16C
+const uint8_t kNeoclimaMaxTemp = 32; // 32C
+const uint8_t kNeoclimaModeMask = 0b11100000;
+const uint8_t kNeoclimaAuto = 0b000;
+const uint8_t kNeoclimaCool = 0b001;
+const uint8_t kNeoclimaDry = 0b010;
+const uint8_t kNeoclimaFan = 0b011;
+const uint8_t kNeoclimaHeat = 0b100;
+
+// Classes
+class IRNeoclimaAc {
+ public:
+ explicit IRNeoclimaAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+ void stateReset(void);
+#if SEND_NEOCLIMA
+ void send(const uint16_t repeat = kNeoclimaMinRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif // SEND_NEOCLIMA
+ void begin(void);
+ void setButton(const uint8_t button);
+ uint8_t getButton(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp(void);
+ void setFan(const uint8_t speed);
+ uint8_t getFan(void);
+ void setSwingV(const bool on);
+ bool getSwingV(void);
+ void setSwingH(const bool on);
+ bool getSwingH(void);
+ void setSleep(const bool on);
+ bool getSleep(void);
+ void setTurbo(const bool on);
+ bool getTurbo(void);
+ void setFresh(const bool on);
+ bool getFresh(void);
+ void setHold(const bool on);
+ bool getHold(void);
+ void setIon(const bool on);
+ bool getIon(void);
+ void setLight(const bool on);
+ bool getLight(void);
+ void set8CHeat(const bool on);
+ bool get8CHeat(void);
+ void setEye(const bool on);
+ bool getEye(void);
+ // DISABLED: See TODO in ir_Neoclima.cpp
+ // void setFollow(const bool on);
+ bool getFollow(void);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t new_code[],
+ const uint16_t length = kNeoclimaStateLength);
+ static bool validChecksum(const uint8_t state[],
+ const uint16_t length = kNeoclimaStateLength);
+ static uint8_t calcChecksum(const uint8_t state[],
+ const uint16_t length = kNeoclimaStateLength);
+ String toString(void);
+ uint8_t convertMode(const stdAc::opmode_t mode);
+ uint8_t convertFan(const stdAc::fanspeed_t speed);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // The state of the IR remote in IR code form.
+ uint8_t remote_state[kNeoclimaStateLength];
+ void checksum(const uint16_t length = kNeoclimaStateLength);
+};
+
+#endif // IR_NEOCLIMA_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Nikai.cpp
similarity index 58%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Nikai.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Nikai.cpp
index 9ac22a849..12e99c278 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Nikai.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Nikai.cpp
@@ -1,20 +1,16 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017 David Conran
+// Nikai
+
#include
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
-// NN NN IIIII KK KK AAA IIIII
-// NNN NN III KK KK AAAAA III
-// NN N NN III KKKK AA AA III
-// NN NNN III KK KK AAAAAAA III
-// NN NN IIIII KK KK AA AA IIIII
-
// Constants
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/309
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/309
const uint16_t kNikaiTick = 500;
const uint16_t kNikaiHdrMarkTicks = 8;
const uint16_t kNikaiHdrMark = kNikaiHdrMarkTicks * kNikaiTick;
@@ -39,7 +35,7 @@ const uint16_t kNikaiMinGap = kNikaiMinGapTicks * kNikaiTick;
//
// Status: STABLE / Working.
//
-// Ref: https://github.com/markszabo/IRremoteESP8266/issues/309
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/309
void IRsend::sendNikai(uint64_t data, uint16_t nbits, uint16_t repeat) {
sendGeneric(kNikaiHdrMark, kNikaiHdrSpace, kNikaiBitMark, kNikaiOneSpace,
kNikaiBitMark, kNikaiZeroSpace, kNikaiBitMark, kNikaiMinGap, data,
@@ -61,38 +57,19 @@ void IRsend::sendNikai(uint64_t data, uint16_t nbits, uint16_t repeat) {
// Status: STABLE / Working.
//
bool IRrecv::decodeNikai(decode_results *results, uint16_t nbits, bool strict) {
- if (results->rawlen < 2 * nbits + kHeader + kFooter - 1)
- return false; // Can't possibly be a valid Nikai message.
if (strict && nbits != kNikaiBits)
return false; // We expect Nikai to be a certain sized message.
uint64_t data = 0;
uint16_t offset = kStartOffset;
- // Header
- if (!matchMark(results->rawbuf[offset], kNikaiHdrMark)) return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kNikaiHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kNikaiHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kNikaiHdrSpaceTicks;
- // Data
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits, kNikaiBitMarkTicks * m_tick,
- kNikaiOneSpaceTicks * s_tick, kNikaiBitMarkTicks * m_tick,
- kNikaiZeroSpaceTicks * s_tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
- // Footer
- if (!matchMark(results->rawbuf[offset++], kNikaiBitMarkTicks * m_tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kNikaiMinGapTicks * s_tick))
- return false;
-
- // Compliance
-
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kNikaiHdrMark, kNikaiHdrSpace,
+ kNikaiBitMark, kNikaiOneSpace,
+ kNikaiBitMark, kNikaiZeroSpace,
+ kNikaiBitMark, kNikaiMinGap, true)) return false;
// Success
results->bits = nbits;
results->value = data;
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.cpp
similarity index 69%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.cpp
index 47aa51c96..1a24ac41f 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.cpp
@@ -1,6 +1,8 @@
// Copyright 2015 Kristian Lauszus
// Copyright 2017, 2018 David Conran
+// Panasonic devices
+
#include "ir_Panasonic.h"
#include
#ifndef ARDUINO
@@ -10,12 +12,6 @@
#include "IRsend.h"
#include "IRutils.h"
-// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC
-// P P A A NN N A A S O O NN N I C
-// PPPP AAAAA N N N AAAAA SSS O O N N N I C
-// P A A N NN A A S O O N NN I C
-// P A A N N A A SSSS OOO N N IIIII CCCC
-
// Panasonic protocol originally added by Kristian Lauszus from:
// https://github.com/z3t0/Arduino-IRremote
// (Thanks to zenwheel and other people at the original blog post)
@@ -65,6 +61,14 @@ const uint16_t kPanasonicAcSectionGap = 10000;
const uint16_t kPanasonicAcSection1Length = 8;
const uint32_t kPanasonicAcMessageGap = kDefaultMessageGap; // Just a guess.
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+using irutils::minsToString;
+
#if (SEND_PANASONIC || SEND_DENON)
// Send a Panasonic formatted message.
//
@@ -77,7 +81,8 @@ const uint32_t kPanasonicAcMessageGap = kDefaultMessageGap; // Just a guess.
//
// Note:
// This protocol is a modified version of Kaseikyo.
-void IRsend::sendPanasonic64(uint64_t data, uint16_t nbits, uint16_t repeat) {
+void IRsend::sendPanasonic64(const uint64_t data, const uint16_t nbits,
+ const uint16_t repeat) {
sendGeneric(kPanasonicHdrMark, kPanasonicHdrSpace, kPanasonicBitMark,
kPanasonicOneSpace, kPanasonicBitMark, kPanasonicZeroSpace,
kPanasonicBitMark, kPanasonicMinGap, kPanasonicMinCommandLength,
@@ -96,8 +101,8 @@ void IRsend::sendPanasonic64(uint64_t data, uint16_t nbits, uint16_t repeat) {
//
// Note:
// This protocol is a modified version of Kaseikyo.
-void IRsend::sendPanasonic(uint16_t address, uint32_t data, uint16_t nbits,
- uint16_t repeat) {
+void IRsend::sendPanasonic(const uint16_t address, const uint32_t data,
+ const uint16_t nbits, const uint16_t repeat) {
sendPanasonic64(((uint64_t)address << 32) | (uint64_t)data, nbits, repeat);
}
@@ -117,8 +122,10 @@ void IRsend::sendPanasonic(uint16_t address, uint32_t data, uint16_t nbits,
// Panasonic 48-bit protocol is a modified version of Kaseikyo.
// Ref:
// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?2615
-uint64_t IRsend::encodePanasonic(uint16_t manufacturer, uint8_t device,
- uint8_t subdevice, uint8_t function) {
+uint64_t IRsend::encodePanasonic(const uint16_t manufacturer,
+ const uint8_t device,
+ const uint8_t subdevice,
+ const uint8_t function) {
uint8_t checksum = device ^ subdevice ^ function;
return (((uint64_t)manufacturer << 32) | ((uint64_t)device << 24) |
((uint64_t)subdevice << 16) | ((uint64_t)function << 8) | checksum);
@@ -141,42 +148,21 @@ uint64_t IRsend::encodePanasonic(uint16_t manufacturer, uint8_t device,
// Ref:
// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152
// http://www.hifi-remote.com/wiki/index.php?title=Panasonic
-bool IRrecv::decodePanasonic(decode_results *results, uint16_t nbits,
- bool strict, uint32_t manufacturer) {
- if (results->rawlen < 2 * nbits + kHeader + kFooter - 1)
- return false; // Not enough entries to be a Panasonic message.
+bool IRrecv::decodePanasonic(decode_results *results, const uint16_t nbits,
+ const bool strict, const uint32_t manufacturer) {
if (strict && nbits != kPanasonicBits)
return false; // Request is out of spec.
uint64_t data = 0;
uint16_t offset = kStartOffset;
- // Header
- if (!matchMark(results->rawbuf[offset], kPanasonicHdrMark)) return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t m_tick =
- results->rawbuf[offset++] * kRawTick / kPanasonicHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kPanasonicHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t s_tick =
- results->rawbuf[offset++] * kRawTick / kPanasonicHdrSpaceTicks;
-
- // Data
- match_result_t data_result = matchData(
- &(results->rawbuf[offset]), nbits, kPanasonicBitMarkTicks * m_tick,
- kPanasonicOneSpaceTicks * s_tick, kPanasonicBitMarkTicks * m_tick,
- kPanasonicZeroSpaceTicks * s_tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Footer
- if (!match(results->rawbuf[offset++], kPanasonicBitMarkTicks * m_tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kPanasonicEndGap))
- return false;
-
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kPanasonicHdrMark, kPanasonicHdrSpace,
+ kPanasonicBitMark, kPanasonicOneSpace,
+ kPanasonicBitMark, kPanasonicZeroSpace,
+ kPanasonicBitMark, kPanasonicEndGap, true)) return false;
// Compliance
uint32_t address = data >> 32;
uint32_t command = data & 0xFFFFFFFF;
@@ -217,7 +203,8 @@ bool IRrecv::decodePanasonic(decode_results *results, uint16_t nbits,
// A75C3747
// A75C3704
//
-void IRsend::sendPanasonicAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) {
+void IRsend::sendPanasonicAC(const uint8_t data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kPanasonicAcSection1Length) return;
for (uint16_t r = 0; r <= repeat; r++) {
// First section. (8 bytes)
@@ -236,16 +223,18 @@ void IRsend::sendPanasonicAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) {
}
#endif // SEND_PANASONIC_AC
-IRPanasonicAc::IRPanasonicAc(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRPanasonicAc::IRPanasonicAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
-void IRPanasonicAc::stateReset() {
+void IRPanasonicAc::stateReset(void) {
for (uint8_t i = 0; i < kPanasonicAcStateLength; i++)
remote_state[i] = kPanasonicKnownGoodState[i];
_temp = 25; // An initial saved desired temp. Completely made up.
_swingh = kPanasonicAcSwingHMiddle; // A similar made up value for H Swing.
}
-void IRPanasonicAc::begin() { _irsend.begin(); }
+void IRPanasonicAc::begin(void) { _irsend.begin(); }
// Verify the checksum is valid for a given state.
// Args:
@@ -264,12 +253,12 @@ uint8_t IRPanasonicAc::calcChecksum(uint8_t state[], const uint16_t length) {
}
void IRPanasonicAc::fixChecksum(const uint16_t length) {
- remote_state[length - 1] = calcChecksum(remote_state, length);
+ remote_state[length - 1] = this->calcChecksum(remote_state, length);
}
#if SEND_PANASONIC_AC
void IRPanasonicAc::send(const uint16_t repeat) {
- fixChecksum();
+ this->fixChecksum();
_irsend.sendPanasonicAC(remote_state, kPanasonicAcStateLength, repeat);
}
#endif // SEND_PANASONIC_AC
@@ -302,7 +291,7 @@ void IRPanasonicAc::setModel(const panasonic_ac_remote_model_t model) {
remote_state[23] = 0x01;
remote_state[25] = 0x06;
// Has to be done last as setSwingHorizontal has model check built-in
- setSwingHorizontal(_swingh);
+ this->setSwingHorizontal(_swingh);
break;
case kPanasonicNke:
remote_state[17] = 0x06;
@@ -321,7 +310,7 @@ void IRPanasonicAc::setModel(const panasonic_ac_remote_model_t model) {
}
}
-panasonic_ac_remote_model_t IRPanasonicAc::getModel() {
+panasonic_ac_remote_model_t IRPanasonicAc::getModel(void) {
if (remote_state[23] == 0x89) return kPanasonicRkr;
if (remote_state[17] == 0x00) {
if ((remote_state[21] & 0x10) && (remote_state[23] & 0x01))
@@ -335,8 +324,8 @@ panasonic_ac_remote_model_t IRPanasonicAc::getModel() {
return kPanasonicUnknown;
}
-uint8_t *IRPanasonicAc::getRaw() {
- fixChecksum();
+uint8_t *IRPanasonicAc::getRaw(void) {
+ this->fixChecksum();
return remote_state;
}
@@ -357,32 +346,32 @@ void IRPanasonicAc::setRaw(const uint8_t state[]) {
//
// For all other models, setPower(true) should set the internal state to
// turn it on, and setPower(false) should turn it off.
-void IRPanasonicAc::setPower(const bool state) {
- if (state)
- on();
+void IRPanasonicAc::setPower(const bool on) {
+ if (on)
+ this->on();
else
- off();
+ this->off();
}
// Return the A/C power state of the remote.
// Except for CKP models, where it returns if the power state will be toggled
// on the A/C unit when the next message is sent.
-bool IRPanasonicAc::getPower() {
+bool IRPanasonicAc::getPower(void) {
return (remote_state[13] & kPanasonicAcPower) == kPanasonicAcPower;
}
-void IRPanasonicAc::on() { remote_state[13] |= kPanasonicAcPower; }
+void IRPanasonicAc::on(void) { remote_state[13] |= kPanasonicAcPower; }
-void IRPanasonicAc::off() { remote_state[13] &= ~kPanasonicAcPower; }
+void IRPanasonicAc::off(void) { remote_state[13] &= ~kPanasonicAcPower; }
-uint8_t IRPanasonicAc::getMode() { return remote_state[13] >> 4; }
+uint8_t IRPanasonicAc::getMode(void) { return remote_state[13] >> 4; }
void IRPanasonicAc::setMode(const uint8_t desired) {
uint8_t mode = kPanasonicAcAuto; // Default to Auto mode.
switch (desired) {
case kPanasonicAcFan:
// Allegedly Fan mode has a temperature of 27.
- setTemp(kPanasonicAcFanModeTemp, false);
+ this->setTemp(kPanasonicAcFanModeTemp, false);
mode = desired;
break;
case kPanasonicAcAuto:
@@ -391,16 +380,16 @@ void IRPanasonicAc::setMode(const uint8_t desired) {
case kPanasonicAcDry:
mode = desired;
// Set the temp to the saved temp, just incase our previous mode was Fan.
- setTemp(_temp);
+ this->setTemp(_temp);
break;
}
remote_state[13] &= 0x0F; // Clear the previous mode bits.
remote_state[13] |= mode << 4;
}
-uint8_t IRPanasonicAc::getTemp() { return remote_state[14] >> 1; }
+uint8_t IRPanasonicAc::getTemp(void) { return remote_state[14] >> 1; }
-// Set the desitred temperature in Celcius.
+// Set the desitred temperature in Celsius.
// Args:
// celsius: The temperature to set the A/C unit to.
// remember: A boolean flag for the class to remember the temperature.
@@ -414,7 +403,9 @@ void IRPanasonicAc::setTemp(const uint8_t celsius, const bool remember) {
if (remember) _temp = temperature;
}
-uint8_t IRPanasonicAc::getSwingVertical() { return remote_state[16] & 0x0F; }
+uint8_t IRPanasonicAc::getSwingVertical(void) {
+ return remote_state[16] & 0x0F;
+}
void IRPanasonicAc::setSwingVertical(const uint8_t desired_elevation) {
uint8_t elevation = desired_elevation;
@@ -426,7 +417,7 @@ void IRPanasonicAc::setSwingVertical(const uint8_t desired_elevation) {
remote_state[16] |= elevation;
}
-uint8_t IRPanasonicAc::getSwingHorizontal() { return remote_state[17]; }
+uint8_t IRPanasonicAc::getSwingHorizontal(void) { return remote_state[17]; }
void IRPanasonicAc::setSwingHorizontal(const uint8_t desired_direction) {
switch (desired_direction) {
@@ -442,7 +433,7 @@ void IRPanasonicAc::setSwingHorizontal(const uint8_t desired_direction) {
}
_swingh = desired_direction; // Store the direction for later.
uint8_t direction = desired_direction;
- switch (getModel()) {
+ switch (this->getModel()) {
case kPanasonicDke:
case kPanasonicRkr:
break;
@@ -462,12 +453,12 @@ void IRPanasonicAc::setFan(const uint8_t speed) {
(remote_state[16] & 0x0F) | ((speed + kPanasonicAcFanOffset) << 4);
}
-uint8_t IRPanasonicAc::getFan() {
+uint8_t IRPanasonicAc::getFan(void) {
return (remote_state[16] >> 4) - kPanasonicAcFanOffset;
}
-bool IRPanasonicAc::getQuiet() {
- switch (getModel()) {
+bool IRPanasonicAc::getQuiet(void) {
+ switch (this->getModel()) {
case kPanasonicRkr:
case kPanasonicCkp:
return remote_state[21] & kPanasonicAcQuietCkp;
@@ -476,9 +467,9 @@ bool IRPanasonicAc::getQuiet() {
}
}
-void IRPanasonicAc::setQuiet(const bool state) {
+void IRPanasonicAc::setQuiet(const bool on) {
uint8_t quiet;
- switch (getModel()) {
+ switch (this->getModel()) {
case kPanasonicRkr:
case kPanasonicCkp:
quiet = kPanasonicAcQuietCkp;
@@ -487,16 +478,16 @@ void IRPanasonicAc::setQuiet(const bool state) {
quiet = kPanasonicAcQuiet;
}
- if (state) {
- setPowerful(false); // Powerful is mutually exclusive.
+ if (on) {
+ this->setPowerful(false); // Powerful is mutually exclusive.
remote_state[21] |= quiet;
} else {
remote_state[21] &= ~quiet;
}
}
-bool IRPanasonicAc::getPowerful() {
- switch (getModel()) {
+bool IRPanasonicAc::getPowerful(void) {
+ switch (this->getModel()) {
case kPanasonicRkr:
case kPanasonicCkp:
return remote_state[21] & kPanasonicAcPowerfulCkp;
@@ -505,9 +496,9 @@ bool IRPanasonicAc::getPowerful() {
}
}
-void IRPanasonicAc::setPowerful(const bool state) {
+void IRPanasonicAc::setPowerful(const bool on) {
uint8_t powerful;
- switch (getModel()) {
+ switch (this->getModel()) {
case kPanasonicRkr:
case kPanasonicCkp:
powerful = kPanasonicAcPowerfulCkp;
@@ -516,8 +507,8 @@ void IRPanasonicAc::setPowerful(const bool state) {
powerful = kPanasonicAcPowerful;
}
- if (state) {
- setQuiet(false); // Quiet is mutually exclusive.
+ if (on) {
+ this->setQuiet(false); // Quiet is mutually exclusive.
remote_state[21] |= powerful;
} else {
remote_state[21] &= ~powerful;
@@ -528,7 +519,7 @@ uint16_t IRPanasonicAc::encodeTime(const uint8_t hours, const uint8_t mins) {
return std::min(hours, (uint8_t)23) * 60 + std::min(mins, (uint8_t)59);
}
-uint16_t IRPanasonicAc::getClock() {
+uint16_t IRPanasonicAc::getClock(void) {
uint16_t result = ((remote_state[25] & 0b00000111) << 8) + remote_state[24];
if (result == kPanasonicAcTimeSpecial) return 0;
return result;
@@ -543,7 +534,7 @@ void IRPanasonicAc::setClock(const uint16_t mins_since_midnight) {
remote_state[25] |= (corrected >> 8);
}
-uint16_t IRPanasonicAc::getOnTimer() {
+uint16_t IRPanasonicAc::getOnTimer(void) {
uint16_t result = ((remote_state[19] & 0b00000111) << 8) + remote_state[18];
if (result == kPanasonicAcTimeSpecial) return 0;
return result;
@@ -567,13 +558,13 @@ void IRPanasonicAc::setOnTimer(const uint16_t mins_since_midnight,
remote_state[19] |= (corrected >> 8);
}
-void IRPanasonicAc::cancelOnTimer() { setOnTimer(0, false); }
+void IRPanasonicAc::cancelOnTimer(void) { this->setOnTimer(0, false); }
-bool IRPanasonicAc::isOnTimerEnabled() {
+bool IRPanasonicAc::isOnTimerEnabled(void) {
return remote_state[13] & kPanasonicAcOnTimer;
}
-uint16_t IRPanasonicAc::getOffTimer() {
+uint16_t IRPanasonicAc::getOffTimer(void) {
uint16_t result =
((remote_state[20] & 0b01111111) << 4) + (remote_state[19] >> 4);
if (result == kPanasonicAcTimeSpecial) return 0;
@@ -599,25 +590,12 @@ void IRPanasonicAc::setOffTimer(const uint16_t mins_since_midnight,
remote_state[20] |= corrected >> 4;
}
-void IRPanasonicAc::cancelOffTimer() { setOffTimer(0, false); }
+void IRPanasonicAc::cancelOffTimer(void) { this->setOffTimer(0, false); }
-bool IRPanasonicAc::isOffTimerEnabled() {
+bool IRPanasonicAc::isOffTimerEnabled(void) {
return remote_state[13] & kPanasonicAcOffTimer;
}
-#ifdef ARDUINO
-String IRPanasonicAc::timeToString(const uint16_t mins_since_midnight) {
- String result = "";
-#else
-std::string IRPanasonicAc::timeToString(const uint16_t mins_since_midnight) {
- std::string result = "";
-#endif // ARDUINO
- result += uint64ToString(mins_since_midnight / 60) + ':';
- uint8_t mins = mins_since_midnight % 60;
- if (mins < 10) result += '0'; // Zero pad the minutes.
- return result + uint64ToString(mins);
-}
-
// Convert a standard A/C mode into its native mode.
uint8_t IRPanasonicAc::convertMode(const stdAc::opmode_t mode) {
switch (mode) {
@@ -685,14 +663,79 @@ uint8_t IRPanasonicAc::convertSwingH(const stdAc::swingh_t position) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRPanasonicAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kPanasonicAcCool: return stdAc::opmode_t::kCool;
+ case kPanasonicAcHeat: return stdAc::opmode_t::kHeat;
+ case kPanasonicAcDry: return stdAc::opmode_t::kDry;
+ case kPanasonicAcFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRPanasonicAc::toCommonFanSpeed(const uint8_t spd) {
+ switch (spd) {
+ case kPanasonicAcFanMax: return stdAc::fanspeed_t::kMax;
+ case kPanasonicAcFanMin + 3: return stdAc::fanspeed_t::kHigh;
+ case kPanasonicAcFanMin + 2: return stdAc::fanspeed_t::kMedium;
+ case kPanasonicAcFanMin + 1: return stdAc::fanspeed_t::kLow;
+ case kPanasonicAcFanMin: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingh_t IRPanasonicAc::toCommonSwingH(const uint8_t pos) {
+ switch (pos) {
+ case kPanasonicAcSwingHFullLeft: return stdAc::swingh_t::kLeftMax;
+ case kPanasonicAcSwingHLeft: return stdAc::swingh_t::kLeft;
+ case kPanasonicAcSwingHMiddle: return stdAc::swingh_t::kMiddle;
+ case kPanasonicAcSwingHRight: return stdAc::swingh_t::kRight;
+ case kPanasonicAcSwingHFullRight: return stdAc::swingh_t::kRightMax;
+ default: return stdAc::swingh_t::kAuto;
+ }
+}
+
+// Convert a native vertical swing to it's common equivalent.
+stdAc::swingv_t IRPanasonicAc::toCommonSwingV(const uint8_t pos) {
+ switch (pos) {
+ case kPanasonicAcSwingVUp: return stdAc::swingv_t::kHighest;
+ case kPanasonicAcSwingVDown: return stdAc::swingv_t::kLowest;
+ default: return stdAc::swingv_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRPanasonicAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::PANASONIC_AC;
+ result.model = this->getModel();
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->toCommonSwingV(this->getSwingVertical());
+ result.swingh = this->toCommonSwingH(this->getSwingHorizontal());
+ result.quiet = this->getQuiet();
+ result.turbo = this->getPowerful();
+ // Not supported.
+ result.econo = false;
+ result.clean = false;
+ result.filter = false;
+ result.light = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRPanasonicAc::toString() {
+String IRPanasonicAc::toString(void) {
String result = "";
-#else
-std::string IRPanasonicAc::toString() {
- std::string result = "";
-#endif // ARDUINO
+ result.reserve(180); // Reserve some heap for the string to reduce fragging.
result += F("Model: ");
result += uint64ToString(getModel());
switch (getModel()) {
@@ -717,52 +760,14 @@ std::string IRPanasonicAc::toString() {
default:
result += F(" (UNKNOWN)");
}
- result += F(", Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kPanasonicAcAuto:
- result += F(" (AUTO)");
- break;
- case kPanasonicAcCool:
- result += F(" (COOL)");
- break;
- case kPanasonicAcHeat:
- result += F(" (HEAT)");
- break;
- case kPanasonicAcDry:
- result += F(" (DRY)");
- break;
- case kPanasonicAcFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kPanasonicAcFanAuto:
- result += F(" (AUTO)");
- break;
- case kPanasonicAcFanMax:
- result += F(" (MAX)");
- break;
- case kPanasonicAcFanMin:
- result += F(" (MIN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- break;
- }
- result += F(", Swing (Vertical): ");
- result += uint64ToString(getSwingVertical());
+ result += addBoolToString(getPower(), F("Power"));
+ result += addModeToString(getMode(), kPanasonicAcAuto, kPanasonicAcCool,
+ kPanasonicAcHeat, kPanasonicAcDry, kPanasonicAcFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kPanasonicAcFanMax, kPanasonicAcFanMin,
+ kPanasonicAcFanAuto, kPanasonicAcFanAuto,
+ kPanasonicAcFanMed);
+ result += addIntToString(getSwingVertical(), F("Swing (Vertical)"));
switch (getSwingVertical()) {
case kPanasonicAcSwingVAuto:
result += F(" (AUTO)");
@@ -786,8 +791,7 @@ std::string IRPanasonicAc::toString() {
case kPanasonicCkp:
break; // No Horizontal Swing support.
default:
- result += F(", Swing (Horizontal): ");
- result += uint64ToString(getSwingHorizontal());
+ result += addIntToString(getSwingHorizontal(), F("Swing (Horizontal)"));
switch (getSwingHorizontal()) {
case kPanasonicAcSwingHAuto:
result += F(" (AUTO)");
@@ -812,28 +816,15 @@ std::string IRPanasonicAc::toString() {
break;
}
}
- result += F(", Quiet: ");
- if (getQuiet())
- result += F("On");
- else
- result += F("Off");
- result += F(", Powerful: ");
- if (getPowerful())
- result += F("On");
- else
- result += F("Off");
- result += F(", Clock: ");
- result += timeToString(getClock());
- result += F(", On Timer: ");
- if (isOnTimerEnabled())
- result += timeToString(getOnTimer());
- else
- result += F("Off");
- result += F(", Off Timer: ");
- if (isOffTimerEnabled())
- result += timeToString(getOffTimer());
- else
- result += F("Off");
+ result += addBoolToString(getQuiet(), F("Quiet"));
+ result += addBoolToString(getPowerful(), F("Powerful"));
+ result += addLabeledString(minsToString(getClock()), F("Clock"));
+ result += addLabeledString(
+ isOnTimerEnabled() ? minsToString(getOnTimer()) : F("Off"),
+ F("On Timer"));
+ result += addLabeledString(
+ isOffTimerEnabled() ? minsToString(getOffTimer()) : F("Off"),
+ F("Off Timer"));
return result;
}
@@ -856,11 +847,8 @@ std::string IRPanasonicAc::toString() {
// A/C Remotes:
// A75C3747 (Confirmed)
// A75C3704
-bool IRrecv::decodePanasonicAC(decode_results *results, uint16_t nbits,
- bool strict) {
- if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte.
- return false;
-
+bool IRrecv::decodePanasonicAC(decode_results *results, const uint16_t nbits,
+ const bool strict) {
uint8_t min_nr_of_messages = 1;
if (strict) {
if (nbits != kPanasonicAcBits && nbits != kPanasonicAcShortBits)
@@ -871,79 +859,31 @@ bool IRrecv::decodePanasonicAC(decode_results *results, uint16_t nbits,
min_nr_of_messages * (2 * nbits + kHeader + kFooter) - 1)
return false; // Can't possibly be a valid PANASONIC_AC message.
- uint16_t dataBitsSoFar = 0;
uint16_t offset = kStartOffset;
- match_result_t data_result;
- // Header
- if (!matchMark(results->rawbuf[offset], kPanasonicHdrMark,
- kPanasonicAcTolerance, kPanasonicAcExcess))
- return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t m_tick =
- results->rawbuf[offset++] * kRawTick / kPanasonicHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kPanasonicHdrSpace,
- kPanasonicAcTolerance, kPanasonicAcExcess))
- return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t s_tick =
- results->rawbuf[offset++] * kRawTick / kPanasonicHdrSpaceTicks;
+ // Match Header + Data #1 + Footer
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, kPanasonicAcSection1Length * 8,
+ kPanasonicHdrMark, kPanasonicHdrSpace,
+ kPanasonicBitMark, kPanasonicOneSpace,
+ kPanasonicBitMark, kPanasonicZeroSpace,
+ kPanasonicBitMark, kPanasonicAcSectionGap, false,
+ kPanasonicAcTolerance, kPanasonicAcExcess, false);
+ if (!used) return false;
+ offset += used;
- uint16_t i = 0;
- // Data (Section #1)
- // Keep reading bytes until we either run out of section or state to fill.
- for (; offset <= results->rawlen - 16 && i < kPanasonicAcSection1Length;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- data_result = matchData(
- &(results->rawbuf[offset]), 8, kPanasonicBitMarkTicks * m_tick,
- kPanasonicOneSpaceTicks * s_tick, kPanasonicBitMarkTicks * m_tick,
- kPanasonicZeroSpaceTicks * s_tick, kPanasonicAcTolerance,
- kPanasonicAcExcess, false);
- if (data_result.success == false) {
- DPRINT("DEBUG: offset = ");
- DPRINTLN(offset + data_result.used);
- return false; // Fail
- }
- results->state[i] = data_result.data;
- }
- // Section footer.
- if (!matchMark(results->rawbuf[offset++], kPanasonicBitMarkTicks * m_tick,
- kPanasonicAcTolerance, kPanasonicAcExcess))
+ // Match Header + Data #2 + Footer
+ if (!matchGeneric(results->rawbuf + offset,
+ results->state + kPanasonicAcSection1Length,
+ results->rawlen - offset,
+ nbits - kPanasonicAcSection1Length * 8,
+ kPanasonicHdrMark, kPanasonicHdrSpace,
+ kPanasonicBitMark, kPanasonicOneSpace,
+ kPanasonicBitMark, kPanasonicZeroSpace,
+ kPanasonicBitMark, kPanasonicAcMessageGap, true,
+ kPanasonicAcTolerance, kPanasonicAcExcess, false))
return false;
- if (!matchSpace(results->rawbuf[offset++], kPanasonicAcSectionGap,
- kPanasonicAcTolerance, kPanasonicAcExcess))
- return false;
- // Header.
- if (!matchMark(results->rawbuf[offset++], kPanasonicHdrMarkTicks * m_tick,
- kPanasonicAcTolerance, kPanasonicAcExcess))
- return false;
- if (!matchSpace(results->rawbuf[offset++], kPanasonicHdrSpaceTicks * s_tick,
- kPanasonicAcTolerance, kPanasonicAcExcess))
- return false;
- // Data (Section #2)
- // Keep reading bytes until we either run out of data.
- for (; offset <= results->rawlen - 16 && i < nbits / 8;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- data_result = matchData(
- &(results->rawbuf[offset]), 8, kPanasonicBitMarkTicks * m_tick,
- kPanasonicOneSpaceTicks * s_tick, kPanasonicBitMarkTicks * m_tick,
- kPanasonicZeroSpaceTicks * s_tick, kPanasonicAcTolerance,
- kPanasonicAcExcess, false);
- if (data_result.success == false) {
- DPRINT("DEBUG: offset = ");
- DPRINTLN(offset + data_result.used);
- return false; // Fail
- }
- results->state[i] = data_result.data;
- }
- // Message Footer.
- if (!matchMark(results->rawbuf[offset++], kPanasonicBitMarkTicks * m_tick,
- kPanasonicAcTolerance, kPanasonicAcExcess))
- return false;
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kPanasonicAcMessageGap))
- return false;
-
// Compliance
if (strict) {
// Check the signatures of the section blocks. They start with 0x02& 0x20.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.h b/lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.h
similarity index 67%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.h
index 1a7b4e114..32899db9b 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.h
@@ -1,5 +1,24 @@
// Copyright 2018 David Conran
+// Supports:
+// Brand: Panasonic, Model: TV
+// Brand: Panasonic, Model: JKE series A/C
+// Brand: Panasonic, Model: DKE series A/C
+// Brand: Panasonic, Model: CKP series A/C
+// Brand: Panasonic, Model: CS-ME10CKPG A/C
+// Brand: Panasonic, Model: CS-ME12CKPG A/C
+// Brand: Panasonic, Model: CS-ME14CKPG A/C
+// Brand: Panasonic, Model: RKR series A/C
+// Brand: Panasonic, Model: CS-Z9RKR A/C
+// Brand: Panasonic, Model: NKE series A/C
+// Brand: Panasonic, Model: CS-YW9MKD A/C
+// Brand: Panasonic, Model: A75C3747 remote
+// Brand: Panasonic, Model: A75C3704 remote
+// Brand: Panasonic, Model: A75C2311 remote (CKP)
+// Brand: Panasonic, Model: A75C3747 remote
+// Brand: Panasonic, Model: A75C3747 remote
+// Brand: Panasonic, Model: A75C3747 remote
+
#ifndef IR_PANASONIC_H_
#define IR_PANASONIC_H_
@@ -7,8 +26,6 @@
#include
#ifdef ARDUINO
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -16,12 +33,6 @@
#include "IRsend_test.h"
#endif
-// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC
-// P P A A NN N A A S O O NN N I C
-// PPPP AAAAA N N N AAAAA SSS O O N N N I C
-// P A A N NN A A S O O N NN I C
-// P A A N N A A SSSS OOO N N IIIII CCCC
-
// Panasonic A/C support heavily influenced by:
// https://github.com/ToniA/ESPEasy/blob/HeatpumpIR/lib/HeatpumpIR/PanasonicHeatpumpIR.cpp
@@ -37,6 +48,7 @@ const uint8_t kPanasonicAcCool = 3; // 0b0011
const uint8_t kPanasonicAcHeat = 4; // 0b0010
const uint8_t kPanasonicAcFan = 6; // 0b0110
const uint8_t kPanasonicAcFanMin = 0;
+const uint8_t kPanasonicAcFanMed = 2;
const uint8_t kPanasonicAcFanMax = 4;
const uint8_t kPanasonicAcFanAuto = 7;
const uint8_t kPanasonicAcFanOffset = 3;
@@ -81,62 +93,63 @@ enum panasonic_ac_remote_model_t {
class IRPanasonicAc {
public:
- explicit IRPanasonicAc(uint16_t pin);
+ explicit IRPanasonicAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
- void stateReset();
+ void stateReset(void);
#if SEND_PANASONIC
void send(const uint16_t repeat = kPanasonicAcDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_PANASONIC
- void begin();
- void on();
- void off();
- void setPower(const bool state);
- bool getPower();
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
void setTemp(const uint8_t temp, const bool remember = true);
- uint8_t getTemp();
+ uint8_t getTemp(void);
void setFan(const uint8_t fan);
- uint8_t getFan();
+ uint8_t getFan(void);
void setMode(const uint8_t mode);
- uint8_t getMode();
+ uint8_t getMode(void);
void setRaw(const uint8_t state[]);
- uint8_t *getRaw();
+ uint8_t *getRaw(void);
static bool validChecksum(uint8_t *state,
const uint16_t length = kPanasonicAcStateLength);
static uint8_t calcChecksum(uint8_t *state,
const uint16_t length = kPanasonicAcStateLength);
- void setQuiet(const bool state);
- bool getQuiet();
- void setPowerful(const bool state);
- bool getPowerful();
+ void setQuiet(const bool on);
+ bool getQuiet(void);
+ void setPowerful(const bool on);
+ bool getPowerful(void);
void setModel(const panasonic_ac_remote_model_t model);
- panasonic_ac_remote_model_t getModel();
+ panasonic_ac_remote_model_t getModel(void);
void setSwingVertical(const uint8_t elevation);
- uint8_t getSwingVertical();
+ uint8_t getSwingVertical(void);
void setSwingHorizontal(const uint8_t direction);
- uint8_t getSwingHorizontal();
+ uint8_t getSwingHorizontal(void);
static uint16_t encodeTime(const uint8_t hours, const uint8_t mins);
- uint16_t getClock();
+ uint16_t getClock(void);
void setClock(const uint16_t mins_since_midnight);
- uint16_t getOnTimer();
+ uint16_t getOnTimer(void);
void setOnTimer(const uint16_t mins_since_midnight, const bool enable = true);
- void cancelOnTimer();
- bool isOnTimerEnabled();
- uint16_t getOffTimer();
+ void cancelOnTimer(void);
+ bool isOnTimerEnabled(void);
+ uint16_t getOffTimer(void);
void setOffTimer(const uint16_t mins_since_midnight,
const bool enable = true);
- void cancelOffTimer();
- bool isOffTimerEnabled();
+ void cancelOffTimer(void);
+ bool isOffTimerEnabled(void);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
uint8_t convertSwingV(const stdAc::swingv_t position);
uint8_t convertSwingH(const stdAc::swingh_t position);
-#ifdef ARDUINO
- String toString();
- static String timeToString(const uint16_t mins_since_midnight);
-#else
- std::string toString();
- static std::string timeToString(const uint16_t mins_since_midnight);
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ static stdAc::swingv_t toCommonSwingV(const uint8_t pos);
+ static stdAc::swingh_t toCommonSwingH(const uint8_t pos);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Pioneer.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Pioneer.cpp
similarity index 55%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Pioneer.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Pioneer.cpp
index 9134e3696..490ea9440 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Pioneer.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Pioneer.cpp
@@ -1,6 +1,9 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017, 2018 David Conran
// Copyright 2018 Kamil Palczewski
+// Copyright 2019 s-hadinger
+
+// Pioneer remote emulation
#define __STDC_LIMIT_MACROS
#include
@@ -8,16 +11,26 @@
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
-#include "ir_NEC.h"
-
-// PPPP III OOO N N EEEE EEEE RRRR
-// P P I O O NN N E E R R
-// PPPP I O O N N N EEE EEE RRRR
-// P I O O N NN E E R R
-// P III OOO N N EEEE EEEE R RR
+// Constants
// Ref:
-// http://adrian-kingston.com/IRFormatPioneer.htm
+// http://www.adrian-kingston.com/IRFormatPioneer.htm
+const uint16_t kPioneerTick = 534;
+const uint16_t kPioneerHdrMarkTicks = 16;
+const uint16_t kPioneerHdrMark = kPioneerHdrMarkTicks * kPioneerTick;
+const uint16_t kPioneerHdrSpaceTicks = 8;
+const uint16_t kPioneerHdrSpace = kPioneerHdrSpaceTicks * kPioneerTick;
+const uint16_t kPioneerBitMarkTicks = 1;
+const uint16_t kPioneerBitMark = kPioneerBitMarkTicks * kPioneerTick;
+const uint16_t kPioneerOneSpaceTicks = 3;
+const uint16_t kPioneerOneSpace = kPioneerOneSpaceTicks * kPioneerTick;
+const uint16_t kPioneerZeroSpaceTicks = 1;
+const uint16_t kPioneerZeroSpace = kPioneerZeroSpaceTicks * kPioneerTick;
+const uint16_t kPioneerMinCommandLengthTicks = 159;
+const uint32_t kPioneerMinCommandLength = kPioneerMinCommandLengthTicks *
+ kPioneerTick;
+const uint16_t kPioneerMinGapTicks = 47;
+const uint32_t kPioneerMinGap = kPioneerMinGapTicks * kPioneerTick;
#if SEND_PIONEER
// Send a raw Pioneer formatted message.
@@ -34,13 +47,25 @@
// http://adrian-kingston.com/IRFormatPioneer.htm
void IRsend::sendPioneer(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
- // If nbits is to big, or is odd, abort.
- if (nbits > sizeof(data) * 8 || nbits % 2 == 1) return;
-
- // send 1st part of the code
- sendNEC(data >> (nbits / 2), nbits / 2, 0);
- // send 2nd part of the code
- sendNEC(data & (((uint64_t)1 << (nbits / 2)) - 1), nbits / 2, repeat);
+ // If nbits is to big, abort.
+ if (nbits > sizeof(data) * 8) return;
+ for (uint16_t r = 0; r <= repeat; r++) {
+ // don't use NEC repeat but repeat the whole sequence
+ if (nbits > 32) {
+ sendGeneric(kPioneerHdrMark, kPioneerHdrSpace,
+ kPioneerBitMark, kPioneerOneSpace,
+ kPioneerBitMark, kPioneerZeroSpace,
+ kPioneerBitMark, kPioneerMinGap,
+ kPioneerMinCommandLength,
+ data >> 32, nbits - 32, 40, true, 0, 33);
+ }
+ sendGeneric(kPioneerHdrMark, kPioneerHdrSpace,
+ kPioneerBitMark, kPioneerOneSpace,
+ kPioneerBitMark, kPioneerZeroSpace,
+ kPioneerBitMark, kPioneerMinGap,
+ kPioneerMinCommandLength,
+ data, nbits > 32 ? 32 : nbits, 40, true, 0, 33);
+ }
}
// Calculate the raw Pioneer data code based on two NEC sub-codes
@@ -87,28 +112,22 @@ bool IRrecv::decodePioneer(decode_results *results, const uint16_t nbits,
uint64_t data = 0;
uint16_t offset = kStartOffset;
-
+ results->value = 0;
for (uint16_t section = 0; section < 2; section++) {
- // Header
- if (!matchMark(results->rawbuf[offset], kNecHdrMark)) return false;
- // Calculate how long the lowest tick time is based on the header mark.
- uint32_t mark_tick =
- results->rawbuf[offset++] * kRawTick / kNecHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kNecHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t space_tick =
- results->rawbuf[offset++] * kRawTick / kNecHdrSpaceTicks;
- //
- // Data
- match_result_t data_result = matchData(
- &(results->rawbuf[offset]), nbits / 2, kNecBitMarkTicks * mark_tick,
- kNecOneSpaceTicks * space_tick, kNecBitMarkTicks * mark_tick,
- kNecZeroSpaceTicks * space_tick);
- if (data_result.success == false) return false;
- uint8_t command = data_result.data >> 8;
- uint8_t command_inverted = data_result.data;
- uint8_t address = data_result.data >> 24;
- uint8_t address_inverted = data_result.data >> 16;
+ // Match Header + Data + Footer
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits / 2,
+ kPioneerHdrMark, kPioneerHdrSpace,
+ kPioneerBitMark, kPioneerOneSpace,
+ kPioneerBitMark, kPioneerZeroSpace,
+ kPioneerBitMark, kPioneerMinGap, true);
+ if (!used) return false;
+ offset += used;
+ uint8_t command = data >> 8;
+ uint8_t command_inverted = data;
+ uint8_t address = data >> 24;
+ uint8_t address_inverted = data >> 16;
// Compliance
if (strict) {
if (command != (command_inverted ^ 0xFF))
@@ -116,8 +135,7 @@ bool IRrecv::decodePioneer(decode_results *results, const uint16_t nbits,
if (address != (address_inverted ^ 0xFF))
return false; // Address integrity failed.
}
- data = (data << (nbits / 2)) + data_result.data;
- offset += data_result.used;
+ results->value = (results->value << (nbits / 2)) + data;
// NEC-like commands and addresses are technically in LSB first order so the
// final versions have to be reversed.
uint16_t code = reverseBits((command << 8) + address, 16);
@@ -125,18 +143,10 @@ bool IRrecv::decodePioneer(decode_results *results, const uint16_t nbits,
results->command = code;
else
results->address = code;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kNecBitMarkTicks * mark_tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kNecMinGapTicks * space_tick))
- return false;
}
// Success
results->bits = nbits;
- results->value = data;
results->decode_type = PIONEER;
return true;
}
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Pronto.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Pronto.cpp
similarity index 92%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Pronto.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Pronto.cpp
index 9ab5c76d0..a408afed5 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Pronto.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Pronto.cpp
@@ -1,14 +1,10 @@
// Copyright 2017 David Conran
+// Pronto code message generation
+
#include
#include "IRsend.h"
-// PPPPPP tt
-// PP PP rr rr oooo nn nnn tt oooo
-// PPPPPP rrr r oo oo nnn nn tttt oo oo
-// PP rr oo oo nn nn tt oo oo
-// PP rr oooo nn nn tttt oooo
-
// Constants
const float kProntoFreqFactor = 0.241246;
const uint16_t kProntoTypeOffset = 0;
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_RC5_RC6.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_RC5_RC6.cpp
similarity index 97%
rename from lib/IRremoteESP8266-2.6.0/src/ir_RC5_RC6.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_RC5_RC6.cpp
index ef1500d60..b79416692 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_RC5_RC6.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_RC5_RC6.cpp
@@ -1,21 +1,15 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017 David Conran
+// RC-5 & RC-6 support added from https://github.com/z3t0/Arduino-IRremote
+// RC-5X support added by David Conran
+
#include
#include "IRrecv.h"
#include "IRsend.h"
#include "IRtimer.h"
#include "IRutils.h"
-// RRRRRR CCCCC 555555 XX XX RRRRRR CCCCC 666
-// RR RR CC C 55 XX XX RR RR CC C 66
-// RRRRRR CC _____ 555555 XXXX RRRRRR CC _____ 666666
-// RR RR CC C 5555 XX XX RR RR CC C 66 66
-// RR RR CCCCC 555555 XX XX RR RR CCCCC 66666
-
-// RC-5 & RC-6 support added from https://github.com/z3t0/Arduino-IRremote
-// RC-5X support added by David Conran
-
// Constants
// RC-5/RC-5X
// Ref:
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_RCMM.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_RCMM.cpp
similarity index 93%
rename from lib/IRremoteESP8266-2.6.0/src/ir_RCMM.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_RCMM.cpp
index 1b03d2c07..4e8f43891 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_RCMM.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_RCMM.cpp
@@ -1,19 +1,16 @@
// Copyright 2017 David Conran
+// Send & decode support for Phillips RC-MM added by David Conran
+
+// Supports:
+// Brand: Microsoft, Model: XBOX 360
+
#include
#include "IRrecv.h"
#include "IRsend.h"
#include "IRtimer.h"
#include "IRutils.h"
-// RRRRRR CCCCC MM MM MM MM
-// RR RR CC C MMM MMM MMM MMM
-// RRRRRR CC _____ MM MM MM MM MM MM
-// RR RR CC C MM MM MM MM
-// RR RR CCCCC MM MM MM MM
-
-// Send & decode support for RC-MM added by David Conran
-
// Constants
// Ref:
// http://www.sbprojects.com/knowledge/ir/rcmm.php
@@ -144,11 +141,9 @@ bool IRrecv::decodeRCMM(decode_results *results, uint16_t nbits, bool strict) {
data <<= 2;
// Use non-default tolerance & excess for matching some of the spaces as the
// defaults are too generous and causes mis-matches in some cases.
- if (match(results->rawbuf[offset], kRcmmBitSpace0Ticks * s_tick,
- kTolerance))
+ if (match(results->rawbuf[offset], kRcmmBitSpace0Ticks * s_tick))
data += 0;
- else if (match(results->rawbuf[offset], kRcmmBitSpace1Ticks * s_tick,
- kTolerance))
+ else if (match(results->rawbuf[offset], kRcmmBitSpace1Ticks * s_tick))
data += 1;
else if (match(results->rawbuf[offset], kRcmmBitSpace2Ticks * s_tick,
kRcmmTolerance))
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Samsung.cpp
similarity index 64%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Samsung.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Samsung.cpp
index 7e54d17df..77985b1c4 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Samsung.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Samsung.cpp
@@ -1,6 +1,8 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017, 2018, 2019 David Conran
+// Samsung remote emulation
+
#include "ir_Samsung.h"
#include
#ifndef ARDUINO
@@ -10,12 +12,6 @@
#include "IRsend.h"
#include "IRutils.h"
-// SSSS AAA MMM SSSS U U N N GGGG
-// S A A M M M S U U NN N G
-// SSS AAAAA M M M SSS U U N N N G GG
-// S A A M M S U U N NN G G
-// SSSS A A M M SSSS UUU N N GGG
-
// Samsung originally added from https://github.com/shirriff/Arduino-IRremote/
// Constants
@@ -54,6 +50,13 @@ const uint16_t kSamsungAcBitMark = 586;
const uint16_t kSamsungAcOneSpace = 1432;
const uint16_t kSamsungAcZeroSpace = 436;
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
#if SEND_SAMSUNG
// Send a Samsung formatted message.
// Samsung has a separate message to indicate a repeat, like NEC does.
@@ -68,7 +71,8 @@ const uint16_t kSamsungAcZeroSpace = 436;
// Status: BETA / Should be working.
//
// Ref: http://elektrolab.wz.cz/katalog/samsung_protocol.pdf
-void IRsend::sendSAMSUNG(uint64_t data, uint16_t nbits, uint16_t repeat) {
+void IRsend::sendSAMSUNG(const uint64_t data, const uint16_t nbits,
+ const uint16_t repeat) {
sendGeneric(kSamsungHdrMark, kSamsungHdrSpace, kSamsungBitMark,
kSamsungOneSpace, kSamsungBitMark, kSamsungZeroSpace,
kSamsungBitMark, kSamsungMinGap, kSamsungMinMessageLength, data,
@@ -85,11 +89,11 @@ void IRsend::sendSAMSUNG(uint64_t data, uint16_t nbits, uint16_t repeat) {
// A raw 32-bit Samsung message suitable for sendSAMSUNG().
//
// Status: BETA / Should be working.
-uint32_t IRsend::encodeSAMSUNG(uint8_t customer, uint8_t command) {
- customer = reverseBits(customer, sizeof(customer) * 8);
- command = reverseBits(command, sizeof(command) * 8);
- return ((command ^ 0xFF) | (command << 8) | (customer << 16) |
- (customer << 24));
+uint32_t IRsend::encodeSAMSUNG(const uint8_t customer, const uint8_t command) {
+ uint8_t revcustomer = reverseBits(customer, sizeof(customer) * 8);
+ uint8_t revcommand = reverseBits(command, sizeof(command) * 8);
+ return ((revcommand ^ 0xFF) | (revcommand << 8) | (revcustomer << 16) |
+ (revcustomer << 24));
}
#endif
@@ -113,8 +117,8 @@ uint32_t IRsend::encodeSAMSUNG(uint8_t customer, uint8_t command) {
// They differ on their compliance criteria and how they repeat.
// Ref:
// http://elektrolab.wz.cz/katalog/samsung_protocol.pdf
-bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits,
- bool strict) {
+bool IRrecv::decodeSAMSUNG(decode_results *results, const uint16_t nbits,
+ const bool strict) {
if (results->rawlen < 2 * nbits + kHeader + kFooter - 1)
return false; // Can't possibly be a valid Samsung message.
if (strict && nbits != kSamsungBits)
@@ -123,31 +127,14 @@ bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits,
uint64_t data = 0;
uint16_t offset = kStartOffset;
- // Header
- if (!matchMark(results->rawbuf[offset], kSamsungHdrMark)) return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kSamsungHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kSamsungHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t s_tick =
- results->rawbuf[offset++] * kRawTick / kSamsungHdrSpaceTicks;
- // Data
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits,
- kSamsungBitMarkTicks * m_tick, kSamsungOneSpaceTicks * s_tick,
- kSamsungBitMarkTicks * m_tick, kSamsungZeroSpaceTicks * s_tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
- // Footer
- if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kSamsungMinGapTicks * s_tick))
- return false;
-
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kSamsungHdrMark, kSamsungHdrSpace,
+ kSamsungBitMark, kSamsungOneSpace,
+ kSamsungBitMark, kSamsungZeroSpace,
+ kSamsungBitMark, kSamsungMinGap, true)) return false;
// Compliance
-
// According to the spec, the customer (address) code is the first 8
// transmitted bits. It's then repeated. Check for that.
uint8_t address = data >> 24;
@@ -182,7 +169,7 @@ bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits,
// Protocol is used by Samsung Bluray Remote: ak59-00167a
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/621
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/621
void IRsend::sendSamsung36(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
if (nbits < 16) return; // To small to send.
@@ -222,7 +209,7 @@ void IRsend::sendSamsung36(const uint64_t data, const uint16_t nbits,
// Protocol is used by Samsung Bluray Remote: ak59-00167a
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/621
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/621
bool IRrecv::decodeSamsung36(decode_results *results, const uint16_t nbits,
const bool strict) {
if (results->rawlen < 2 * nbits + kHeader + kFooter * 2 - 1)
@@ -235,52 +222,29 @@ bool IRrecv::decodeSamsung36(decode_results *results, const uint16_t nbits,
uint64_t data = 0;
uint16_t offset = kStartOffset;
- // Header
- if (!matchMark(results->rawbuf[offset], kSamsungHdrMark)) return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kSamsungHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kSamsungHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t s_tick =
- results->rawbuf[offset++] * kRawTick / kSamsungHdrSpaceTicks;
- // Data (Block #1)
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), 16,
- kSamsungBitMarkTicks * m_tick, kSamsungOneSpaceTicks * s_tick,
- kSamsungBitMarkTicks * m_tick, kSamsungZeroSpaceTicks * s_tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
- uint16_t bitsSoFar = data_result.used / 2;
- // Footer (Block #1)
- if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick))
- return false;
- if (!matchSpace(results->rawbuf[offset++], kSamsungHdrSpaceTicks * s_tick))
- return false;
+ // Match Header + Data + Footer
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, 16,
+ kSamsungHdrMark, kSamsungHdrSpace,
+ kSamsungBitMark, kSamsungOneSpace,
+ kSamsungBitMark, kSamsungZeroSpace,
+ kSamsungBitMark, kSamsungHdrSpace, false);
+ if (!used) return false;
+ offset += used;
// Data (Block #2)
- data_result = matchData(&(results->rawbuf[offset]),
- nbits - 16,
- kSamsungBitMarkTicks * m_tick,
- kSamsungOneSpaceTicks * s_tick,
- kSamsungBitMarkTicks * m_tick,
- kSamsungZeroSpaceTicks * s_tick);
- if (data_result.success == false) return false;
+ uint64_t data2 = 0;
+ if (!matchGeneric(results->rawbuf + offset, &data2,
+ results->rawlen - offset, nbits - 16,
+ 0, 0,
+ kSamsungBitMark, kSamsungOneSpace,
+ kSamsungBitMark, kSamsungZeroSpace,
+ kSamsungBitMark, kSamsungMinGap, true)) return false;
data <<= (nbits - 16);
- data += data_result.data;
- offset += data_result.used;
- bitsSoFar += data_result.used / 2;
- // Footer (Block #2)
- if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kSamsungMinGapTicks * s_tick))
- return false;
-
- // Compliance
- if (nbits != bitsSoFar) return false;
+ data += data2;
// Success
- results->bits = bitsSoFar;
+ results->bits = nbits;
results->value = data;
results->decode_type = SAMSUNG36;
results->command = data & ((1ULL << (nbits - 16)) - 1);
@@ -297,10 +261,10 @@ bool IRrecv::decodeSamsung36(decode_results *results, const uint16_t nbits,
// nbytes: Nr. of bytes of data in the array. (>=kSamsungAcStateLength)
// repeat: Nr. of times the message is to be repeated. (Default = 0).
//
-// Status: ALPHA / Untested.
+// Status: Stable / Known working.
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/505
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/505
void IRsend::sendSamsungAC(const uint8_t data[], const uint16_t nbytes,
const uint16_t repeat) {
if (nbytes < kSamsungAcStateLength && nbytes % kSamsungACSectionLength)
@@ -326,9 +290,13 @@ void IRsend::sendSamsungAC(const uint8_t data[], const uint16_t nbytes,
}
#endif // SEND_SAMSUNG_AC
-IRSamsungAc::IRSamsungAc(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRSamsungAc::IRSamsungAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) {
+ this->stateReset();
+}
-void IRSamsungAc::stateReset() {
+void IRSamsungAc::stateReset(void) {
for (uint8_t i = 0; i < kSamsungAcExtendedStateLength; i++)
remote_state[i] = 0x0;
remote_state[0] = 0x02;
@@ -341,9 +309,10 @@ void IRSamsungAc::stateReset() {
remote_state[10] = 0x71;
remote_state[12] = 0x15;
remote_state[13] = 0xF0;
+ _sendpower = false;
}
-void IRSamsungAc::begin() { _irsend.begin(); }
+void IRSamsungAc::begin(void) { _irsend.begin(); }
uint8_t IRSamsungAc::calcChecksum(const uint8_t state[],
const uint16_t length) {
@@ -365,25 +334,35 @@ bool IRSamsungAc::validChecksum(const uint8_t state[], const uint16_t length) {
return true; // No checksum to compare with. Assume okay.
uint8_t offset = 0;
if (length >= kSamsungAcExtendedStateLength) offset = 7;
- return ((state[length - 6] >> 4) == calcChecksum(state, length) &&
- (state[length - (13 + offset)] >> 4) == calcChecksum(state, length -
- (7 + offset)));
+ return ((state[length - 6] >> 4) == IRSamsungAc::calcChecksum(state, length)
+ && (state[length - (13 + offset)] >> 4) == IRSamsungAc::calcChecksum(
+ state, length - (7 + offset)));
}
// Update the checksum for the internal state.
void IRSamsungAc::checksum(uint16_t length) {
if (length < 13) return;
remote_state[length - 6] &= 0x0F;
- remote_state[length - 6] |= (calcChecksum(remote_state, length) << 4);
+ remote_state[length - 6] |= (this->calcChecksum(remote_state, length) << 4);
remote_state[length - 13] &= 0x0F;
- remote_state[length - 13] |= (calcChecksum(remote_state, length - 7) << 4);
+ remote_state[length - 13] |= (this->calcChecksum(remote_state,
+ length - 7) << 4);
}
#if SEND_SAMSUNG_AC
// Use for most function/mode/settings changes to the unit.
// i.e. When the device is already running.
void IRSamsungAc::send(const uint16_t repeat, const bool calcchecksum) {
- if (calcchecksum) checksum();
+ if (calcchecksum) this->checksum();
+ if (_sendpower) { // Do we need to send a the special power on/off message?
+ _sendpower = false; // It will now been sent.
+ if (this->getPower()) {
+ this->sendOn();
+ } else {
+ this->sendOff();
+ return; // No point sending anything else if we are turning the unit off.
+ }
+ }
_irsend.sendSamsungAC(remote_state, kSamsungAcStateLength, repeat);
}
@@ -391,7 +370,7 @@ void IRSamsungAc::send(const uint16_t repeat, const bool calcchecksum) {
// Samsung A/C requires an extended length message when you want to
// change the power operating mode of the A/C unit.
void IRSamsungAc::sendExtended(const uint16_t repeat, const bool calcchecksum) {
- if (calcchecksum) checksum();
+ if (calcchecksum) this->checksum();
uint8_t extended_state[kSamsungAcExtendedStateLength] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00,
@@ -409,7 +388,7 @@ void IRSamsungAc::sendExtended(const uint16_t repeat, const bool calcchecksum) {
// Send the special extended "On" message as the library can't seem to reproduce
// this message automatically.
-// See: https://github.com/markszabo/IRremoteESP8266/issues/604#issuecomment-475020036
+// See: https://github.com/crankyoldgit/IRremoteESP8266/issues/604#issuecomment-475020036
void IRSamsungAc::sendOn(const uint16_t repeat) {
const uint8_t extended_state[21] = {
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
@@ -420,7 +399,7 @@ void IRSamsungAc::sendOn(const uint16_t repeat) {
// Send the special extended "Off" message as the library can't seem to
// reproduce this message automatically.
-// See: https://github.com/markszabo/IRremoteESP8266/issues/604#issuecomment-475020036
+// See: https://github.com/crankyoldgit/IRremoteESP8266/issues/604#issuecomment-475020036
void IRSamsungAc::sendOff(const uint16_t repeat) {
const uint8_t extended_state[21] = {
0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0,
@@ -430,8 +409,8 @@ void IRSamsungAc::sendOff(const uint16_t repeat) {
}
#endif // SEND_SAMSUNG_AC
-uint8_t *IRSamsungAc::getRaw() {
- checksum();
+uint8_t *IRSamsungAc::getRaw(void) {
+ this->checksum();
return remote_state;
}
@@ -446,26 +425,28 @@ void IRSamsungAc::setRaw(const uint8_t new_code[], const uint16_t length) {
}
}
-void IRSamsungAc::on() {
- remote_state[1] &= ~kSamsungAcPowerMask1;
- remote_state[6] |= kSamsungAcPowerMask2;
+void IRSamsungAc::on(void) {
+ remote_state[1] &= ~kSamsungAcPowerMask1; // Bit needs to be cleared.
+ remote_state[6] |= kSamsungAcPowerMask6; // Bit needs to be set.
+ _sendpower = true; // Flag that we need to send the special power message(s).
}
-void IRSamsungAc::off() {
- remote_state[1] |= kSamsungAcPowerMask1;
- remote_state[6] &= ~kSamsungAcPowerMask2;
+void IRSamsungAc::off(void) {
+ remote_state[1] |= kSamsungAcPowerMask1; // Bit needs to be set.
+ remote_state[6] &= ~kSamsungAcPowerMask6; // Bit needs to be cleared.
+ _sendpower = true; // Flag that we need to send the special power message(s).
}
-void IRSamsungAc::setPower(const bool state) {
- if (state)
- on();
+void IRSamsungAc::setPower(const bool on) {
+ if (on)
+ this->on();
else
- off();
+ this->off();
}
-bool IRSamsungAc::getPower() {
- return ((remote_state[6] & kSamsungAcPowerMask2) != 0) &&
- ((remote_state[1] & kSamsungAcPowerMask1) == 0);
+bool IRSamsungAc::getPower(void) {
+ return (remote_state[6] & kSamsungAcPowerMask6) &&
+ !(remote_state[1] & kSamsungAcPowerMask1);
}
// Set the temp. in deg C
@@ -477,7 +458,7 @@ void IRSamsungAc::setTemp(const uint8_t temp) {
}
// Return the set temp. in deg C
-uint8_t IRSamsungAc::getTemp() {
+uint8_t IRSamsungAc::getTemp(void) {
return ((remote_state[11] & kSamsungAcTempMask) >> 4) + kSamsungAcMinTemp;
}
@@ -489,14 +470,15 @@ void IRSamsungAc::setMode(const uint8_t mode) {
// Auto mode has a special fan setting valid only in auto mode.
if (newmode == kSamsungAcAuto) {
- setFan(kSamsungAcFanAuto2);
+ this->setFan(kSamsungAcFanAuto2);
} else {
- if (getFan() == kSamsungAcFanAuto2) // Non-Auto can't have this fan setting
- setFan(kSamsungAcFanAuto); // Default to something safe.
+ // Non-Auto can't have this fan setting
+ if (this->getFan() == kSamsungAcFanAuto2)
+ this->setFan(kSamsungAcFanAuto); // Default to something safe.
}
}
-uint8_t IRSamsungAc::getMode() {
+uint8_t IRSamsungAc::getMode(void) {
return (remote_state[12] & kSamsungAcModeMask) >> 4;
}
@@ -507,10 +489,10 @@ void IRSamsungAc::setFan(const uint8_t speed) {
case kSamsungAcFanMed:
case kSamsungAcFanHigh:
case kSamsungAcFanTurbo:
- if (getMode() == kSamsungAcAuto) return; // Not valid in Auto mode.
+ if (this->getMode() == kSamsungAcAuto) return; // Not valid in Auto mode.
break;
case kSamsungAcFanAuto2: // Special fan setting for when in Auto mode.
- if (getMode() != kSamsungAcAuto) return;
+ if (this->getMode() != kSamsungAcAuto) return;
break;
default:
return;
@@ -518,42 +500,44 @@ void IRSamsungAc::setFan(const uint8_t speed) {
remote_state[12] = (remote_state[12] & ~kSamsungAcFanMask) | (speed << 1);
}
-uint8_t IRSamsungAc::getFan() {
+uint8_t IRSamsungAc::getFan(void) {
return ((remote_state[12] & kSamsungAcFanMask) >> 1);
}
-bool IRSamsungAc::getSwing() {
+bool IRSamsungAc::getSwing(void) {
// TODO(Hollako): Explain why sometimes the LSB of remote_state[9] is a 1.
// e.g. 0xAE or 0XAF for swing move.
return ((remote_state[9] & kSamsungAcSwingMask) >> 4) == kSamsungAcSwingMove;
}
-void IRSamsungAc::setSwing(const bool state) {
+void IRSamsungAc::setSwing(const bool on) {
// TODO(Hollako): Explain why sometimes the LSB of remote_state[9] is a 1.
// e.g. 0xAE or 0XAF for swing move.
remote_state[9] &= ~kSamsungAcSwingMask; // Clear the previous swing state.
- if (state)
+ if (on)
remote_state[9] |= (kSamsungAcSwingMove << 4);
else
remote_state[9] |= (kSamsungAcSwingStop << 4);
}
-bool IRSamsungAc::getBeep() { return remote_state[13] & kSamsungAcBeepMask; }
+bool IRSamsungAc::getBeep(void) {
+ return remote_state[13] & kSamsungAcBeepMask;
+}
-void IRSamsungAc::setBeep(const bool state) {
- if (state)
+void IRSamsungAc::setBeep(const bool on) {
+ if (on)
remote_state[13] |= kSamsungAcBeepMask;
else
remote_state[13] &= ~kSamsungAcBeepMask;
}
-bool IRSamsungAc::getClean() {
+bool IRSamsungAc::getClean(void) {
return (remote_state[10] & kSamsungAcCleanMask10) &&
(remote_state[11] & kSamsungAcCleanMask11);
}
-void IRSamsungAc::setClean(const bool state) {
- if (state) {
+void IRSamsungAc::setClean(const bool on) {
+ if (on) {
remote_state[10] |= kSamsungAcCleanMask10;
remote_state[11] |= kSamsungAcCleanMask11;
} else {
@@ -562,18 +546,42 @@ void IRSamsungAc::setClean(const bool state) {
}
}
-// Very unsure this is correct.
-bool IRSamsungAc::getQuiet() {
- return remote_state[11] & kSamsungAcQuietMask11;
+bool IRSamsungAc::getQuiet(void) {
+ return !(remote_state[1] & kSamsungAcQuietMask1) &&
+ (remote_state[5] & kSamsungAcQuietMask5);
}
-// Very unsure this is correct.
-void IRSamsungAc::setQuiet(const bool state) {
- if (state) {
- remote_state[11] |= kSamsungAcQuietMask11;
- setFan(kSamsungAcFanAuto); // Quiet mode seems to set fan speed to auto.
+void IRSamsungAc::setQuiet(const bool on) {
+ if (on) {
+ remote_state[1] &= ~kSamsungAcQuietMask1; // Bit needs to be cleared.
+ remote_state[5] |= kSamsungAcQuietMask5; // Bit needs to be set.
+ // Quiet mode seems to set fan speed to auto.
+ this->setFan(kSamsungAcFanAuto);
+ this->setPowerful(false); // Quiet 'on' is mutually exclusive to Powerful.
} else {
- remote_state[11] &= ~kSamsungAcQuietMask11;
+ remote_state[1] |= kSamsungAcQuietMask1; // Bit needs to be set.
+ remote_state[5] &= ~kSamsungAcQuietMask5; // Bit needs to be cleared.
+ }
+}
+
+bool IRSamsungAc::getPowerful(void) {
+ return !(remote_state[8] & kSamsungAcPowerfulMask8) &&
+ (remote_state[10] & kSamsungAcPowerfulMask10) &&
+ this->getFan() == kSamsungAcFanTurbo;
+}
+
+void IRSamsungAc::setPowerful(const bool on) {
+ if (on) {
+ remote_state[8] &= ~kSamsungAcPowerfulMask8; // Bit needs to be cleared.
+ remote_state[10] |= kSamsungAcPowerfulMask10; // Bit needs to be set.
+ // Powerful mode sets fan speed to Turbo.
+ this->setFan(kSamsungAcFanTurbo);
+ this->setQuiet(false); // Powerful 'on' is mutually exclusive to Quiet.
+ } else {
+ remote_state[8] |= kSamsungAcPowerfulMask8; // Bit needs to be set.
+ remote_state[10] &= ~kSamsungAcPowerfulMask10; // Bit needs to be cleared.
+ // Turning off Powerful mode sets fan speed to Auto if we were in Turbo mode
+ if (this->getFan() == kSamsungAcFanTurbo) this->setFan(kSamsungAcFanAuto);
}
}
@@ -610,85 +618,90 @@ uint8_t IRSamsungAc::convertFan(const stdAc::fanspeed_t speed) {
}
}
-// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRSamsungAc::toString() {
- String result = "";
-#else
-std::string IRSamsungAc::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kSamsungAcAuto:
- result += F(" (AUTO)");
- break;
- case kSamsungAcCool:
- result += F(" (COOL)");
- break;
- case kSamsungAcHeat:
- result += F(" (HEAT)");
- break;
- case kSamsungAcDry:
- result += F(" (DRY)");
- break;
- case kSamsungAcFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRSamsungAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kSamsungAcCool: return stdAc::opmode_t::kCool;
+ case kSamsungAcHeat: return stdAc::opmode_t::kHeat;
+ case kSamsungAcDry: return stdAc::opmode_t::kDry;
+ case kSamsungAcFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
}
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRSamsungAc::toCommonFanSpeed(const uint8_t spd) {
+ switch (spd) {
+ case kSamsungAcFanTurbo: return stdAc::fanspeed_t::kMax;
+ case kSamsungAcFanHigh: return stdAc::fanspeed_t::kHigh;
+ case kSamsungAcFanMed: return stdAc::fanspeed_t::kMedium;
+ case kSamsungAcFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRSamsungAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::SAMSUNG_AC;
+ result.model = -1; // Not supported.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwing() ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.quiet = this->getQuiet();
+ result.turbo = this->getPowerful();
+ result.clean = this->getClean();
+ result.beep = this->getBeep();
+ // Not supported.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.econo = false;
+ result.filter = false;
+ result.light = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRSamsungAc::toString(void) {
+ String result = "";
+ result.reserve(100); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kSamsungAcAuto, kSamsungAcCool,
+ kSamsungAcHeat, kSamsungAcDry,
+ kSamsungAcFan);
+ result += addTempToString(getTemp());
+ result += addIntToString(getFan(), F("Fan"));
switch (getFan()) {
case kSamsungAcFanAuto:
case kSamsungAcFanAuto2:
- result += F(" (AUTO)");
+ result += F(" (Auto)");
break;
case kSamsungAcFanLow:
- result += F(" (LOW)");
+ result += F(" (Low)");
break;
case kSamsungAcFanMed:
- result += F(" (MED)");
+ result += F(" (Medium)");
break;
case kSamsungAcFanHigh:
- result += F(" (HIGH)");
+ result += F(" (High)");
break;
case kSamsungAcFanTurbo:
- result += F(" (TURBO)");
+ result += F(" (Turbo)");
break;
default:
result += F(" (UNKNOWN)");
break;
}
- result += F(", Swing: ");
- if (getSwing())
- result += F("On");
- else
- result += F("Off");
- result += F(", Beep: ");
- if (getBeep())
- result += F("On");
- else
- result += F("Off");
- result += F(", Clean: ");
- if (getBeep())
- result += F("On");
- else
- result += F("Off");
- result += F(", Quiet: ");
- if (getQuiet())
- result += F("On");
- else
- result += F("Off");
+ result += addBoolToString(getSwing(), F("Swing"));
+ result += addBoolToString(getBeep(), F("Beep"));
+ result += addBoolToString(getClean(), F("Clean"));
+ result += addBoolToString(getQuiet(), F("Quiet"));
+ result += addBoolToString(getPowerful(), F("Powerful"));
return result;
}
@@ -702,62 +715,38 @@ std::string IRSamsungAc::toString() {
// Returns:
// boolean: True if it can decode it, false if it can't.
//
-// Status: BETA / Appears to mostly work.
+// Status: Stable / Known to be working.
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/505
-bool IRrecv::decodeSamsungAC(decode_results *results, uint16_t nbits,
- bool strict) {
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/505
+bool IRrecv::decodeSamsungAC(decode_results *results, const uint16_t nbits,
+ const bool strict) {
if (results->rawlen < 2 * nbits + kHeader * 3 + kFooter * 2 - 1)
return false; // Can't possibly be a valid Samsung A/C message.
if (nbits != kSamsungAcBits && nbits != kSamsungAcExtendedBits) return false;
uint16_t offset = kStartOffset;
- uint16_t dataBitsSoFar = 0;
- match_result_t data_result;
// Message Header
if (!matchMark(results->rawbuf[offset++], kSamsungAcBitMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kSamsungAcHdrSpace)) return false;
// Section(s)
- for (uint16_t pos = kSamsungACSectionLength, i = 0; pos <= nbits / 8;
+ for (uint16_t pos = 0; pos <= (nbits / 8) - kSamsungACSectionLength;
pos += kSamsungACSectionLength) {
- uint64_t sectiondata = 0;
- // Section Header
- if (!matchMark(results->rawbuf[offset++], kSamsungAcSectionMark))
- return false;
- if (!matchSpace(results->rawbuf[offset++], kSamsungAcSectionSpace))
- return false;
- // Section Data
- // Keep reading bytes until we either run out of section or state to fill.
- for (; offset <= results->rawlen - 16 && i < pos;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- data_result = matchData(&(results->rawbuf[offset]), 8, kSamsungAcBitMark,
- kSamsungAcOneSpace, kSamsungAcBitMark,
- kSamsungAcZeroSpace, kTolerance, 0, false);
- if (data_result.success == false) {
- DPRINT("DEBUG: offset = ");
- DPRINTLN(offset + data_result.used);
- return false; // Fail
- }
- results->state[i] = data_result.data;
- sectiondata = (sectiondata << 8) + data_result.data;
- }
- DPRINTLN("DEBUG: sectiondata = 0x" + uint64ToString(sectiondata, 16));
- // Section Footer
- if (!matchMark(results->rawbuf[offset++], kSamsungAcBitMark)) return false;
- if (pos < nbits / 8) { // Inter-section gap.
- if (!matchSpace(results->rawbuf[offset++], kSamsungAcSectionGap))
- return false;
- } else { // Last section / End of message gap.
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kSamsungAcSectionGap))
- return false;
- }
+ uint16_t used;
+ // Section Header + Section Data (7 bytes) + Section Footer
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, kSamsungACSectionLength * 8,
+ kSamsungAcSectionMark, kSamsungAcSectionSpace,
+ kSamsungAcBitMark, kSamsungAcOneSpace,
+ kSamsungAcBitMark, kSamsungAcZeroSpace,
+ kSamsungAcBitMark, kSamsungAcSectionGap,
+ pos + kSamsungACSectionLength >= nbits / 8,
+ _tolerance, 0, false);
+ if (used == 0) return false;
+ offset += used;
}
// Compliance
- // Re-check we got the correct size/length due to the way we read the data.
- if (dataBitsSoFar != nbits) return false;
// Is the signature correct?
DPRINTLN("DEBUG: Checking signature.");
if (results->state[0] != 0x02 || results->state[2] != 0x0F) return false;
@@ -770,7 +759,7 @@ bool IRrecv::decodeSamsungAC(decode_results *results, uint16_t nbits,
}
// Success
results->decode_type = SAMSUNG_AC;
- results->bits = dataBitsSoFar;
+ results->bits = nbits;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Samsung.h b/lib/IRremoteESP8266-2.6.5/src/ir_Samsung.h
similarity index 53%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Samsung.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Samsung.h
index 9df427c6f..1a2be79bb 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Samsung.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Samsung.h
@@ -9,8 +9,6 @@
#include
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -18,14 +16,14 @@
#include "IRsend_test.h"
#endif
-// SSSS AAA MMM SSSS U U N N GGGG
-// S A A M M M S U U NN N G
-// SSS AAAAA M M M SSS U U N N N G GG
-// S A A M M S U U N NN G G
-// SSSS A A M M SSSS UUU N N GGG
+// Supports:
+// Brand: Samsung, Model: UA55H6300 TV
+// Brand: Samsung, Model: IEC-R03 remote
+// Brand: Samsung, Model: AR12KSFPEWQNET A/C
+// Brand: Samsung, Model: AR12HSSDBWKNEU A/C
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/505
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/505
// Constants
const uint8_t kSamsungAcAuto = 0;
@@ -33,7 +31,7 @@ const uint8_t kSamsungAcCool = 1;
const uint8_t kSamsungAcDry = 2;
const uint8_t kSamsungAcFan = 3;
const uint8_t kSamsungAcHeat = 4;
-const uint8_t kSamsungAcModeMask = 0x70;
+const uint8_t kSamsungAcModeMask = 0x70; // 0b01110000
const uint8_t kSamsungAcFanAuto = 0;
const uint8_t kSamsungAcFanLow = 2;
const uint8_t kSamsungAcFanMed = 4;
@@ -43,17 +41,20 @@ const uint8_t kSamsungAcFanTurbo = 7;
const uint8_t kSamsungAcMinTemp = 16; // 16C
const uint8_t kSamsungAcMaxTemp = 30; // 30C
const uint8_t kSamsungAcAutoTemp = 25; // 25C
-const uint8_t kSamsungAcTempMask = 0xF0;
-const uint8_t kSamsungAcPowerMask1 = 0x20;
-const uint8_t kSamsungAcPowerMask2 = 0x30;
-const uint8_t kSamsungAcFanMask = 0x0E;
-const uint8_t kSamsungAcSwingMask = 0x70;
+const uint8_t kSamsungAcTempMask = 0xF0; // 0b11110000
+const uint8_t kSamsungAcPowerMask1 = 0x20; // 0b00100000
+const uint8_t kSamsungAcPowerMask6 = 0x30; // 0b00110000
+const uint8_t kSamsungAcFanMask = 0x0E; // 0b00001110
+const uint8_t kSamsungAcSwingMask = 0x70; // 0b01110000
const uint8_t kSamsungAcSwingMove = 0b010;
const uint8_t kSamsungAcSwingStop = 0b111;
-const uint8_t kSamsungAcBeepMask = 0x02;
-const uint8_t kSamsungAcCleanMask10 = 0x80;
-const uint8_t kSamsungAcCleanMask11 = 0x02;
-const uint8_t kSamsungAcQuietMask11 = 0x01;
+const uint8_t kSamsungAcBeepMask = 0x02; // 0b00000010
+const uint8_t kSamsungAcCleanMask10 = 0x80; // 0b10000000
+const uint8_t kSamsungAcCleanMask11 = 0x02; // 0b00000010
+const uint8_t kSamsungAcQuietMask1 = 0x10; // 0b00010000
+const uint8_t kSamsungAcQuietMask5 = 0x20; // 0b00100000
+const uint8_t kSamsungAcPowerfulMask8 = 0x50; // 0b01010000
+const uint8_t kSamsungAcPowerfulMask10 = 0x06; // 0b00000110
const uint16_t kSamsungACSectionLength = 7;
const uint64_t kSamsungAcPowerSection = 0x1D20F00000000;
@@ -61,9 +62,10 @@ const uint64_t kSamsungAcPowerSection = 0x1D20F00000000;
// Classes
class IRSamsungAc {
public:
- explicit IRSamsungAc(uint16_t pin);
+ explicit IRSamsungAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
- void stateReset();
+ void stateReset(void);
#if SEND_SAMSUNG_AC
void send(const uint16_t repeat = kSamsungAcDefaultRepeat,
const bool calcchecksum = true);
@@ -71,27 +73,30 @@ class IRSamsungAc {
const bool calcchecksum = true);
void sendOn(const uint16_t repeat = kSamsungAcDefaultRepeat);
void sendOff(const uint16_t repeat = kSamsungAcDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_SAMSUNG_AC
- void begin();
- void on();
- void off();
- void setPower(const bool state);
- bool getPower();
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
void setTemp(const uint8_t temp);
- uint8_t getTemp();
+ uint8_t getTemp(void);
void setFan(const uint8_t speed);
- uint8_t getFan();
+ uint8_t getFan(void);
void setMode(const uint8_t mode);
- uint8_t getMode();
- void setSwing(const bool state);
- bool getSwing();
- void setBeep(const bool state);
- bool getBeep();
- void setClean(const bool state);
- bool getClean();
- void setQuiet(const bool state);
- bool getQuiet();
- uint8_t* getRaw();
+ uint8_t getMode(void);
+ void setSwing(const bool on);
+ bool getSwing(void);
+ void setBeep(const bool on);
+ bool getBeep(void);
+ void setClean(const bool on);
+ bool getClean(void);
+ void setQuiet(const bool on);
+ bool getQuiet(void);
+ void setPowerful(const bool on);
+ bool getPowerful(void);
+ uint8_t* getRaw(void);
void setRaw(const uint8_t new_code[],
const uint16_t length = kSamsungAcStateLength);
static bool validChecksum(const uint8_t state[],
@@ -100,11 +105,10 @@ class IRSamsungAc {
const uint16_t length = kSamsungAcStateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -114,6 +118,7 @@ class IRSamsungAc {
#endif
// The state of the IR remote in IR code form.
uint8_t remote_state[kSamsungAcExtendedStateLength];
+ bool _sendpower; // Hack to know when we need to send a special power mesg.
void checksum(const uint16_t length = kSamsungAcStateLength);
};
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Sanyo.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Sanyo.cpp
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Sanyo.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Sanyo.cpp
index b2b4d7830..b05e76766 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Sanyo.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Sanyo.cpp
@@ -6,12 +6,6 @@
#include "IRrecv.h"
#include "IRsend.h"
-// SSSS AAA N N Y Y OOO
-// S A A NN N Y Y O O
-// SSS AAAAA N N N Y O O
-// S A A N NN Y O O
-// SSSS A A N N Y OOO
-
// Sanyo SA 8650B originally added from:
// https://github.com/shirriff/Arduino-IRremote/
// Sanyo LC7461 support originally by marcosamarinho
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.cpp
new file mode 100644
index 000000000..250248554
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.cpp
@@ -0,0 +1,557 @@
+// Copyright 2009 Ken Shirriff
+// Copyright 2017, 2019 David Conran
+
+// Sharp remote emulation
+
+#include "ir_Sharp.h"
+#include
+#ifndef ARDUINO
+#include
+#endif
+#include "IRrecv.h"
+#include "IRsend.h"
+#include "IRutils.h"
+
+// Equipment it seems compatible with:
+// * Sharp LC-52D62U
+// *
+//
+
+// Constants
+// period time = 1/38000Hz = 26.316 microseconds.
+// Ref:
+// GlobalCache's IR Control Tower data.
+// http://www.sbprojects.com/knowledge/ir/sharp.php
+const uint16_t kSharpTick = 26;
+const uint16_t kSharpBitMarkTicks = 10;
+const uint16_t kSharpBitMark = kSharpBitMarkTicks * kSharpTick;
+const uint16_t kSharpOneSpaceTicks = 70;
+const uint16_t kSharpOneSpace = kSharpOneSpaceTicks * kSharpTick;
+const uint16_t kSharpZeroSpaceTicks = 30;
+const uint16_t kSharpZeroSpace = kSharpZeroSpaceTicks * kSharpTick;
+const uint16_t kSharpGapTicks = 1677;
+const uint16_t kSharpGap = kSharpGapTicks * kSharpTick;
+// Address(5) + Command(8) + Expansion(1) + Check(1)
+const uint64_t kSharpToggleMask =
+ ((uint64_t)1 << (kSharpBits - kSharpAddressBits)) - 1;
+const uint64_t kSharpAddressMask = ((uint64_t)1 << kSharpAddressBits) - 1;
+const uint64_t kSharpCommandMask = ((uint64_t)1 << kSharpCommandBits) - 1;
+
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
+#if (SEND_SHARP || SEND_DENON)
+// Send a (raw) Sharp message
+//
+// Args:
+// data: Contents of the message to be sent.
+// nbits: Nr. of bits of data to be sent. Typically kSharpBits.
+// repeat: Nr. of additional times the message is to be sent.
+//
+// Status: BETA / Previously working fine.
+//
+// Notes:
+// This procedure handles the inversion of bits required per protocol.
+// The protocol spec says to send the LSB first, but legacy code & usage
+// has us sending the MSB first. Grrrr. Normal invocation of encodeSharp()
+// handles this for you, assuming you are using the correct/standard values.
+// e.g. sendSharpRaw(encodeSharp(address, command));
+//
+// Ref:
+// http://www.sbprojects.com/knowledge/ir/sharp.htm
+// http://lirc.sourceforge.net/remotes/sharp/GA538WJSA
+// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf
+// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp
+void IRsend::sendSharpRaw(const uint64_t data, const uint16_t nbits,
+ const uint16_t repeat) {
+ uint64_t tempdata = data;
+ for (uint16_t i = 0; i <= repeat; i++) {
+ // Protocol demands that the data be sent twice; once normally,
+ // then with all but the address bits inverted.
+ // Note: Previously this used to be performed 3 times (normal, inverted,
+ // normal), however all data points to that being incorrect.
+ for (uint8_t n = 0; n < 2; n++) {
+ sendGeneric(0, 0, // No Header
+ kSharpBitMark, kSharpOneSpace, kSharpBitMark, kSharpZeroSpace,
+ kSharpBitMark, kSharpGap, tempdata, nbits, 38, true,
+ 0, // Repeats are handled already.
+ 33);
+ // Invert the data per protocol. This is always called twice, so it's
+ // retured to original upon exiting the inner loop.
+ tempdata ^= kSharpToggleMask;
+ }
+ }
+}
+
+// Encode a (raw) Sharp message from it's components.
+//
+// Args:
+// address: The value of the address to be sent.
+// command: The value of the address to be sent. (8 bits)
+// expansion: The value of the expansion bit to use. (0 or 1, typically 1)
+// check: The value of the check bit to use. (0 or 1, typically 0)
+// MSBfirst: Flag indicating MSB first or LSB first order. (Default: false)
+// Returns:
+// An uint32_t containing the raw Sharp message for sendSharpRaw().
+//
+// Status: BETA / Should work okay.
+//
+// Notes:
+// Assumes the standard Sharp bit sizes.
+// Historically sendSharp() sends address & command in
+// MSB first order. This is actually incorrect. It should be sent in LSB
+// order. The behaviour of sendSharp() hasn't been changed to maintain
+// backward compatibility.
+//
+// Ref:
+// http://www.sbprojects.com/knowledge/ir/sharp.htm
+// http://lirc.sourceforge.net/remotes/sharp/GA538WJSA
+// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf
+uint32_t IRsend::encodeSharp(const uint16_t address, const uint16_t command,
+ const uint16_t expansion, const uint16_t check,
+ const bool MSBfirst) {
+ // Mask any unexpected bits.
+ uint16_t tempaddress = address & ((1 << kSharpAddressBits) - 1);
+ uint16_t tempcommand = command & ((1 << kSharpCommandBits) - 1);
+ uint16_t tempexpansion = expansion & 1;
+ uint16_t tempcheck = check & 1;
+
+ if (!MSBfirst) { // Correct bit order if needed.
+ tempaddress = reverseBits(tempaddress, kSharpAddressBits);
+ tempcommand = reverseBits(tempcommand, kSharpCommandBits);
+ }
+ // Concatinate all the bits.
+ return (tempaddress << (kSharpCommandBits + 2)) | (tempcommand << 2) |
+ (tempexpansion << 1) | tempcheck;
+}
+
+// Send a Sharp message
+//
+// Args:
+// address: Address value to be sent.
+// command: Command value to be sent.
+// nbits: Nr. of bits of data to be sent. Typically kSharpBits.
+// repeat: Nr. of additional times the message is to be sent.
+//
+// Status: DEPRICATED / Previously working fine.
+//
+// Notes:
+// This procedure has a non-standard invocation style compared to similar
+// sendProtocol() routines. This is due to legacy, compatibility, & historic
+// reasons. Normally the calling syntax version is like sendSharpRaw().
+// This procedure transmits the address & command in MSB first order, which is
+// incorrect. This behaviour is left as-is to maintain backward
+// compatibility with legacy code.
+// In short, you should use sendSharpRaw(), encodeSharp(), and the correct
+// values of address & command instead of using this, & the wrong values.
+//
+// Ref:
+// http://www.sbprojects.com/knowledge/ir/sharp.htm
+// http://lirc.sourceforge.net/remotes/sharp/GA538WJSA
+// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf
+void IRsend::sendSharp(const uint16_t address, uint16_t const command,
+ const uint16_t nbits, const uint16_t repeat) {
+ sendSharpRaw(encodeSharp(address, command, 1, 0, true), nbits, repeat);
+}
+#endif // (SEND_SHARP || SEND_DENON)
+
+#if (DECODE_SHARP || DECODE_DENON)
+// Decode the supplied Sharp message.
+//
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of data bits to expect. Typically kSharpBits.
+// strict: Flag indicating if we should perform strict matching.
+// expansion: Should we expect the expansion bit to be set. Default is true.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: STABLE / Working fine.
+//
+// Note:
+// This procedure returns a value suitable for use in sendSharpRaw().
+// TODO(crankyoldgit): Need to ensure capture of the inverted message as it can
+// be missed due to the interrupt timeout used to detect an end of message.
+// Several compliance checks are disabled until that is resolved.
+// Ref:
+// http://www.sbprojects.com/knowledge/ir/sharp.php
+// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf
+// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp
+bool IRrecv::decodeSharp(decode_results *results, const uint16_t nbits,
+ const bool strict, const bool expansion) {
+ if (results->rawlen < 2 * nbits + kFooter - 1)
+ return false; // Not enough entries to be a Sharp message.
+ // Compliance
+ if (strict) {
+ if (nbits != kSharpBits) return false; // Request is out of spec.
+ // DISABLED - See TODO
+#ifdef UNIT_TEST
+ // An in spec message has the data sent normally, then inverted. So we
+ // expect twice as many entries than to just get the results.
+ if (results->rawlen < 2 * (2 * nbits + kFooter)) return false;
+#endif
+ }
+
+ uint64_t data = 0;
+ uint16_t offset = kStartOffset;
+
+ // Match Data + Footer
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ 0, 0, // No Header
+ kSharpBitMark, kSharpOneSpace,
+ kSharpBitMark, kSharpZeroSpace,
+ kSharpBitMark, kSharpGap, true, 35);
+ if (!used) return false;
+ offset += used;
+ // Compliance
+ if (strict) {
+ // Check the state of the expansion bit is what we expect.
+ if ((data & 0b10) >> 1 != expansion) return false;
+ // The check bit should be cleared in a normal message.
+ if (data & 0b1) return false;
+ // DISABLED - See TODO
+#ifdef UNIT_TEST
+ // Grab the second copy of the data (i.e. inverted)
+ uint64_t second_data = 0;
+ // Match Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &second_data,
+ results->rawlen - offset, nbits,
+ 0, 0,
+ kSharpBitMark, kSharpOneSpace,
+ kSharpBitMark, kSharpZeroSpace,
+ kSharpBitMark, kSharpGap, true, 35)) return false;
+ // Check that second_data has been inverted correctly.
+ if (data != (second_data ^ kSharpToggleMask)) return false;
+#endif // UNIT_TEST
+ }
+
+ // Success
+ results->decode_type = SHARP;
+ results->bits = nbits;
+ results->value = data;
+ // Address & command are actually transmitted in LSB first order.
+ results->address = reverseBits(data, nbits) & kSharpAddressMask;
+ results->command =
+ reverseBits((data >> 2) & kSharpCommandMask, kSharpCommandBits);
+ return true;
+}
+#endif // (DECODE_SHARP || DECODE_DENON)
+
+#if SEND_SHARP_AC
+// Send a Sharp A/C message.
+//
+// Args:
+// data: An array of kSharpAcStateLength bytes containing the IR command.
+// nbytes: Nr. of bytes of data to send. i.e. length of `data`.
+// repeat: Nr. of times the message should be repeated.
+//
+// Status: Alpha / Untested.
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/638
+// https://github.com/ToniA/arduino-heatpumpir/blob/master/SharpHeatpumpIR.cpp
+void IRsend::sendSharpAc(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ if (nbytes < kSharpAcStateLength)
+ return; // Not enough bytes to send a proper message.
+
+ sendGeneric(kSharpAcHdrMark, kSharpAcHdrSpace,
+ kSharpAcBitMark, kSharpAcOneSpace,
+ kSharpAcBitMark, kSharpAcZeroSpace,
+ kSharpAcBitMark, kSharpAcGap,
+ data, nbytes, 38000, false, repeat, 50);
+}
+#endif // SEND_SHARP_AC
+
+IRSharpAc::IRSharpAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
+
+void IRSharpAc::begin(void) { _irsend.begin(); }
+
+#if SEND_SHARP_AC
+void IRSharpAc::send(const uint16_t repeat) {
+ this->checksum();
+ _irsend.sendSharpAc(remote, kSharpAcStateLength, repeat);
+}
+#endif // SEND_SHARP_AC
+
+// Calculate the checksum for a given state.
+// Args:
+// state: The array to verify the checksums of.
+// length: The size of the state.
+// Returns:
+// The 4 bit checksum.
+uint8_t IRSharpAc::calcChecksum(uint8_t state[], const uint16_t length) {
+ uint8_t xorsum = xorBytes(state, length - 1);
+ xorsum ^= (state[length - 1] & 0xF);
+ xorsum ^= xorsum >> 4;
+ return xorsum & 0xF;
+}
+
+// Verify the checksums are valid for a given state.
+// Args:
+// state: The array to verify the checksums of.
+// length: The size of the state.
+// Returns:
+// A boolean.
+bool IRSharpAc::validChecksum(uint8_t state[], const uint16_t length) {
+ return (state[length - 1] >> 4) == IRSharpAc::calcChecksum(state, length);
+}
+
+// Calculate and set the checksum values for the internal state.
+void IRSharpAc::checksum(void) {
+ remote[kSharpAcStateLength - 1] &= 0x0F;
+ remote[kSharpAcStateLength - 1] |= this->calcChecksum(remote) << 4;
+}
+
+void IRSharpAc::stateReset(void) {
+ static const uint8_t reset[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x01, 0x00, 0x00, 0x08, 0x80, 0x00, 0xE0,
+ 0x01};
+ for (uint8_t i = 0; i < kSharpAcStateLength; i++) remote[i] = reset[i];
+}
+
+uint8_t *IRSharpAc::getRaw(void) {
+ this->checksum(); // Ensure correct settings before sending.
+ return remote;
+}
+
+void IRSharpAc::setRaw(const uint8_t new_code[], const uint16_t length) {
+ for (uint8_t i = 0; i < length && i < kSharpAcStateLength; i++)
+ remote[i] = new_code[i];
+}
+
+void IRSharpAc::on(void) { remote[kSharpAcBytePower] |= kSharpAcBitPower; }
+
+void IRSharpAc::off(void) { remote[kSharpAcBytePower] &= ~kSharpAcBitPower; }
+
+void IRSharpAc::setPower(const bool on) {
+ if (on)
+ this->on();
+ else
+ this->off();
+}
+
+bool IRSharpAc::getPower(void) {
+ return remote[kSharpAcBytePower] & kSharpAcBitPower;
+}
+
+// Set the temp in deg C
+void IRSharpAc::setTemp(const uint8_t temp) {
+ switch (this->getMode()) {
+ // Auto & Dry don't allow temp changes and have a special temp.
+ case kSharpAcAuto:
+ case kSharpAcDry:
+ remote[kSharpAcByteTemp] = 0;
+ remote[kSharpAcByteManual] = 0; // When in Dry/Auto this byte is 0.
+ return;
+ default:
+ remote[kSharpAcByteTemp] = 0xC0;
+ remote[kSharpAcByteManual] |= kSharpAcBitTempManual;
+ }
+ uint8_t degrees = std::max(temp, kSharpAcMinTemp);
+ degrees = std::min(degrees, kSharpAcMaxTemp);
+ remote[kSharpAcByteTemp] &= ~kSharpAcMaskTemp;
+ remote[kSharpAcByteTemp] |= (degrees - kSharpAcMinTemp);
+}
+
+uint8_t IRSharpAc::getTemp(void) {
+ return (remote[kSharpAcByteTemp] & kSharpAcMaskTemp) + kSharpAcMinTemp;
+}
+
+uint8_t IRSharpAc::getMode(void) {
+ return remote[kSharpAcByteMode] & kSharpAcMaskMode;
+}
+
+void IRSharpAc::setMode(const uint8_t mode) {
+ const uint8_t special = 0x20; // Non-auto modes have this bit set.
+ remote[kSharpAcBytePower] |= special;
+ switch (mode) {
+ case kSharpAcAuto:
+ remote[kSharpAcBytePower] &= ~special; // Auto has this bit cleared.
+ // FALLTHRU
+ case kSharpAcDry:
+ this->setTemp(0); // Dry/Auto have no temp setting.
+ // FALLTHRU
+ case kSharpAcCool:
+ case kSharpAcHeat:
+ remote[kSharpAcByteMode] &= ~kSharpAcMaskMode;
+ remote[kSharpAcByteMode] |= mode;
+
+ break;
+ default:
+ this->setMode(kSharpAcAuto);
+ }
+}
+
+// Set the speed of the fan
+void IRSharpAc::setFan(const uint8_t speed) {
+ remote[kSharpAcByteManual] |= kSharpAcBitFanManual; // Manual fan mode.
+ switch (speed) {
+ case kSharpAcFanAuto:
+ // Clear the manual fan bit.
+ remote[kSharpAcByteManual] &= ~kSharpAcBitFanManual;
+ // FALLTHRU
+ case kSharpAcFanMin:
+ case kSharpAcFanMed:
+ case kSharpAcFanHigh:
+ case kSharpAcFanMax:
+ remote[kSharpAcByteFan] &= ~kSharpAcMaskFan;
+ remote[kSharpAcByteFan] |= (speed << 4);
+ break;
+ default:
+ this->setFan(kSharpAcFanAuto);
+ }
+}
+
+uint8_t IRSharpAc::getFan(void) {
+ return (remote[kSharpAcByteFan] & kSharpAcMaskFan) >> 4;
+}
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRSharpAc::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kSharpAcCool;
+ case stdAc::opmode_t::kHeat:
+ return kSharpAcHeat;
+ case stdAc::opmode_t::kDry:
+ return kSharpAcDry;
+ // No Fan mode.
+ default:
+ return kSharpAcAuto;
+ }
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRSharpAc::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ case stdAc::fanspeed_t::kLow:
+ return kSharpAcFanMin;
+ case stdAc::fanspeed_t::kMedium:
+ return kSharpAcFanMed;
+ case stdAc::fanspeed_t::kHigh:
+ return kSharpAcFanHigh;
+ case stdAc::fanspeed_t::kMax:
+ return kSharpAcFanMax;
+ default:
+ return kSharpAcFanAuto;
+ }
+}
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRSharpAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kSharpAcCool: return stdAc::opmode_t::kCool;
+ case kSharpAcHeat: return stdAc::opmode_t::kHeat;
+ case kSharpAcDry: return stdAc::opmode_t::kDry;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRSharpAc::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kSharpAcFanMax: return stdAc::fanspeed_t::kMax;
+ case kSharpAcFanHigh: return stdAc::fanspeed_t::kHigh;
+ case kSharpAcFanMed: return stdAc::fanspeed_t::kMedium;
+ case kSharpAcFanMin: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRSharpAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::SHARP_AC;
+ result.model = -1; // Not supported.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ // Not supported.
+ result.swingv = stdAc::swingv_t::kOff;
+ result.swingh = stdAc::swingh_t::kOff;
+ result.quiet = false;
+ result.turbo = false;
+ result.clean = false;
+ result.beep = false;
+ result.econo = false;
+ result.filter = false;
+ result.light = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRSharpAc::toString(void) {
+ String result = "";
+ result.reserve(60); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kSharpAcAuto, kSharpAcCool, kSharpAcHeat,
+ kSharpAcDry, kSharpAcAuto);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kSharpAcFanMax, kSharpAcFanMin,
+ kSharpAcFanAuto, kSharpAcFanAuto, kSharpAcFanMed);
+ return result;
+}
+
+#if DECODE_SHARP_AC
+// Decode the supplied Sharp A/C message.
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: Nr. of bits to expect in the data portion. (kSharpAcBits)
+// strict: Flag to indicate if we strictly adhere to the specification.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: BETA / Should be working.
+//
+// Ref:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/638
+// https://github.com/ToniA/arduino-heatpumpir/blob/master/SharpHeatpumpIR.cpp
+bool IRrecv::decodeSharpAc(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ // Is there enough data to match successfully?
+ if (results->rawlen < 2 * nbits + kHeader + kFooter - 1)
+ return false;
+
+ // Compliance
+ if (strict && nbits != kSharpAcBits) return false;
+
+ uint16_t offset = kStartOffset;
+ // Match Header + Data + Footer
+ uint16_t used;
+ used = matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kSharpAcHdrMark, kSharpAcHdrSpace,
+ kSharpAcBitMark, kSharpAcOneSpace,
+ kSharpAcBitMark, kSharpAcZeroSpace,
+ kSharpAcBitMark, kSharpAcGap, true,
+ _tolerance, kMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
+ // Compliance
+ if (strict) {
+ if (!IRSharpAc::validChecksum(results->state)) return false;
+ }
+
+ // Success
+ results->decode_type = SHARP_AC;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_SHARP_AC
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.h b/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.h
new file mode 100644
index 000000000..e80c7cdde
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.h
@@ -0,0 +1,98 @@
+// Copyright 2019 crankyoldgit
+
+// Supports:
+// Brand: Sharp, Model: LC-52D62U TV
+// Brand: Sharp, Model: AY-ZP40KR A/C
+
+#ifndef IR_SHARP_H_
+#define IR_SHARP_H_
+
+#ifndef UNIT_TEST
+#include
+#endif
+#include "IRrecv.h"
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#ifdef UNIT_TEST
+#include "IRsend_test.h"
+#endif
+
+// Constants
+const uint16_t kSharpAcHdrMark = 3800;
+const uint16_t kSharpAcHdrSpace = 1900;
+const uint16_t kSharpAcBitMark = 470;
+const uint16_t kSharpAcZeroSpace = 500;
+const uint16_t kSharpAcOneSpace = 1400;
+const uint32_t kSharpAcGap = kDefaultMessageGap;
+
+const uint8_t kSharpAcAuto = 0b000;
+const uint8_t kSharpAcDry = 0b011;
+const uint8_t kSharpAcCool = 0b010;
+const uint8_t kSharpAcHeat = 0b001;
+const uint8_t kSharpAcMinTemp = 15; // Celsius
+const uint8_t kSharpAcMaxTemp = 30; // Celsius
+const uint8_t kSharpAcFanAuto = 0b010; // 2
+const uint8_t kSharpAcFanMin = 0b100; // 4 (FAN1)
+const uint8_t kSharpAcFanMed = 0b011; // 3 (FAN2)
+const uint8_t kSharpAcFanHigh = 0b101; // 5 (FAN3)
+const uint8_t kSharpAcFanMax = 0b111; // 7 (FAN4)
+const uint8_t kSharpAcByteTemp = 4;
+const uint8_t kSharpAcMaskTemp = 0b00001111;
+const uint8_t kSharpAcBytePower = 5;
+const uint8_t kSharpAcBitPower = 0b00010000;
+const uint8_t kSharpAcByteMode = 6;
+const uint8_t kSharpAcMaskMode = 0b00000011;
+const uint8_t kSharpAcByteFan = kSharpAcByteMode;
+const uint8_t kSharpAcMaskFan = 0b01110000;
+const uint8_t kSharpAcByteManual = 10;
+const uint8_t kSharpAcBitFanManual = 0b00000001;
+const uint8_t kSharpAcBitTempManual = 0b00000100;
+
+
+class IRSharpAc {
+ public:
+ explicit IRSharpAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
+
+#if SEND_SHARP_AC
+ void send(const uint16_t repeat = kSharpAcDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
+#endif // SEND_SHARP_AC
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t temp);
+ uint8_t getTemp(void);
+ void setFan(const uint8_t fan);
+ uint8_t getFan(void);
+ void setMode(const uint8_t mode);
+ uint8_t getMode(void);
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t new_code[],
+ const uint16_t length = kSharpAcStateLength);
+ static bool validChecksum(uint8_t state[],
+ const uint16_t length = kSharpAcStateLength);
+ static uint8_t convertMode(const stdAc::opmode_t mode);
+ static uint8_t convertFan(const stdAc::fanspeed_t speed);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
+#ifndef UNIT_TEST
+
+ private:
+ IRsend _irsend;
+#else
+ IRsendTest _irsend;
+#endif
+ // # of bytes per command
+ uint8_t remote[kSharpAcStateLength];
+ void stateReset(void);
+ void checksum(void);
+ static uint8_t calcChecksum(uint8_t state[],
+ const uint16_t length = kSharpAcStateLength);
+};
+
+#endif // IR_SHARP_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Sherwood.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Sherwood.cpp
similarity index 66%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Sherwood.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Sherwood.cpp
index 8af7dfb34..47c6790de 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Sherwood.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Sherwood.cpp
@@ -1,14 +1,14 @@
// Copyright 2017 David Conran
+// Sherwood IR remote emulation
+
+// Supports:
+// Brand: Sherwood, Model: RC-138 remote
+// Brand: Sherwood, Model: RD6505(B) Receiver
+
#include
#include "IRsend.h"
-// SSSSS HH HH EEEEEEE RRRRRR WW WW OOOOO OOOOO DDDDD
-// SS HH HH EE RR RR WW WW OO OO OO OO DD DD
-// SSSSS HHHHHHH EEEEE RRRRRR WW W WW OO OO OO OO DD DD
-// SS HH HH EE RR RR WW WWW WW OO OO OO OO DD DD
-// SSSSS HH HH EEEEEEE RR RR WW WW OOOO0 OOOO0 DDDDDD
-
#if SEND_SHERWOOD
// Send an IR command to a Sherwood device.
//
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Sony.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Sony.cpp
similarity index 88%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Sony.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Sony.cpp
index efa6e6a46..6fc39b7b5 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Sony.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Sony.cpp
@@ -2,17 +2,13 @@
// Copyright 2016 marcosamarinho
// Copyright 2017 David Conran
+// Sony Remote Emulation
+
#include
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
-// SSSS OOO N N Y Y
-// S O O NN N Y Y
-// SSS O O N N N Y
-// S O O N NN Y
-// SSSS OOO N N Y
-
// Sony originally added from https://github.com/shirriff/Arduino-IRremote/
// Updates from marcosamarinho
@@ -123,25 +119,20 @@ bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) {
uint64_t data = 0;
uint16_t offset = kStartOffset;
uint16_t actualBits;
- uint32_t timeSoFar = 0; // Time in uSecs of the message length.
// Header
- timeSoFar += results->rawbuf[offset] * kRawTick;
if (!matchMark(results->rawbuf[offset], kSonyHdrMark)) return false;
// Calculate how long the common tick time is based on the header mark.
uint32_t tick = results->rawbuf[offset++] * kRawTick / kSonyHdrMarkTicks;
// Data
for (actualBits = 0; offset < results->rawlen - 1; actualBits++, offset++) {
- // The gap after a Sony packet for a repeat should be kSonyMinGap or
- // (kSonyRptLength - timeSoFar) according to the spec.
- if (matchSpace(results->rawbuf[offset], kSonyMinGapTicks * tick) ||
- matchAtLeast(results->rawbuf[offset], kSonyRptLength - timeSoFar))
+ // The gap after a Sony packet for a repeat should be kSonyMinGap according
+ // to the spec.
+ if (matchAtLeast(results->rawbuf[offset], kSonyMinGapTicks * tick))
break; // Found a repeat space.
- timeSoFar += results->rawbuf[offset] * kRawTick;
if (!matchSpace(results->rawbuf[offset++], kSonySpaceTicks * tick))
return false;
- timeSoFar += results->rawbuf[offset] * kRawTick;
if (matchMark(results->rawbuf[offset], kSonyOneMarkTicks * tick))
data = (data << 1) | 1;
else if (matchMark(results->rawbuf[offset], kSonyZeroMarkTicks * tick))
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Tcl.cpp
similarity index 69%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Tcl.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Tcl.cpp
index 79fb23cf1..0186f43e5 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Tcl.cpp
@@ -10,6 +10,12 @@
// Constants
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
#if SEND_TCL112AC
void IRsend::sendTcl112Ac(const unsigned char data[], const uint16_t nbytes,
@@ -22,9 +28,11 @@ void IRsend::sendTcl112Ac(const unsigned char data[], const uint16_t nbytes,
}
#endif // SEND_TCL112AC
-IRTcl112Ac::IRTcl112Ac(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRTcl112Ac::IRTcl112Ac(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { stateReset(); }
-void IRTcl112Ac::begin() { this->_irsend.begin(); }
+void IRTcl112Ac::begin(void) { this->_irsend.begin(); }
#if SEND_TCL112AC
void IRTcl112Ac::send(const uint16_t repeat) {
@@ -64,7 +72,7 @@ bool IRTcl112Ac::validChecksum(uint8_t state[], const uint16_t length) {
return (length > 1 && state[length - 1] == calcChecksum(state, length));
}
-void IRTcl112Ac::stateReset() {
+void IRTcl112Ac::stateReset(void) {
for (uint8_t i = 0; i < kTcl112AcStateLength; i++)
remote_state[i] = 0x0;
// A known good state. (On, Cool, 24C)
@@ -79,7 +87,7 @@ void IRTcl112Ac::stateReset() {
remote_state[13] = 0x03;
}
-uint8_t* IRTcl112Ac::getRaw() {
+uint8_t* IRTcl112Ac::getRaw(void) {
this->checksum();
return remote_state;
}
@@ -112,7 +120,7 @@ bool IRTcl112Ac::getPower(void) {
// Get the requested climate operation mode of the a/c unit.
// Returns:
// A uint8_t containing the A/C mode.
-uint8_t IRTcl112Ac::getMode() {
+uint8_t IRTcl112Ac::getMode(void) {
return remote_state[6] & 0xF;
}
@@ -151,7 +159,7 @@ void IRTcl112Ac::setTemp(const float celsius) {
remote_state[7] |= ((uint8_t)kTcl112AcTempMax - nrHalfDegrees / 2);
}
-float IRTcl112Ac::getTemp() {
+float IRTcl112Ac::getTemp(void) {
float result = kTcl112AcTempMax - (remote_state[7] & 0xF);
if (remote_state[12] & kTcl112AcHalfDegree) result += 0.5;
return result;
@@ -174,7 +182,7 @@ void IRTcl112Ac::setFan(const uint8_t speed) {
}
// Return the currect fan speed.
-uint8_t IRTcl112Ac::getFan() {
+uint8_t IRTcl112Ac::getFan(void) {
return remote_state[8] & kTcl112AcFanMask;
}
@@ -291,69 +299,74 @@ uint8_t IRTcl112Ac::convertFan(const stdAc::fanspeed_t speed) {
}
}
-// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRTcl112Ac::toString() {
- String result = "";
-#else
-std::string IRTcl112Ac::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- result += (this->getPower() ? F("On") : F("Off"));
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (this->getMode()) {
- case kTcl112AcAuto:
- result += F(" (AUTO)");
- break;
- case kTcl112AcCool:
- result += F(" (COOL)");
- break;
- case kTcl112AcHeat:
- result += F(" (HEAT)");
- break;
- case kTcl112AcDry:
- result += F(" (DRY)");
- break;
- case kTcl112AcFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRTcl112Ac::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kTcl112AcCool: return stdAc::opmode_t::kCool;
+ case kTcl112AcHeat: return stdAc::opmode_t::kHeat;
+ case kTcl112AcDry: return stdAc::opmode_t::kDry;
+ case kTcl112AcFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
}
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRTcl112Ac::toCommonFanSpeed(const uint8_t spd) {
+ switch (spd) {
+ case kTcl112AcFanHigh: return stdAc::fanspeed_t::kMax;
+ case kTcl112AcFanMed: return stdAc::fanspeed_t::kMedium;
+ case kTcl112AcFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRTcl112Ac::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::TCL112AC;
+ result.model = -1; // Not supported.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwingVertical() ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.swingh = this->getSwingHorizontal() ? stdAc::swingh_t::kAuto :
+ stdAc::swingh_t::kOff;
+ result.turbo = this->getTurbo();
+ result.light = this->getLight();
+ result.filter = this->getHealth();
+ result.econo = this->getEcono();
+ // Not supported.
+ result.quiet = false;
+ result.clean = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRTcl112Ac::toString(void) {
+ String result = "";
+ result.reserve(140); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kTcl112AcAuto, kTcl112AcCool,
+ kTcl112AcHeat, kTcl112AcDry, kTcl112AcFan);
uint16_t nrHalfDegrees = this->getTemp() * 2;
result += F(", Temp: ");
result += uint64ToString(nrHalfDegrees / 2);
if (nrHalfDegrees & 1) result += F(".5");
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kTcl112AcFanAuto:
- result += F(" (Auto)");
- break;
- case kTcl112AcFanLow:
- result += F(" (Low)");
- break;
- case kTcl112AcFanMed:
- result += F(" (Med)");
- break;
- case kTcl112AcFanHigh:
- result += F(" (High)");
- break;
- }
- result += F(", Econo: ");
- result += (this->getEcono() ? F("On") : F("Off"));
- result += ", Health: ";
- result += (this->getHealth() ? F("On") : F("Off"));
- result += F(", Light: ");
- result += (this->getLight() ? F("On") : F("Off"));
- result += F(", Turbo: ");
- result += (this->getTurbo() ? F("On") : F("Off"));
- result += ", Swing (H): ";
- result += (this->getSwingHorizontal() ? F("On") : F("Off"));
- result += F(", Swing (V): ");
- result += (this->getSwingVertical() ? F("On") : F("Off"));
+ result += 'C';
+ result += addFanToString(getFan(), kTcl112AcFanHigh, kTcl112AcFanLow,
+ kTcl112AcFanAuto, kTcl112AcFanAuto, kTcl112AcFanMed);
+ result += addBoolToString(getEcono(), F("Econo"));
+ result += addBoolToString(getHealth(), F("Health"));
+ result += addBoolToString(getLight(), F("Light"));
+ result += addBoolToString(getTurbo(), F("Turbo"));
+ result += addBoolToString(getSwingHorizontal(), F("Swing (H)"));
+ result += addBoolToString(getSwingVertical(), F("Swing (V)"));
return result;
}
@@ -370,48 +383,26 @@ std::string IRTcl112Ac::toString() {
// Status: BETA / Appears to mostly work.
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/619
-bool IRrecv::decodeTcl112Ac(decode_results *results, uint16_t nbits,
- bool strict) {
- if (results->rawlen < 2 * nbits + kHeader + kFooter - 1)
- return false; // Can't possibly be a valid Samsung A/C message.
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/619
+bool IRrecv::decodeTcl112Ac(decode_results *results, const uint16_t nbits,
+ const bool strict) {
if (strict && nbits != kTcl112AcBits) return false;
uint16_t offset = kStartOffset;
- uint16_t dataBitsSoFar = 0;
- match_result_t data_result;
-
- // Message Header
- if (!matchMark(results->rawbuf[offset++], kTcl112AcHdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kTcl112AcHdrSpace)) return false;
-
- // Data
- // Keep reading bytes until we either run out of section or state to fill.
- for (uint16_t i = 0; offset <= results->rawlen - 16 && i < nbits / 8;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- data_result = matchData(&(results->rawbuf[offset]), 8, kTcl112AcBitMark,
- kTcl112AcOneSpace, kTcl112AcBitMark,
- kTcl112AcZeroSpace, kTolerance, 0, false);
- if (data_result.success == false) {
- DPRINT("DEBUG: offset = ");
- DPRINTLN(offset + data_result.used);
- return false; // Fail
- }
- results->state[i] = data_result.data;
- }
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kTcl112AcBitMark)) return false;
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kTcl112AcGap)) return false;
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kTcl112AcHdrMark, kTcl112AcHdrSpace,
+ kTcl112AcBitMark, kTcl112AcOneSpace,
+ kTcl112AcBitMark, kTcl112AcZeroSpace,
+ kTcl112AcBitMark, kTcl112AcGap, true,
+ _tolerance + kTcl112AcTolerance, 0, false)) return false;
// Compliance
- // Re-check we got the correct size/length due to the way we read the data.
- if (dataBitsSoFar != nbits) return false;
// Verify we got a valid checksum.
if (strict && !IRTcl112Ac::validChecksum(results->state)) return false;
// Success
results->decode_type = TCL112AC;
- results->bits = dataBitsSoFar;
+ results->bits = nbits;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.h b/lib/IRremoteESP8266-2.6.5/src/ir_Tcl.h
similarity index 84%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Tcl.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Tcl.h
index a1595451d..1a1bc1d6b 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Tcl.h
@@ -1,15 +1,17 @@
// Copyright 2019 David Conran
+// Supports:
+// Brand: Leberg, Model: LBS-TOR07 A/C
+
#ifndef IR_TCL_H_
#define IR_TCL_H_
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
+#include "IRrecv.h"
#ifdef UNIT_TEST
#include "IRsend_test.h"
#endif
@@ -21,6 +23,7 @@ const uint16_t kTcl112AcBitMark = 500;
const uint16_t kTcl112AcOneSpace = 1050;
const uint16_t kTcl112AcZeroSpace = 325;
const uint32_t kTcl112AcGap = kDefaultMessageGap; // Just a guess.
+const uint8_t kTcl112AcTolerance = 5; // Extra Percent
const uint8_t kTcl112AcHeat = 1;
const uint8_t kTcl112AcDry = 2;
@@ -48,10 +51,12 @@ const uint8_t kTcl112AcBitTurbo = 0b01000000;
class IRTcl112Ac {
public:
- explicit IRTcl112Ac(uint16_t pin);
+ explicit IRTcl112Ac(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
#if SEND_TCL112AC
void send(const uint16_t repeat = kTcl112AcDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_TCL
void begin(void);
uint8_t* getRaw(void);
@@ -85,11 +90,10 @@ class IRTcl112Ac {
bool getTurbo(void);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -98,7 +102,7 @@ class IRTcl112Ac {
IRsendTest _irsend;
#endif
uint8_t remote_state[kTcl112AcStateLength];
- void stateReset();
+ void stateReset(void);
void checksum(const uint16_t length = kTcl112AcStateLength);
};
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Teco.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Teco.cpp
similarity index 53%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Teco.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Teco.cpp
index 779bf8f8f..9967ccee1 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Teco.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Teco.cpp
@@ -20,6 +20,13 @@ const uint16_t kTecoOneSpace = 1650;
const uint16_t kTecoZeroSpace = 580;
const uint32_t kTecoGap = kDefaultMessageGap; // Made-up value. Just a guess.
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
#if SEND_TECO
// Send a Teco A/C message.
//
@@ -27,7 +34,8 @@ const uint32_t kTecoGap = kDefaultMessageGap; // Made-up value. Just a guess.
// data: Contents of the message to be sent.
// nbits: Nr. of bits of data to be sent. Typically kTecoBits.
// repeat: Nr. of additional times the message is to be sent.
-void IRsend::sendTeco(uint64_t data, uint16_t nbits, uint16_t repeat) {
+void IRsend::sendTeco(const uint64_t data, const uint16_t nbits,
+ const uint16_t repeat) {
sendGeneric(kTecoHdrMark, kTecoHdrSpace, kTecoBitMark, kTecoOneSpace,
kTecoBitMark, kTecoZeroSpace, kTecoBitMark, kTecoGap,
data, nbits, 38000, false, repeat, kDutyDefault);
@@ -35,9 +43,11 @@ void IRsend::sendTeco(uint64_t data, uint16_t nbits, uint16_t repeat) {
#endif // SEND_TECO
// Class for decoding and constructing Teco AC messages.
-IRTecoAc::IRTecoAc(const uint16_t pin) : _irsend(pin) { stateReset(); }
+IRTecoAc::IRTecoAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
-void IRTecoAc::begin() { _irsend.begin(); }
+void IRTecoAc::begin(void) { _irsend.begin(); }
#if SEND_TECO
void IRTecoAc::send(const uint16_t repeat) {
@@ -54,19 +64,18 @@ uint64_t IRTecoAc::getRaw(void) { return remote_state; }
void IRTecoAc::setRaw(const uint64_t new_code) { remote_state = new_code; }
-void IRTecoAc::on(void) { remote_state |= kTecoPower; }
+void IRTecoAc::on(void) { setPower(true); }
-void IRTecoAc::off(void) { remote_state &= ~kTecoPower; }
+void IRTecoAc::off(void) { setPower(false); }
void IRTecoAc::setPower(const bool on) {
if (on)
- this->on();
+ remote_state |= kTecoPower;
else
- this->off();
+ remote_state &= ~kTecoPower;
}
-bool IRTecoAc::getPower(void) {
- return (remote_state & kTecoPower) == kTecoPower; }
+bool IRTecoAc::getPower(void) { return remote_state & kTecoPower; }
void IRTecoAc::setTemp(const uint8_t temp) {
uint8_t newtemp = temp;
@@ -136,6 +145,33 @@ void IRTecoAc::setSleep(const bool on) {
bool IRTecoAc::getSleep(void) { return remote_state & kTecoSleep; }
+bool IRTecoAc::getLight(void) { return remote_state & kTecoLight; }
+
+void IRTecoAc::setLight(const bool on) {
+ if (on)
+ remote_state |= kTecoLight;
+ else
+ remote_state &= ~kTecoLight;
+}
+
+bool IRTecoAc::getHumid(void) { return remote_state & kTecoHumid; }
+
+void IRTecoAc::setHumid(const bool on) {
+ if (on)
+ remote_state |= kTecoHumid;
+ else
+ remote_state &= ~kTecoHumid;
+}
+
+bool IRTecoAc::getSave(void) { return remote_state & kTecoSave; }
+
+void IRTecoAc::setSave(const bool on) {
+ if (on)
+ remote_state |= kTecoSave;
+ else
+ remote_state &= ~kTecoSave;
+}
+
// Convert a standard A/C mode into its native mode.
uint8_t IRTecoAc::convertMode(const stdAc::opmode_t mode) {
switch (mode) {
@@ -168,61 +204,69 @@ uint8_t IRTecoAc::convertFan(const stdAc::fanspeed_t speed) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRTecoAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kTecoCool: return stdAc::opmode_t::kCool;
+ case kTecoHeat: return stdAc::opmode_t::kHeat;
+ case kTecoDry: return stdAc::opmode_t::kDry;
+ case kTecoFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRTecoAc::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kTecoFanHigh: return stdAc::fanspeed_t::kMax;
+ case kTecoFanMed: return stdAc::fanspeed_t::kMedium;
+ case kTecoFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRTecoAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::TECO;
+ result.model = -1; // Not supported.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwing() ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.sleep = this->getSleep() ? 0 : -1;
+ result.light = this->getLight();
+ // Not supported.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.turbo = false;
+ result.filter = false;
+ result.econo = false;
+ result.quiet = false;
+ result.clean = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
String IRTecoAc::toString(void) {
String result = "";
-#else
-std::string IRTecoAc::toString(void) {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- result += (this->getPower() ? F("On") : F("Off"));
- result += F(", Mode: ");
- result += uint64ToString(this->getMode());
- switch (this->getMode()) {
- case kTecoAuto:
- result += F(" (AUTO)");
- break;
- case kTecoCool:
- result += F(" (COOL)");
- break;
- case kTecoHeat:
- result += F(" (HEAT)");
- break;
- case kTecoDry:
- result += F(" (DRY)");
- break;
- case kTecoFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (this->getFan()) {
- case kTecoFanAuto:
- result += F(" (Auto)");
- break;
- case kTecoFanHigh:
- result += F(" (High)");
- break;
- case kTecoFanLow:
- result += F(" (Low)");
- break;
- case kTecoFanMed:
- result += F(" (Med)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Sleep: ");
- result += (this->getSleep() ? F("On") : F("Off"));
- result += F(", Swing: ");
- result += (this->getSwing() ? F("On") : F("Off"));
+ result.reserve(100); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kTecoAuto, kTecoCool, kTecoHeat,
+ kTecoDry, kTecoFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kTecoFanHigh, kTecoFanLow,
+ kTecoFanAuto, kTecoFanAuto, kTecoFanMed);
+ result += addBoolToString(getSleep(), F("Sleep"));
+ result += addBoolToString(getSwing(), F("Swing"));
+ result += addBoolToString(getLight(), F("Light"));
+ result += addBoolToString(getHumid(), F("Humid"));
+ result += addBoolToString(getSave(), F("Save"));
+
return result;
}
@@ -237,39 +281,24 @@ std::string IRTecoAc::toString(void) {
// boolean: True if it can decode it, false if it can't.
//
// Status: STABLE / Tested.
-bool IRrecv::decodeTeco(decode_results* results, uint16_t nbits, bool strict) {
- // Check if can possibly be a valid Teco message.
- if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false;
+bool IRrecv::decodeTeco(decode_results* results,
+ const uint16_t nbits, const bool strict) {
if (strict && nbits != kTecoBits) return false; // Not what is expected
uint64_t data = 0;
uint16_t offset = kStartOffset;
- match_result_t data_result;
-
- // Header
- if (!matchMark(results->rawbuf[offset++], kTecoHdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kTecoHdrSpace)) return false;
- // Data (35 bits)
- data_result =
- matchData(&(results->rawbuf[offset]), 35, kTecoBitMark, kTecoOneSpace,
- kTecoBitMark, kTecoZeroSpace, kTolerance, kMarkExcess, false);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
- uint16_t actualBits = data_result.used / 2;
-
- // Footer.
- if (!matchMark(results->rawbuf[offset++], kTecoBitMark)) return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kTecoGap)) return false;
-
- // Compliance
- if (actualBits < nbits) return false;
- if (strict && actualBits != nbits) return false; // Not as we expected.
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kTecoHdrMark, kTecoHdrSpace,
+ kTecoBitMark, kTecoOneSpace,
+ kTecoBitMark, kTecoZeroSpace,
+ kTecoBitMark, kTecoGap, true,
+ _tolerance, kMarkExcess, false)) return false;
// Success
results->decode_type = TECO;
- results->bits = actualBits;
+ results->bits = nbits;
results->value = data;
results->address = 0;
results->command = 0;
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Teco.h b/lib/IRremoteESP8266-2.6.5/src/ir_Teco.h
similarity index 78%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Teco.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Teco.h
index 65a0050ae..616fc5dfb 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Teco.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Teco.h
@@ -5,8 +5,6 @@
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -14,6 +12,10 @@
#include "IRsend_test.h"
#endif
+// Supports:
+// Brand: Alaska, Model: SAC9010QC A/C
+// Brand: Alaska, Model: SAC9010QC remote
+
// Constants. Using LSB to be able to send only 35bits.
const uint8_t kTecoAuto = 0; // 0b000
const uint8_t kTecoCool = 1; // 0b001
@@ -37,6 +39,9 @@ const uint64_t kTecoTimerHalfH = 0b00000000000000000000001000000000000;
const uint64_t kTecoTimerTenHr = 0b00000000000000000000110000000000000;
const uint64_t kTecoTimerOn = 0b00000000000000000001000000000000000;
const uint64_t kTecoTimerUniHr = 0b00000000000000011110000000000000000;
+const uint64_t kTecoHumid = 0b00000000000000100000000000000000000;
+const uint64_t kTecoLight = 0b00000000000001000000000000000000000;
+const uint64_t kTecoSave = 0b00000000000100000000000000000000000;
const uint64_t kTecoReset = 0b01001010000000000000010000000000000;
/*
(header mark and space)
@@ -44,8 +49,12 @@ const uint64_t kTecoReset = 0b01001010000000000000010000000000000;
byte 0 = Cst 0x02
byte 1 = Cst 0x50
+ b6-7 = "AIR" 0, 1, 2 (Not Implemented)
byte 2:
- b0-3 = 0b0000
+ b0 = Save
+ b1 = "Tree with bubbles" / Filter?? (Not Implemented)
+ b2 = Light/LED.
+ b3 = Humid
b4-7 = Timer hours (unit, not thenth)
hours:
0000 (0) = +0 hour
@@ -89,7 +98,8 @@ const uint64_t kTecoReset = 0b01001010000000000000010000000000000;
// Classes
class IRTecoAc {
public:
- explicit IRTecoAc(const uint16_t pin);
+ explicit IRTecoAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
void stateReset(void);
#if SEND_TECO
@@ -111,12 +121,21 @@ class IRTecoAc {
void setMode(const uint8_t mode);
uint8_t getMode(void);
- void setSwing(const bool state);
+ void setSwing(const bool on);
bool getSwing(void);
- void setSleep(const bool state);
+ void setSleep(const bool on);
bool getSleep(void);
+ void setLight(const bool on);
+ bool getLight(void);
+
+ void setHumid(const bool on);
+ bool getHumid(void);
+
+ void setSave(const bool on);
+ bool getSave(void);
+
// void setTimer(uint8_t time); // To check unit
// uint8_t getTimer(uint8_t);
@@ -125,11 +144,10 @@ class IRTecoAc {
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
String toString(void);
-#else
- std::string toString(void);
-#endif
#ifndef UNIT_TEST
private:
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.cpp
similarity index 62%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.cpp
index a82a2fb24..4fa4c1075 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.cpp
@@ -1,5 +1,8 @@
// Copyright 2017 David Conran
+// Toshiba A/C support added by David Conran
+
+
#include "ir_Toshiba.h"
#include
#ifndef ARDUINO
@@ -9,13 +12,6 @@
#include "IRsend.h"
#include "IRutils.h"
-// TTTTTTT OOOOO SSSSS HH HH IIIII BBBBB AAA
-// TTT OO OO SS HH HH III BB B AAAAA
-// TTT OO OO SSSSS HHHHHHH III BBBBBB AA AA
-// TTT OO OO SS HH HH III BB BB AAAAAAA
-// TTT OOOO0 SSSSS HH HH IIIII BBBBBB AA AA
-
-// Toshiba A/C support added by David Conran
//
// Equipment it seems compatible with:
// * Toshiba RAS-B13N3KV2 / Akita EVO II
@@ -35,6 +31,13 @@ const uint16_t kToshibaAcOneSpace = 1623;
const uint16_t kToshibaAcZeroSpace = 472;
const uint16_t kToshibaAcMinGap = 7048;
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
#if SEND_TOSHIBA_AC
// Send a Toshiba A/C message.
//
@@ -46,8 +49,8 @@ const uint16_t kToshibaAcMinGap = 7048;
//
// Status: StABLE / Working.
//
-void IRsend::sendToshibaAC(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
+void IRsend::sendToshibaAC(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kToshibaACStateLength)
return; // Not enough bytes to send a proper message.
sendGeneric(kToshibaAcHdrMark, kToshibaAcHdrSpace, kToshibaAcBitMark,
@@ -64,10 +67,12 @@ void IRsend::sendToshibaAC(unsigned char data[], uint16_t nbytes,
// Status: STABLE / Working.
//
// Initialise the object.
-IRToshibaAC::IRToshibaAC(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRToshibaAC::IRToshibaAC(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
// Reset the state of the remote to a known good state/sequence.
-void IRToshibaAC::stateReset() {
+void IRToshibaAC::stateReset(void) {
// The state of the IR remote in IR code form.
// Known good state obtained from:
// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266T.ino#L103
@@ -81,32 +86,32 @@ void IRToshibaAC::stateReset() {
remote_state[4] = 0x01;
for (uint8_t i = 5; i < kToshibaACStateLength; i++) remote_state[i] = 0;
mode_state = remote_state[6] & 0b00000011;
- checksum(); // Calculate the checksum
+ this->checksum(); // Calculate the checksum
}
// Configure the pin for output.
-void IRToshibaAC::begin() { _irsend.begin(); }
+void IRToshibaAC::begin(void) { _irsend.begin(); }
#if SEND_TOSHIBA_AC
// Send the current desired state to the IR LED.
void IRToshibaAC::send(const uint16_t repeat) {
- checksum(); // Ensure correct checksum before sending.
+ this->checksum(); // Ensure correct checksum before sending.
_irsend.sendToshibaAC(remote_state, kToshibaACStateLength, repeat);
}
#endif // SEND_TOSHIBA_AC
// Return a pointer to the internal state date of the remote.
-uint8_t* IRToshibaAC::getRaw() {
- checksum();
+uint8_t* IRToshibaAC::getRaw(void) {
+ this->checksum();
return remote_state;
}
// Override the internal state with the new state.
-void IRToshibaAC::setRaw(uint8_t newState[]) {
+void IRToshibaAC::setRaw(const uint8_t newState[]) {
for (uint8_t i = 0; i < kToshibaACStateLength; i++) {
remote_state[i] = newState[i];
}
- mode_state = getMode(true);
+ mode_state = this->getMode(true);
}
// Calculate the checksum for a given array.
@@ -133,56 +138,59 @@ uint8_t IRToshibaAC::calcChecksum(const uint8_t state[],
// Returns:
// A boolean.
bool IRToshibaAC::validChecksum(const uint8_t state[], const uint16_t length) {
- return (length > 1 && state[length - 1] == calcChecksum(state, length));
+ return (length > 1 && state[length - 1] == IRToshibaAC::calcChecksum(state,
+ length));
}
// Calculate & set the checksum for the current internal state of the remote.
void IRToshibaAC::checksum(const uint16_t length) {
// Stored the checksum value in the last byte.
- if (length > 1) remote_state[length - 1] = calcChecksum(remote_state, length);
+ if (length > 1) remote_state[length - 1] = this->calcChecksum(remote_state,
+ length);
}
// Set the requested power state of the A/C to off.
-void IRToshibaAC::on() {
+void IRToshibaAC::on(void) {
// state = ON;
remote_state[6] &= ~kToshibaAcPower;
setMode(mode_state);
}
// Set the requested power state of the A/C to off.
-void IRToshibaAC::off() {
+void IRToshibaAC::off(void) {
// state = OFF;
remote_state[6] |= (kToshibaAcPower | 0b00000011);
}
// Set the requested power state of the A/C.
-void IRToshibaAC::setPower(bool state) {
- if (state)
- on();
+void IRToshibaAC::setPower(const bool on) {
+ if (on)
+ this->on();
else
- off();
+ this->off();
}
// Return the requested power state of the A/C.
-bool IRToshibaAC::getPower() {
+bool IRToshibaAC::getPower(void) {
return ((remote_state[6] & kToshibaAcPower) == 0);
}
// Set the temp. in deg C
-void IRToshibaAC::setTemp(uint8_t temp) {
- temp = std::max((uint8_t)kToshibaAcMinTemp, temp);
+void IRToshibaAC::setTemp(const uint8_t degrees) {
+ uint8_t temp = std::max((uint8_t)kToshibaAcMinTemp, degrees);
temp = std::min((uint8_t)kToshibaAcMaxTemp, temp);
remote_state[5] = (temp - kToshibaAcMinTemp) << 4;
}
// Return the set temp. in deg C
-uint8_t IRToshibaAC::getTemp() {
+uint8_t IRToshibaAC::getTemp(void) {
return ((remote_state[5] >> 4) + kToshibaAcMinTemp);
}
// Set the speed of the fan, 0-5.
// 0 is auto, 1-5 is the speed, 5 is Max.
-void IRToshibaAC::setFan(uint8_t fan) {
+void IRToshibaAC::setFan(const uint8_t speed) {
+ uint8_t fan = speed;
// Bounds check
if (fan > kToshibaAcFanMax)
fan = kToshibaAcFanMax; // Set the fan to maximum if out of range.
@@ -192,7 +200,7 @@ void IRToshibaAC::setFan(uint8_t fan) {
}
// Return the requested state of the unit's fan.
-uint8_t IRToshibaAC::getFan() {
+uint8_t IRToshibaAC::getFan(void) {
uint8_t fan = remote_state[6] >> 5;
if (fan == kToshibaAcFanAuto) return kToshibaAcFanAuto;
return --fan;
@@ -203,7 +211,7 @@ uint8_t IRToshibaAC::getFan() {
// useRaw: Indicate to get the mode from the state array. (Default: false)
// Returns:
// A uint8_t containing the A/C mode.
-uint8_t IRToshibaAC::getMode(bool useRaw) {
+uint8_t IRToshibaAC::getMode(const bool useRaw) {
if (useRaw)
return (remote_state[6] & 0b00000011);
else
@@ -211,25 +219,23 @@ uint8_t IRToshibaAC::getMode(bool useRaw) {
}
// Set the requested climate operation mode of the a/c unit.
-void IRToshibaAC::setMode(uint8_t mode) {
+void IRToshibaAC::setMode(const uint8_t mode) {
// If we get an unexpected mode, default to AUTO.
switch (mode) {
case kToshibaAcAuto:
- break;
case kToshibaAcCool:
- break;
case kToshibaAcDry:
- break;
case kToshibaAcHeat:
- break;
+ mode_state = mode;
+ // Only adjust the remote_state if we have power set to on.
+ if (getPower()) {
+ remote_state[6] &= 0b11111100; // Clear the previous mode.
+ remote_state[6] |= mode_state;
+ }
+ return;
default:
- mode = kToshibaAcAuto;
- }
- mode_state = mode;
- // Only adjust the remote_state if we have power set to on.
- if (getPower()) {
- remote_state[6] &= 0b11111100; // Clear the previous mode.
- remote_state[6] |= mode_state;
+ // THere is no Fan mode.
+ this->setMode(kToshibaAcAuto);
}
}
@@ -266,49 +272,64 @@ uint8_t IRToshibaAC::convertFan(const stdAc::fanspeed_t speed) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRToshibaAC::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kToshibaAcCool: return stdAc::opmode_t::kCool;
+ case kToshibaAcHeat: return stdAc::opmode_t::kHeat;
+ case kToshibaAcDry: return stdAc::opmode_t::kDry;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRToshibaAC::toCommonFanSpeed(const uint8_t spd) {
+ switch (spd) {
+ case kToshibaAcFanMax: return stdAc::fanspeed_t::kMax;
+ case kToshibaAcFanMax - 1: return stdAc::fanspeed_t::kHigh;
+ case kToshibaAcFanMax - 2: return stdAc::fanspeed_t::kMedium;
+ case kToshibaAcFanMax - 3: return stdAc::fanspeed_t::kLow;
+ case kToshibaAcFanMax - 4: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRToshibaAC::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::TOSHIBA_AC;
+ result.model = -1; // Not supported.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ // Not supported.
+ result.turbo = false;
+ result.light = false;
+ result.filter = false;
+ result.econo = false;
+ result.swingv = stdAc::swingv_t::kOff;
+ result.swingh = stdAc::swingh_t::kOff;
+ result.quiet = false;
+ result.clean = false;
+ result.beep = false;
+ result.sleep = -1;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRToshibaAC::toString() {
+String IRToshibaAC::toString(void) {
String result = "";
-#else
-std::string IRToshibaAC::toString() {
- std::string result = "";
-#endif // ARDUINO
- result += F("Power: ");
- if (getPower())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kToshibaAcAuto:
- result += F(" (AUTO)");
- break;
- case kToshibaAcCool:
- result += F(" (COOL)");
- break;
- case kToshibaAcHeat:
- result += F(" (HEAT)");
- break;
- case kToshibaAcDry:
- result += F(" (DRY)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kToshibaAcFanAuto:
- result += F(" (AUTO)");
- break;
- case kToshibaAcFanMax:
- result += F(" (MAX)");
- break;
- }
+ result.reserve(40);
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kToshibaAcAuto, kToshibaAcCool,
+ kToshibaAcHeat, kToshibaAcDry, kToshibaAcAuto);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kToshibaAcFanMax, kToshibaAcFanMin,
+ kToshibaAcFanAuto, kToshibaAcFanAuto,
+ kToshibaAcFanMed);
return result;
}
@@ -326,39 +347,22 @@ std::string IRToshibaAC::toString() {
//
// Ref:
//
-bool IRrecv::decodeToshibaAC(decode_results* results, uint16_t nbits,
- bool strict) {
+bool IRrecv::decodeToshibaAC(decode_results* results, const uint16_t nbits,
+ const bool strict) {
uint16_t offset = kStartOffset;
- uint16_t dataBitsSoFar = 0;
-
- // Have we got enough data to successfully decode?
- if (results->rawlen < kToshibaACBits + kHeader + kFooter - 1)
- return false; // Can't possibly be a valid message.
// Compliance
if (strict && nbits != kToshibaACBits)
return false; // Must be called with the correct nr. of bytes.
- // Header
- if (!matchMark(results->rawbuf[offset++], kToshibaAcHdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kToshibaAcHdrSpace)) return false;
-
- // Data
- for (uint8_t i = 0; i < kToshibaACStateLength; i++) {
- // Read a byte's worth of data.
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), 8, kToshibaAcBitMark,
- kToshibaAcOneSpace, kToshibaAcBitMark, kToshibaAcZeroSpace);
- if (data_result.success == false) return false; // Fail
- dataBitsSoFar += 8;
- results->state[i] = (uint8_t)data_result.data;
- offset += data_result.used;
- }
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kToshibaAcBitMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kToshibaAcMinGap)) return false;
-
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kToshibaAcHdrMark, kToshibaAcHdrSpace,
+ kToshibaAcBitMark, kToshibaAcOneSpace,
+ kToshibaAcBitMark, kToshibaAcZeroSpace,
+ kToshibaAcBitMark, kToshibaAcMinGap, true,
+ _tolerance, kMarkExcess)) return false;
// Compliance
if (strict) {
// Check that the checksum of the message is correct.
@@ -367,7 +371,7 @@ bool IRrecv::decodeToshibaAC(decode_results* results, uint16_t nbits,
// Success
results->decode_type = TOSHIBA_AC;
- results->bits = dataBitsSoFar;
+ results->bits = nbits;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.h b/lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.h
similarity index 62%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.h
index 03b461add..6b06855bf 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.h
@@ -1,4 +1,15 @@
// Copyright 2017 David Conran
+
+// Toshiba A/C support added by David Conran
+
+// Supports:
+// Brand: Toshiba, Model: RAS-B13N3KV2
+// Brand: Toshiba, Model: Akita EVO II
+// Brand: Toshiba, Model: RAS-B13N3KVP-E
+// Brand: Toshiba, Model: RAS 18SKP-ES
+// Brand: Toshiba, Model: WH-TA04NE
+// Brand: Toshiba, Model: WC-L03SE
+
#ifndef IR_TOSHIBA_H_
#define IR_TOSHIBA_H_
@@ -6,8 +17,6 @@
#include
#ifdef ARDUINO
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -15,14 +24,6 @@
#include "IRsend_test.h"
#endif
-// TTTTTTT OOOOO SSSSS HH HH IIIII BBBBB AAA
-// TTT OO OO SS HH HH III BB B AAAAA
-// TTT OO OO SSSSS HHHHHHH III BBBBBB AA AA
-// TTT OO OO SS HH HH III BB BB AAAAAAA
-// TTT OOOO0 SSSSS HH HH IIIII BBBBBB AA AA
-
-// Toshiba A/C support added by David Conran
-
// Constants
const uint8_t kToshibaAcAuto = 0;
const uint8_t kToshibaAcCool = 1;
@@ -30,6 +31,8 @@ const uint8_t kToshibaAcDry = 2;
const uint8_t kToshibaAcHeat = 3;
const uint8_t kToshibaAcPower = 4;
const uint8_t kToshibaAcFanAuto = 0;
+const uint8_t kToshibaAcFanMin = 1;
+const uint8_t kToshibaAcFanMed = 3;
const uint8_t kToshibaAcFanMax = 5;
const uint8_t kToshibaAcMinTemp = 17; // 17C
const uint8_t kToshibaAcMaxTemp = 30; // 30C
@@ -47,34 +50,35 @@ const uint8_t kToshibaAcMaxTemp = 30; // 30C
class IRToshibaAC {
public:
- explicit IRToshibaAC(uint16_t pin);
+ explicit IRToshibaAC(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
- void stateReset();
+ void stateReset(void);
#if SEND_TOSHIBA_AC
void send(const uint16_t repeat = kToshibaACMinRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_TOSHIBA_AC
- void begin();
- void on();
- void off();
- void setPower(bool state);
- bool getPower();
- void setTemp(uint8_t temp);
- uint8_t getTemp();
- void setFan(uint8_t fan);
- uint8_t getFan();
- void setMode(uint8_t mode);
- uint8_t getMode(bool useRaw = false);
- void setRaw(uint8_t newState[]);
- uint8_t* getRaw();
+ void begin(void);
+ void on(void);
+ void off(void);
+ void setPower(const bool on);
+ bool getPower(void);
+ void setTemp(const uint8_t degrees);
+ uint8_t getTemp(void);
+ void setFan(const uint8_t speed);
+ uint8_t getFan(void);
+ void setMode(const uint8_t mode);
+ uint8_t getMode(const bool useRaw = false);
+ void setRaw(const uint8_t newState[]);
+ uint8_t* getRaw(void);
static bool validChecksum(const uint8_t state[],
const uint16_t length = kToshibaACStateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Trotec.cpp
new file mode 100644
index 000000000..281779f62
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Trotec.cpp
@@ -0,0 +1,296 @@
+// Copyright 2017 stufisher
+// Copyright 2019 crankyoldgit
+
+#include "ir_Trotec.h"
+#include
+#ifndef UNIT_TEST
+#include
+#endif
+#include "IRremoteESP8266.h"
+#include "IRutils.h"
+
+// Constants
+const uint16_t kTrotecHdrMark = 5952;
+const uint16_t kTrotecHdrSpace = 7364;
+const uint16_t kTrotecBitMark = 592;
+const uint16_t kTrotecOneSpace = 1560;
+const uint16_t kTrotecZeroSpace = 592;
+const uint16_t kTrotecGap = 6184;
+const uint16_t kTrotecGapEnd = 1500; // made up value
+
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+
+#if SEND_TROTEC
+
+void IRsend::sendTrotec(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
+ if (nbytes < kTrotecStateLength) return;
+
+ for (uint16_t r = 0; r <= repeat; r++) {
+ sendGeneric(kTrotecHdrMark, kTrotecHdrSpace, kTrotecBitMark,
+ kTrotecOneSpace, kTrotecBitMark, kTrotecZeroSpace,
+ kTrotecBitMark, kTrotecGap, data, nbytes, 36, false,
+ 0, // Repeats handled elsewhere
+ 50);
+ // More footer
+ enableIROut(36);
+ mark(kTrotecBitMark);
+ space(kTrotecGapEnd);
+ }
+}
+#endif // SEND_TROTEC
+
+IRTrotecESP::IRTrotecESP(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
+
+void IRTrotecESP::begin(void) { _irsend.begin(); }
+
+#if SEND_TROTEC
+void IRTrotecESP::send(const uint16_t repeat) {
+ this->checksum();
+ _irsend.sendTrotec(remote_state, kTrotecStateLength, repeat);
+}
+#endif // SEND_TROTEC
+
+uint8_t IRTrotecESP::calcChecksum(const uint8_t state[],
+ const uint16_t length) {
+ return sumBytes(state + 2, length - 3);
+}
+
+bool IRTrotecESP::validChecksum(const uint8_t state[], const uint16_t length) {
+ return state[length - 1] == calcChecksum(state, length);
+}
+
+void IRTrotecESP::checksum(void) {
+ remote_state[kTrotecStateLength - 1] = sumBytes(remote_state + 2,
+ kTrotecStateLength - 3);
+}
+
+void IRTrotecESP::stateReset(void) {
+ for (uint8_t i = 2; i < kTrotecStateLength; i++) remote_state[i] = 0x0;
+
+ remote_state[0] = kTrotecIntro1;
+ remote_state[1] = kTrotecIntro2;
+
+ this->setPower(false);
+ this->setTemp(kTrotecDefTemp);
+ this->setSpeed(kTrotecFanMed);
+ this->setMode(kTrotecAuto);
+}
+
+uint8_t* IRTrotecESP::getRaw(void) {
+ this->checksum();
+ return remote_state;
+}
+
+void IRTrotecESP::setRaw(const uint8_t state[]) {
+ for (uint16_t i = 0; i < kTrotecStateLength; i++) remote_state[i] = state[i];
+}
+
+void IRTrotecESP::setPower(const bool on) {
+ if (on)
+ remote_state[2] |= kTrotecPowerBit;
+ else
+ remote_state[2] &= ~kTrotecPowerBit;
+}
+
+bool IRTrotecESP::getPower(void) { return remote_state[2] & kTrotecPowerBit; }
+
+void IRTrotecESP::setSpeed(const uint8_t fan) {
+ uint8_t speed = std::min(fan, kTrotecFanHigh);
+ remote_state[2] = (remote_state[2] & 0b11001111) | (speed << 4);
+}
+
+uint8_t IRTrotecESP::getSpeed(void) {
+ return (remote_state[2] & 0b00110000) >> 4;
+}
+
+void IRTrotecESP::setMode(const uint8_t mode) {
+ switch (mode) {
+ case kTrotecAuto:
+ case kTrotecCool:
+ case kTrotecDry:
+ case kTrotecFan:
+ remote_state[2] = (remote_state[2] & 0b11111100) | mode;
+ return;
+ default:
+ this->setMode(kTrotecAuto);
+ }
+}
+
+uint8_t IRTrotecESP::getMode(void) { return remote_state[2] & 0b00000011; }
+
+void IRTrotecESP::setTemp(const uint8_t celsius) {
+ uint8_t temp = std::max(celsius, kTrotecMinTemp);
+ temp = std::min(temp, kTrotecMaxTemp);
+ remote_state[3] = (remote_state[3] & 0x80) | (temp - kTrotecMinTemp);
+}
+
+uint8_t IRTrotecESP::getTemp(void) {
+ return (remote_state[3] & 0b01111111) + kTrotecMinTemp;
+}
+
+void IRTrotecESP::setSleep(const bool on) {
+ if (on)
+ remote_state[3] |= kTrotecSleepBit;
+ else
+ remote_state[3] &= ~kTrotecSleepBit;
+}
+
+bool IRTrotecESP::getSleep(void) { return remote_state[3] & kTrotecSleepBit; }
+
+void IRTrotecESP::setTimer(const uint8_t timer) {
+ if (timer)
+ remote_state[5] |= kTrotecTimerBit;
+ else
+ remote_state[5] &= ~kTrotecTimerBit;
+ remote_state[6] = (timer > kTrotecMaxTimer) ? kTrotecMaxTimer : timer;
+}
+
+uint8_t IRTrotecESP::getTimer(void) { return remote_state[6]; }
+
+// Convert a standard A/C mode into its native mode.
+uint8_t IRTrotecESP::convertMode(const stdAc::opmode_t mode) {
+ switch (mode) {
+ case stdAc::opmode_t::kCool:
+ return kTrotecCool;
+ case stdAc::opmode_t::kDry:
+ return kTrotecDry;
+ case stdAc::opmode_t::kFan:
+ return kTrotecFan;
+ // Note: No Heat mode.
+ default:
+ return kTrotecAuto;
+ }
+}
+
+// Convert a standard A/C Fan speed into its native fan speed.
+uint8_t IRTrotecESP::convertFan(const stdAc::fanspeed_t speed) {
+ switch (speed) {
+ case stdAc::fanspeed_t::kMin:
+ case stdAc::fanspeed_t::kLow:
+ return kTrotecFanLow;
+ case stdAc::fanspeed_t::kMedium:
+ return kTrotecFanMed;
+ case stdAc::fanspeed_t::kHigh:
+ case stdAc::fanspeed_t::kMax:
+ return kTrotecFanHigh;
+ default:
+ return kTrotecFanMed;
+ }
+}
+
+
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRTrotecESP::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kTrotecCool: return stdAc::opmode_t::kCool;
+ case kTrotecDry: return stdAc::opmode_t::kDry;
+ case kTrotecFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRTrotecESP::toCommonFanSpeed(const uint8_t spd) {
+ switch (spd) {
+ case kTrotecFanHigh: return stdAc::fanspeed_t::kMax;
+ case kTrotecFanMed: return stdAc::fanspeed_t::kMedium;
+ case kTrotecFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRTrotecESP::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::TROTEC;
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getSpeed());
+ result.sleep = this->getSleep() ? 0 : -1;
+ // Not supported.
+ result.model = -1; // Not supported.
+ result.swingv = stdAc::swingv_t::kOff;
+ result.swingh = stdAc::swingh_t::kOff;
+ result.turbo = false;
+ result.light = false;
+ result.filter = false;
+ result.econo = false;
+ result.quiet = false;
+ result.clean = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
+// Convert the internal state into a human readable string.
+String IRTrotecESP::toString(void) {
+ String result = "";
+ result.reserve(100); // Reserve some heap for the string to reduce fragging.
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kTrotecAuto, kTrotecCool, kTrotecAuto,
+ kTrotecDry, kTrotecFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getSpeed(), kTrotecFanHigh, kTrotecFanLow,
+ kTrotecFanHigh, kTrotecFanHigh, kTrotecFanMed);
+ result += addBoolToString(getSleep(), F("Sleep"));
+ return result;
+}
+
+#if DECODE_TROTEC
+// Decode the supplied Trotec message.
+//
+// Args:
+// results: Ptr to the data to decode and where to store the decode result.
+// nbits: The number of data bits to expect. Typically kTrotecBits.
+// strict: Flag indicating if we should perform strict matching.
+// Returns:
+// boolean: True if it can decode it, false if it can't.
+//
+// Status: BETA / Probably works. Untested on real devices.
+//
+// Ref:
+bool IRrecv::decodeTrotec(decode_results *results, const uint16_t nbits,
+ const bool strict) {
+ if (results->rawlen < 2 * nbits + kHeader + 2 * kFooter - 1)
+ return false; // Can't possibly be a valid Samsung A/C message.
+ if (strict && nbits != kTrotecBits) return false;
+
+ uint16_t offset = kStartOffset;
+ uint16_t used;
+ // Header + Data + Footer #1
+ used = matchGeneric(results->rawbuf + offset, results->state,
+ results->rawlen - offset, nbits,
+ kTrotecHdrMark, kTrotecHdrSpace,
+ kTrotecBitMark, kTrotecOneSpace,
+ kTrotecBitMark, kTrotecZeroSpace,
+ kTrotecBitMark, kTrotecGap, true,
+ _tolerance, 0, false);
+ if (used == 0) return false;
+ offset += used;
+
+ // Footer #2
+ if (!matchMark(results->rawbuf[offset++], kTrotecBitMark)) return false;
+ if (offset <= results->rawlen &&
+ !matchAtLeast(results->rawbuf[offset++], kTrotecGapEnd)) return false;
+ // Compliance
+ // Verify we got a valid checksum.
+ if (strict && !IRTrotecESP::validChecksum(results->state)) return false;
+ // Success
+ results->decode_type = TROTEC;
+ results->bits = nbits;
+ // No need to record the state as we stored it as we decoded it.
+ // As we use result->state, we don't record value, address, or command as it
+ // is a union data type.
+ return true;
+}
+#endif // DECODE_TROTEC
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.h b/lib/IRremoteESP8266-2.6.5/src/ir_Trotec.h
similarity index 63%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Trotec.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Trotec.h
index dfbc26c07..98bf3795c 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Trotec.h
@@ -1,8 +1,12 @@
// Copyright 2017 stufisher
+// Copyright 2019 crankyoldgit
#ifndef IR_TROTEC_H_
#define IR_TROTEC_H_
+#ifndef UNIT_TEST
+#include
+#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
#ifdef UNIT_TEST
@@ -55,35 +59,43 @@ const uint8_t kTrotecMaxTimer = 23;
class IRTrotecESP {
public:
- explicit IRTrotecESP(uint16_t pin);
+ explicit IRTrotecESP(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
#if SEND_TROTEC
void send(const uint16_t repeat = kTrotecDefaultRepeat);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_TROTEC
- void begin();
+ void begin(void);
void setPower(const bool state);
- bool getPower();
+ bool getPower(void);
void setTemp(const uint8_t celsius);
- uint8_t getTemp();
+ uint8_t getTemp(void);
void setSpeed(const uint8_t fan);
- uint8_t getSpeed();
+ uint8_t getSpeed(void);
- uint8_t getMode();
+ uint8_t getMode(void);
void setMode(const uint8_t mode);
- bool getSleep();
- void setSleep(bool sleep);
+ bool getSleep(void);
+ void setSleep(const bool on);
- uint8_t getTimer();
+ uint8_t getTimer(void);
void setTimer(const uint8_t timer);
- uint8_t* getRaw();
-
+ uint8_t* getRaw(void);
+ void setRaw(const uint8_t state[]);
+ static bool validChecksum(const uint8_t state[],
+ const uint16_t length = kTrotecStateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -92,8 +104,10 @@ class IRTrotecESP {
IRsendTest _irsend;
#endif
uint8_t remote_state[kTrotecStateLength];
- void stateReset();
- void checksum();
+ static uint8_t calcChecksum(const uint8_t state[],
+ const uint16_t length = kTrotecStateLength);
+ void stateReset(void);
+ void checksum(void);
};
#endif // IR_TROTEC_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Vestel.cpp
similarity index 71%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Vestel.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Vestel.cpp
index 1fbb822cf..1374c6b59 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Vestel.cpp
@@ -1,12 +1,12 @@
// Copyright 2018 Erdem U. Altinyurt
// Copyright 2019 David Conran
+// Vestel added by Erdem U. Altinyurt
+
#include "ir_Vestel.h"
#include
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRrecv.h"
#include "IRremoteESP8266.h"
@@ -14,14 +14,6 @@
#include "IRutils.h"
#include "ir_Haier.h"
-// VV VV EEEEEEE SSSSS TTTTTTTT EEEEEEE LL
-// VV VV EE S TT EE LL
-// VV VV EEEEE SSSS TT EEEEE LL
-// VV VV EE S TT EE LL
-// VVV EEEEEEE SSSSS TT EEEEEEE LLLLLLL
-
-// Vestel added by Erdem U. Altinyurt
-
// Equipment it seems compatible with:
// * Vestel AC Model BIOX CXP-9 (9K BTU)
// *
@@ -29,6 +21,13 @@
// Ref:
// None. Totally reverse engineered.
+using irutils::addBoolToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+using irutils::minsToString;
+
#if SEND_VESTEL_AC
// Send a Vestel message
//
@@ -53,10 +52,12 @@ void IRsend::sendVestelAc(const uint64_t data, const uint16_t nbits,
// Code to emulate Vestel A/C IR remote control unit.
// Initialise the object.
-IRVestelAc::IRVestelAc(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRVestelAc::IRVestelAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
// Reset the state of the remote to a known good state/sequence.
-void IRVestelAc::stateReset() {
+void IRVestelAc::stateReset(void) {
// Power On, Mode Auto, Fan Auto, Temp = 25C/77F
remote_state = kVestelAcStateDefault;
remote_time_state = kVestelAcTimeStateDefault;
@@ -64,14 +65,14 @@ void IRVestelAc::stateReset() {
}
// Configure the pin for output.
-void IRVestelAc::begin() {
+void IRVestelAc::begin(void) {
_irsend.begin();
}
#if SEND_VESTEL_AC
// Send the current desired state to the IR LED.
-void IRVestelAc::send() {
- checksum(); // Ensure correct checksum before sending.
+void IRVestelAc::send(void) {
+ this->checksum(); // Ensure correct checksum before sending.
uint64_t code_to_send;
if (use_time_state)
code_to_send = remote_time_state;
@@ -82,14 +83,14 @@ void IRVestelAc::send() {
#endif // SEND_VESTEL_AC
// Return the internal state date of the remote.
-uint64_t IRVestelAc::getRaw() {
- checksum();
+uint64_t IRVestelAc::getRaw(void) {
+ this->checksum();
if (use_time_state) return remote_time_state;
return remote_state;
}
// Override the internal state with the new state.
-void IRVestelAc::setRaw(uint8_t* newState) {
+void IRVestelAc::setRaw(const uint8_t* newState) {
uint64_t upState = 0;
for (int i = 0; i < 7; i++)
upState |= static_cast(newState[i]) << (i * 8);
@@ -109,15 +110,15 @@ void IRVestelAc::setRaw(const uint64_t newState) {
}
// Set the requested power state of the A/C to on.
-void IRVestelAc::on() { setPower(true); }
+void IRVestelAc::on(void) { setPower(true); }
// Set the requested power state of the A/C to off.
-void IRVestelAc::off() { setPower(false); }
+void IRVestelAc::off(void) { setPower(false); }
// Set the requested power state of the A/C.
-void IRVestelAc::setPower(const bool state) {
+void IRVestelAc::setPower(const bool on) {
remote_state &= ~((uint64_t)0xF << kVestelAcPowerOffset);
- if (state)
+ if (on)
remote_state |= ((uint64_t)0xF << kVestelAcPowerOffset);
else
remote_state |= ((uint64_t)0xC << kVestelAcPowerOffset);
@@ -125,7 +126,7 @@ void IRVestelAc::setPower(const bool state) {
}
// Return the requested power state of the A/C.
-bool IRVestelAc::getPower() {
+bool IRVestelAc::getPower(void) {
return (remote_state >> kVestelAcPowerOffset == 0xF);
}
@@ -165,14 +166,14 @@ void IRVestelAc::setFan(const uint8_t fan) {
}
// Return the requested state of the unit's fan.
-uint8_t IRVestelAc::getFan() {
+uint8_t IRVestelAc::getFan(void) {
return (remote_state >> kVestelAcFanOffset) & 0xF;
}
// Get the requested climate operation mode of the a/c unit.
// Returns:
// A uint8_t containing the A/C mode.
-uint8_t IRVestelAc::getMode() {
+uint8_t IRVestelAc::getMode(void) {
return (remote_state >> kVestelAcModeOffset) & 0xF;
}
@@ -313,53 +314,54 @@ uint16_t IRVestelAc::getOffTimer(void) {
}
// Set the Sleep state of the A/C.
-void IRVestelAc::setSleep(const bool state) {
+void IRVestelAc::setSleep(const bool on) {
remote_state &= ~((uint64_t)0xF << kVestelAcTurboSleepOffset);
- remote_state |= (uint64_t)(state ? kVestelAcSleep : kVestelAcNormal)
+ remote_state |= (uint64_t)(on ? kVestelAcSleep : kVestelAcNormal)
<< kVestelAcTurboSleepOffset;
use_time_state = false;
}
// Return the Sleep state of the A/C.
-bool IRVestelAc::getSleep() {
+bool IRVestelAc::getSleep(void) {
return ((remote_state >> kVestelAcTurboSleepOffset) & 0xF) == kVestelAcSleep;
}
// Set the Turbo state of the A/C.
-void IRVestelAc::setTurbo(const bool state) {
+void IRVestelAc::setTurbo(const bool on) {
remote_state &= ~((uint64_t)0xF << kVestelAcTurboSleepOffset);
- remote_state |= (uint64_t)(state ? kVestelAcTurbo : kVestelAcNormal)
+ remote_state |= (uint64_t)(on ? kVestelAcTurbo : kVestelAcNormal)
<< kVestelAcTurboSleepOffset;
use_time_state = false;
}
// Return the Turbo state of the A/C.
-bool IRVestelAc::getTurbo() {
+bool IRVestelAc::getTurbo(void) {
return ((remote_state >> kVestelAcTurboSleepOffset) & 0xF) == kVestelAcTurbo;
}
// Set the Ion state of the A/C.
-void IRVestelAc::setIon(const bool state) {
+void IRVestelAc::setIon(const bool on) {
remote_state &= ~((uint64_t)0x1 << kVestelAcIonOffset);
- remote_state |= (uint64_t)(state ? 1 : 0) << kVestelAcIonOffset;
+ remote_state |= (uint64_t)(on ? 1 : 0) << kVestelAcIonOffset;
use_time_state = false;
}
// Return the Ion state of the A/C.
-bool IRVestelAc::getIon() { return (remote_state >> kVestelAcIonOffset) & 1; }
+bool IRVestelAc::getIon(void) {
+ return (remote_state >> kVestelAcIonOffset) & 1;
+}
// Set the Swing Roaming state of the A/C.
-void IRVestelAc::setSwing(const bool state) {
+void IRVestelAc::setSwing(const bool on) {
remote_state &= ~((uint64_t)0xF << kVestelAcSwingOffset);
- remote_state |= (uint64_t)(state ? kVestelAcSwing : 0xF)
- << kVestelAcSwingOffset;
+ remote_state |= (uint64_t)(on ? kVestelAcSwing : 0xF) << kVestelAcSwingOffset;
use_time_state = false;
}
// Return the Swing Roaming state of the A/C.
-bool IRVestelAc::getSwing() {
+bool IRVestelAc::getSwing(void) {
return ((remote_state >> kVestelAcSwingOffset) & 0xF) == kVestelAcSwing;
}
@@ -385,22 +387,23 @@ uint8_t IRVestelAc::calcChecksum(const uint64_t state) {
// Returns:
// A boolean.
bool IRVestelAc::validChecksum(const uint64_t state) {
- return (((state >> kVestelAcChecksumOffset) & 0xFF) == calcChecksum(state));
+ return (((state >> kVestelAcChecksumOffset) & 0xFF) ==
+ IRVestelAc::calcChecksum(state));
}
// Calculate & set the checksum for the current internal state of the remote.
-void IRVestelAc::checksum() {
+void IRVestelAc::checksum(void) {
// Stored the checksum value in the last byte.
remote_state &= ~((uint64_t)0xFF << kVestelAcChecksumOffset);
- remote_state |= (uint64_t)calcChecksum(remote_state)
+ remote_state |= (uint64_t)this->calcChecksum(remote_state)
<< kVestelAcChecksumOffset;
remote_time_state &= ~((uint64_t)0xFF << kVestelAcChecksumOffset);
- remote_time_state |= (uint64_t)calcChecksum(remote_time_state)
+ remote_time_state |= (uint64_t)this->calcChecksum(remote_time_state)
<< kVestelAcChecksumOffset;
}
-bool IRVestelAc::isTimeCommand() {
+bool IRVestelAc::isTimeCommand(void) {
return (remote_state >> kVestelAcPowerOffset == 0x00 || use_time_state);
}
@@ -437,89 +440,103 @@ uint8_t IRVestelAc::convertFan(const stdAc::fanspeed_t speed) {
}
}
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRVestelAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kVestelAcCool: return stdAc::opmode_t::kCool;
+ case kVestelAcHeat: return stdAc::opmode_t::kHeat;
+ case kVestelAcDry: return stdAc::opmode_t::kDry;
+ case kVestelAcFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRVestelAc::toCommonFanSpeed(const uint8_t spd) {
+ switch (spd) {
+ case kVestelAcFanHigh: return stdAc::fanspeed_t::kMax;
+ case kVestelAcFanMed: return stdAc::fanspeed_t::kMedium;
+ case kVestelAcFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRVestelAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::VESTEL_AC;
+ result.model = -1; // Not supported.
+ result.power = this->getPower();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwing() ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.turbo = this->getTurbo();
+ result.filter = this->getIon();
+ result.sleep = this->getSleep() ? 0 : -1;
+ // Not supported.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.light = false;
+ result.econo = false;
+ result.quiet = false;
+ result.clean = false;
+ result.beep = false;
+ result.clock = -1;
+ return result;
+}
+
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRVestelAc::toString() {
+String IRVestelAc::toString(void) {
String result = "";
-#else
-std::string IRVestelAc::toString() {
- std::string result = "";
-#endif // ARDUINO
- if (isTimeCommand()) {
- result += F("Time: ");
- result += IRHaierAC::timeToString(getTime());
-
- result += F(", Timer: ");
- result += isTimerActive() ? IRHaierAC::timeToString(getTimer()) : F("Off");
-
- result += F(", On Timer: ");
- result += (isOnTimerActive() && !isTimerActive())
- ? IRHaierAC::timeToString(getOnTimer())
- : F("Off");
-
- result += F(", Off Timer: ");
- result +=
- isOffTimerActive() ? IRHaierAC::timeToString(getOffTimer()) : F("Off");
+ result.reserve(100); // Reserve some heap for the string to reduce fragging.
+ if (this->isTimeCommand()) {
+ result += addLabeledString(minsToString(getTime()), F("Time"), false);
+ result += addLabeledString(
+ isTimerActive() ? minsToString(getTimer()) : F("Off"),
+ F("Timer"));
+ result += addLabeledString(
+ (isOnTimerActive() && !isTimerActive()) ?
+ minsToString(this->getOnTimer()) : F("Off"),
+ F("On Timer"));
+ result += addLabeledString(
+ isOffTimerActive() ? minsToString(getOffTimer()) : F("Off"),
+ F("Off Timer"));
return result;
}
// Not a time command, it's a normal command.
- result += F("Power: ");
- result += (getPower() ? F("On") : F("Off"));
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kVestelAcAuto:
- result += F(" (AUTO)");
- break;
- case kVestelAcCool:
- result += F(" (COOL)");
- break;
- case kVestelAcHeat:
- result += F(" (HEAT)");
- break;
- case kVestelAcDry:
- result += F(" (DRY)");
- break;
- case kVestelAcFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
+ result += addBoolToString(getPower(), F("Power"), false);
+ result += addModeToString(getMode(), kVestelAcAuto, kVestelAcCool,
+ kVestelAcHeat, kVestelAcDry, kVestelAcFan);
+ result += addTempToString(getTemp());
+ result += addIntToString(getFan(), F("Fan"));
+ switch (this->getFan()) {
case kVestelAcFanAuto:
- result += F(" (AUTO)");
+ result += F(" (Auto)");
break;
case kVestelAcFanLow:
- result += F(" (LOW)");
+ result += F(" (Low)");
break;
case kVestelAcFanMed:
- result += F(" (MEDIUM)");
+ result += F(" (Medium)");
break;
case kVestelAcFanHigh:
- result += F(" (HIGH)");
+ result += F(" (High)");
break;
case kVestelAcFanAutoCool:
- result += F(" (AUTO COOL)");
+ result += F(" (Auto Cool)");
break;
case kVestelAcFanAutoHot:
- result += F(" (AUTO HOT)");
+ result += F(" (Auto Hot)");
break;
default:
result += F(" (UNKNOWN)");
}
- result += F(", Sleep: ");
- result += (getSleep() ? F("On") : F("Off"));
- result += F(", Turbo: ");
- result += (getTurbo() ? F("On") : F("Off"));
- result += F(", Ion: ");
- result += (getIon() ? F("On") : F("Off"));
- result += F(", Swing: ");
- result += (getSwing() ? F("On") : F("Off"));
+ result += addBoolToString(getSleep(), F("Sleep"));
+ result += addBoolToString(getTurbo(), F("Turbo"));
+ result += addBoolToString(getIon(), F("Ion"));
+ result += addBoolToString(getSwing(), F("Swing"));
return result;
}
@@ -535,8 +552,8 @@ std::string IRVestelAc::toString() {
//
// Status: Alpha / Needs testing against a real device.
//
-bool IRrecv::decodeVestelAc(decode_results* results, uint16_t nbits,
- bool strict) {
+bool IRrecv::decodeVestelAc(decode_results* results, const uint16_t nbits,
+ const bool strict) {
if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte.
return false;
@@ -550,26 +567,17 @@ bool IRrecv::decodeVestelAc(decode_results* results, uint16_t nbits,
if (nbits > sizeof(data) * 8)
return false; // We can't possibly capture a Vestel packet that big.
- // Header
- if (!matchMark(results->rawbuf[offset++], kVestelAcHdrMark)) return false;
- if (!matchSpace(results->rawbuf[offset++], kVestelAcHdrSpace)) return false;
-
- // Data (Normal)
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits, kVestelAcBitMark,
- kVestelAcOneSpace, kVestelAcBitMark, kVestelAcZeroSpace,
- kVestelAcTolerance, kMarkExcess, false);
-
- if (data_result.success == false) return false;
- offset += data_result.used;
- data = data_result.data;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kVestelAcBitMark)) return false;
-
+ // Match Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kVestelAcHdrMark, kVestelAcHdrSpace,
+ kVestelAcBitMark, kVestelAcOneSpace,
+ kVestelAcBitMark, kVestelAcZeroSpace,
+ kVestelAcBitMark, 0, false,
+ kVestelAcTolerance, kMarkExcess, false)) return false;
// Compliance
if (strict)
- if (!IRVestelAc::validChecksum(data_result.data)) return false;
+ if (!IRVestelAc::validChecksum(data)) return false;
// Success
results->decode_type = VESTEL_AC;
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.h b/lib/IRremoteESP8266-2.6.5/src/ir_Vestel.h
similarity index 83%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Vestel.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Vestel.h
index ab04e8b35..f60c031aa 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Vestel.h
@@ -1,6 +1,9 @@
// Copyright 2018 Erdem U. Altinyurt
// Copyright 2019 David Conran
+// Supports:
+// Brand: Vestel, Model: BIOX CXP-9 A/C (9K BTU)
+
#ifndef IR_VESTEL_H_
#define IR_VESTEL_H_
@@ -8,8 +11,6 @@
#include
#ifdef ARDUINO
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -17,12 +18,6 @@
#include "IRsend_test.h"
#endif
-// VV VV EEEEEEE SSSSS TTTTTTTT EEEEEEE LL
-// VV VV EE S TT EE LL
-// VV VV EEEEE SSSS TT EEEEE LL
-// VV VV EE S TT EE LL
-// VVV EEEEEEE SSSSS TT EEEEEEE LLLLLLL
-
// Vestel added by Erdem U. Altinyurt
// Structure of a Command message (56 bits)
@@ -31,7 +26,7 @@
// Swing: 4 bits. (auto 0xA, stop 0xF)
// turbo_sleep_normal: 4bits. (normal 0x1, sleep 0x3, turbo 0x7)
// Unused: 8 bits. (0x00)
-// Temperature: 4 bits. (Celcius, but offset by -16 degrees. e.g. 0x0 = 16C)
+// Temperature: 4 bits. (Celsius, but offset by -16 degrees. e.g. 0x0 = 16C)
// Fan Speed: 4 bits (auto 0x1, low 0x5, mid 0x9, high 0xB, 0xD auto hot,
// 0xC auto cool)
// Mode: 3 bits. (auto 0x0, cold 0x1, dry 0x2, fan 0x3, hot 0x4)
@@ -108,17 +103,19 @@ const uint64_t kVestelAcTimeStateDefault = 0x201ULL;
class IRVestelAc {
public:
- explicit IRVestelAc(uint16_t pin);
+ explicit IRVestelAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
- void stateReset();
+ void stateReset(void);
#if SEND_VESTEL_AC
- void send();
+ void send(void);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_VESTEL_AC
void begin(void);
void on(void);
void off(void);
- void setPower(const bool state);
- bool getPower();
+ void setPower(const bool on);
+ bool getPower(void);
void setAuto(const int8_t autoLevel);
void setTimer(const uint16_t minutes);
uint16_t getTimer(void);
@@ -134,17 +131,17 @@ class IRVestelAc {
uint8_t getFan(void);
void setMode(const uint8_t mode);
uint8_t getMode(void);
- void setRaw(uint8_t* newState);
+ void setRaw(const uint8_t* newState);
void setRaw(const uint64_t newState);
uint64_t getRaw(void);
static bool validChecksum(const uint64_t state);
- void setSwing(const bool state);
+ void setSwing(const bool on);
bool getSwing(void);
- void setSleep(const bool state);
+ void setSleep(const bool on);
bool getSleep(void);
- void setTurbo(const bool state);
+ void setTurbo(const bool on);
bool getTurbo(void);
- void setIon(const bool state);
+ void setIon(const bool on);
bool getIon(void);
bool isTimeCommand(void);
bool isOnTimerActive(void);
@@ -154,13 +151,12 @@ class IRVestelAc {
bool isTimerActive(void);
void setTimerActive(const bool on);
static uint8_t calcChecksum(const uint64_t state);
- uint8_t convertMode(const stdAc::opmode_t mode);
- uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static uint8_t convertMode(const stdAc::opmode_t mode);
+ static uint8_t convertFan(const stdAc::fanspeed_t speed);
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -171,7 +167,7 @@ class IRVestelAc {
uint64_t remote_state;
uint64_t remote_time_state;
bool use_time_state;
- void checksum();
+ void checksum(void);
};
#endif // IR_VESTEL_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.cpp
similarity index 62%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.cpp
index 048c1a1eb..92a9b2bb3 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.cpp
@@ -24,14 +24,8 @@
#include "IRsend.h"
#include "IRutils.h"
-// WW WW HH HH IIIII RRRRRR LL PPPPPP OOOOO OOOOO LL
-// WW WW HH HH III RR RR LL PP PP OO OO OO OO LL
-// WW W WW HHHHHHH III RRRRRR LL PPPPPP OO OO OO OO LL
-// WW WWW WW HH HH III RR RR LL PP OO OO OO OO LL
-// WW WW HH HH IIIII RR RR LLLLLLL PP OOOO0 OOOO0 LLLLLLL
-
// Constants
-// Ref: https://github.com/markszabo/IRremoteESP8266/issues/509
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/509
const uint16_t kWhirlpoolAcHdrMark = 8950;
const uint16_t kWhirlpoolAcHdrSpace = 4484;
const uint16_t kWhirlpoolAcBitMark = 597;
@@ -41,6 +35,14 @@ const uint16_t kWhirlpoolAcGap = 7920;
const uint32_t kWhirlpoolAcMinGap = kDefaultMessageGap; // Just a guess.
const uint8_t kWhirlpoolAcSections = 3;
+using irutils::addBoolToString;
+using irutils::addFanToString;
+using irutils::addIntToString;
+using irutils::addLabeledString;
+using irutils::addModeToString;
+using irutils::addTempToString;
+using irutils::minsToString;
+
#if SEND_WHIRLPOOL_AC
// Send a Whirlpool A/C message.
//
@@ -52,9 +54,9 @@ const uint8_t kWhirlpoolAcSections = 3;
// Status: ALPHA / Untested.
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/509
-void IRsend::sendWhirlpoolAC(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/509
+void IRsend::sendWhirlpoolAC(const unsigned char data[], const uint16_t nbytes,
+ const uint16_t repeat) {
if (nbytes < kWhirlpoolAcStateLength)
return; // Not enough bytes to send a proper message.
for (uint16_t r = 0; r <= repeat; r++) {
@@ -85,17 +87,19 @@ void IRsend::sendWhirlpoolAC(unsigned char data[], uint16_t nbytes,
// Decoding help from:
// @redmusicxd, @josh929800, @raducostea
-IRWhirlpoolAc::IRWhirlpoolAc(uint16_t pin) : _irsend(pin) { stateReset(); }
+IRWhirlpoolAc::IRWhirlpoolAc(const uint16_t pin, const bool inverted,
+ const bool use_modulation)
+ : _irsend(pin, inverted, use_modulation) { this->stateReset(); }
-void IRWhirlpoolAc::stateReset() {
+void IRWhirlpoolAc::stateReset(void) {
for (uint8_t i = 2; i < kWhirlpoolAcStateLength; i++) remote_state[i] = 0x0;
remote_state[0] = 0x83;
remote_state[1] = 0x06;
remote_state[6] = 0x80;
- _setTemp(kWhirlpoolAcAutoTemp); // Default to a sane value.
+ this->_setTemp(kWhirlpoolAcAutoTemp); // Default to a sane value.
}
-void IRWhirlpoolAc::begin() { _irsend.begin(); }
+void IRWhirlpoolAc::begin(void) { _irsend.begin(); }
bool IRWhirlpoolAc::validChecksum(uint8_t state[], const uint16_t length) {
if (length > kWhirlpoolAcChecksumByte1 &&
@@ -128,13 +132,13 @@ void IRWhirlpoolAc::checksum(uint16_t length) {
#if SEND_WHIRLPOOL_AC
void IRWhirlpoolAc::send(const uint16_t repeat, const bool calcchecksum) {
- if (calcchecksum) checksum();
+ if (calcchecksum) this->checksum();
_irsend.sendWhirlpoolAC(remote_state, kWhirlpoolAcStateLength, repeat);
}
#endif // SEND_WHIRLPOOL_AC
uint8_t *IRWhirlpoolAc::getRaw(const bool calcchecksum) {
- if (calcchecksum) checksum();
+ if (calcchecksum) this->checksum();
return remote_state;
}
@@ -143,7 +147,7 @@ void IRWhirlpoolAc::setRaw(const uint8_t new_code[], const uint16_t length) {
remote_state[i] = new_code[i];
}
-whirlpool_ac_remote_model_t IRWhirlpoolAc::getModel() {
+whirlpool_ac_remote_model_t IRWhirlpoolAc::getModel(void) {
if (remote_state[kWhirlpoolAcAltTempPos] & kWhirlpoolAcAltTempMask)
return DG11J191;
else
@@ -160,13 +164,13 @@ void IRWhirlpoolAc::setModel(const whirlpool_ac_remote_model_t model) {
default:
remote_state[kWhirlpoolAcAltTempPos] &= ~kWhirlpoolAcAltTempMask;
}
- _setTemp(_desiredtemp); // Different models have different temp values.
+ this->_setTemp(_desiredtemp); // Different models have different temp values.
}
// Return the temp. offset in deg C for the current model.
-int8_t IRWhirlpoolAc::getTempOffset() {
- switch (getModel()) {
- case DG11J191:
+int8_t IRWhirlpoolAc::getTempOffset(void) {
+ switch (this->getModel()) {
+ case whirlpool_ac_remote_model_t::DG11J191:
return -2;
break;
default:
@@ -177,7 +181,7 @@ int8_t IRWhirlpoolAc::getTempOffset() {
// Set the temp. in deg C
void IRWhirlpoolAc::_setTemp(const uint8_t temp, const bool remember) {
if (remember) _desiredtemp = temp;
- int8_t offset = getTempOffset(); // Cache the min temp for the model.
+ int8_t offset = this->getTempOffset(); // Cache the min temp for the model.
uint8_t newtemp = std::max((uint8_t)(kWhirlpoolAcMinTemp + offset), temp);
newtemp = std::min((uint8_t)(kWhirlpoolAcMaxTemp + offset), newtemp);
remote_state[kWhirlpoolAcTempPos] =
@@ -187,23 +191,23 @@ void IRWhirlpoolAc::_setTemp(const uint8_t temp, const bool remember) {
// Set the temp. in deg C
void IRWhirlpoolAc::setTemp(const uint8_t temp) {
- _setTemp(temp);
- setSuper(false); // Changing temp cancels Super/Jet mode.
- setCommand(kWhirlpoolAcCommandTemp);
+ this->_setTemp(temp);
+ this->setSuper(false); // Changing temp cancels Super/Jet mode.
+ this->setCommand(kWhirlpoolAcCommandTemp);
}
// Return the set temp. in deg C
-uint8_t IRWhirlpoolAc::getTemp() {
+uint8_t IRWhirlpoolAc::getTemp(void) {
return ((remote_state[kWhirlpoolAcTempPos] & kWhirlpoolAcTempMask) >> 4) +
- + kWhirlpoolAcMinTemp + getTempOffset();
+ + kWhirlpoolAcMinTemp + this->getTempOffset();
}
void IRWhirlpoolAc::_setMode(const uint8_t mode) {
switch (mode) {
case kWhirlpoolAcAuto:
- setFan(kWhirlpoolAcFanAuto);
- _setTemp(kWhirlpoolAcAutoTemp, false);
- setSleep(false); // Cancel sleep mode when in auto/6thsense mode.
+ this->setFan(kWhirlpoolAcFanAuto);
+ this->_setTemp(kWhirlpoolAcAutoTemp, false);
+ this->setSleep(false); // Cancel sleep mode when in auto/6thsense mode.
// FALL THRU
case kWhirlpoolAcHeat:
case kWhirlpoolAcCool:
@@ -211,20 +215,20 @@ void IRWhirlpoolAc::_setMode(const uint8_t mode) {
case kWhirlpoolAcFan:
remote_state[kWhirlpoolAcModePos] &= ~kWhirlpoolAcModeMask;
remote_state[kWhirlpoolAcModePos] |= mode;
- setCommand(kWhirlpoolAcCommandMode);
+ this->setCommand(kWhirlpoolAcCommandMode);
break;
default:
return;
}
- if (mode == kWhirlpoolAcAuto) setCommand(kWhirlpoolAcCommand6thSense);
+ if (mode == kWhirlpoolAcAuto) this->setCommand(kWhirlpoolAcCommand6thSense);
}
void IRWhirlpoolAc::setMode(const uint8_t mode) {
- setSuper(false); // Changing mode cancels Super/Jet mode.
- _setMode(mode);
+ this->setSuper(false); // Changing mode cancels Super/Jet mode.
+ this->_setMode(mode);
}
-uint8_t IRWhirlpoolAc::getMode() {
+uint8_t IRWhirlpoolAc::getMode(void) {
return remote_state[kWhirlpoolAcModePos] & kWhirlpoolAcModeMask;
}
@@ -236,13 +240,13 @@ void IRWhirlpoolAc::setFan(const uint8_t speed) {
case kWhirlpoolAcFanHigh:
remote_state[kWhirlpoolAcFanPos] =
(remote_state[kWhirlpoolAcFanPos] & ~kWhirlpoolAcFanMask) | speed;
- setSuper(false); // Changing fan speed cancels Super/Jet mode.
- setCommand(kWhirlpoolAcCommandFanSpeed);
+ this->setSuper(false); // Changing fan speed cancels Super/Jet mode.
+ this->setCommand(kWhirlpoolAcCommandFanSpeed);
break;
}
}
-uint8_t IRWhirlpoolAc::getFan() {
+uint8_t IRWhirlpoolAc::getFan(void) {
return remote_state[kWhirlpoolAcFanPos] & kWhirlpoolAcFanMask;
}
@@ -257,7 +261,7 @@ void IRWhirlpoolAc::setSwing(const bool on) {
setCommand(kWhirlpoolAcCommandSwing);
}
-bool IRWhirlpoolAc::getSwing() {
+bool IRWhirlpoolAc::getSwing(void) {
return (remote_state[kWhirlpoolAcFanPos] & kWhirlpoolAcSwing1Mask) &&
(remote_state[kWhirlpoolAcOffTimerPos] & kWhirlpoolAcSwing2Mask);
}
@@ -269,7 +273,7 @@ void IRWhirlpoolAc::setLight(const bool on) {
remote_state[kWhirlpoolAcClockPos] |= kWhirlpoolAcLightMask;
}
-bool IRWhirlpoolAc::getLight() {
+bool IRWhirlpoolAc::getLight(void) {
return !(remote_state[kWhirlpoolAcClockPos] & kWhirlpoolAcLightMask);
}
@@ -292,49 +296,53 @@ bool IRWhirlpoolAc::isTimerEnabled(const uint16_t pos) {
return remote_state[pos - 1] & kWhirlpoolAcTimerEnableMask;
}
-void IRWhirlpoolAc::enableTimer(const uint16_t pos, const bool state) {
- if (state)
+void IRWhirlpoolAc::enableTimer(const uint16_t pos, const bool on) {
+ if (on)
remote_state[pos - 1] |= kWhirlpoolAcTimerEnableMask;
else
remote_state[pos - 1] &= ~kWhirlpoolAcTimerEnableMask;
}
void IRWhirlpoolAc::setClock(const uint16_t minspastmidnight) {
- setTime(kWhirlpoolAcClockPos, minspastmidnight);
+ this->setTime(kWhirlpoolAcClockPos, minspastmidnight);
}
-uint16_t IRWhirlpoolAc::getClock() { return getTime(kWhirlpoolAcClockPos); }
+uint16_t IRWhirlpoolAc::getClock(void) {
+ return this->getTime(kWhirlpoolAcClockPos);
+}
void IRWhirlpoolAc::setOffTimer(const uint16_t minspastmidnight) {
- setTime(kWhirlpoolAcOffTimerPos, minspastmidnight);
+ this->setTime(kWhirlpoolAcOffTimerPos, minspastmidnight);
}
-uint16_t IRWhirlpoolAc::getOffTimer() {
- return getTime(kWhirlpoolAcOffTimerPos);
+uint16_t IRWhirlpoolAc::getOffTimer(void) {
+ return this->getTime(kWhirlpoolAcOffTimerPos);
}
-bool IRWhirlpoolAc::isOffTimerEnabled() {
- return isTimerEnabled(kWhirlpoolAcOffTimerPos);
+bool IRWhirlpoolAc::isOffTimerEnabled(void) {
+ return this->isTimerEnabled(kWhirlpoolAcOffTimerPos);
}
-void IRWhirlpoolAc::enableOffTimer(const bool state) {
- enableTimer(kWhirlpoolAcOffTimerPos, state);
- setCommand(kWhirlpoolAcCommandOffTimer);
+void IRWhirlpoolAc::enableOffTimer(const bool on) {
+ this->enableTimer(kWhirlpoolAcOffTimerPos, on);
+ this->setCommand(kWhirlpoolAcCommandOffTimer);
}
void IRWhirlpoolAc::setOnTimer(const uint16_t minspastmidnight) {
- setTime(kWhirlpoolAcOnTimerPos, minspastmidnight);
+ this->setTime(kWhirlpoolAcOnTimerPos, minspastmidnight);
}
-uint16_t IRWhirlpoolAc::getOnTimer() { return getTime(kWhirlpoolAcOnTimerPos); }
-
-bool IRWhirlpoolAc::isOnTimerEnabled() {
- return isTimerEnabled(kWhirlpoolAcOnTimerPos);
+uint16_t IRWhirlpoolAc::getOnTimer(void) {
+ return this->getTime(kWhirlpoolAcOnTimerPos);
}
-void IRWhirlpoolAc::enableOnTimer(const bool state) {
- enableTimer(kWhirlpoolAcOnTimerPos, state);
- setCommand(kWhirlpoolAcCommandOnTimer);
+bool IRWhirlpoolAc::isOnTimerEnabled(void) {
+ return this->isTimerEnabled(kWhirlpoolAcOnTimerPos);
+}
+
+void IRWhirlpoolAc::enableOnTimer(const bool on) {
+ this->enableTimer(kWhirlpoolAcOnTimerPos, on);
+ this->setCommand(kWhirlpoolAcCommandOnTimer);
}
void IRWhirlpoolAc::setPowerToggle(const bool on) {
@@ -342,54 +350,54 @@ void IRWhirlpoolAc::setPowerToggle(const bool on) {
remote_state[kWhirlpoolAcPowerTogglePos] |= kWhirlpoolAcPowerToggleMask;
else
remote_state[kWhirlpoolAcPowerTogglePos] &= ~kWhirlpoolAcPowerToggleMask;
- setSuper(false); // Changing power cancels Super/Jet mode.
- setCommand(kWhirlpoolAcCommandPower);
+ this->setSuper(false); // Changing power cancels Super/Jet mode.
+ this->setCommand(kWhirlpoolAcCommandPower);
}
-bool IRWhirlpoolAc::getPowerToggle() {
+bool IRWhirlpoolAc::getPowerToggle(void) {
return remote_state[kWhirlpoolAcPowerTogglePos] & kWhirlpoolAcPowerToggleMask;
}
-uint8_t IRWhirlpoolAc::getCommand() {
+uint8_t IRWhirlpoolAc::getCommand(void) {
return remote_state[kWhirlpoolAcCommandPos];
}
void IRWhirlpoolAc::setSleep(const bool on) {
if (on) {
remote_state[kWhirlpoolAcSleepPos] |= kWhirlpoolAcSleepMask;
- setFan(kWhirlpoolAcFanLow);
+ this->setFan(kWhirlpoolAcFanLow);
} else {
remote_state[kWhirlpoolAcSleepPos] &= ~kWhirlpoolAcSleepMask;
}
- setCommand(kWhirlpoolAcCommandSleep);
+ this->setCommand(kWhirlpoolAcCommandSleep);
}
-bool IRWhirlpoolAc::getSleep() {
+bool IRWhirlpoolAc::getSleep(void) {
return remote_state[kWhirlpoolAcSleepPos] & kWhirlpoolAcSleepMask;
}
// AKA Jet/Turbo mode.
void IRWhirlpoolAc::setSuper(const bool on) {
if (on) {
- setFan(kWhirlpoolAcFanHigh);
- switch (getMode()) {
+ this->setFan(kWhirlpoolAcFanHigh);
+ switch (this->getMode()) {
case kWhirlpoolAcHeat:
- setTemp(kWhirlpoolAcMaxTemp + getTempOffset());
+ this->setTemp(kWhirlpoolAcMaxTemp + this->getTempOffset());
break;
case kWhirlpoolAcCool:
default:
- setTemp(kWhirlpoolAcMinTemp + getTempOffset());
- setMode(kWhirlpoolAcCool);
+ this->setTemp(kWhirlpoolAcMinTemp + this->getTempOffset());
+ this->setMode(kWhirlpoolAcCool);
break;
}
remote_state[kWhirlpoolAcSuperPos] |= kWhirlpoolAcSuperMask;
} else {
remote_state[kWhirlpoolAcSuperPos] &= ~kWhirlpoolAcSuperMask;
}
- setCommand(kWhirlpoolAcCommandSuper);
+ this->setCommand(kWhirlpoolAcCommandSuper);
}
-bool IRWhirlpoolAc::getSuper() {
+bool IRWhirlpoolAc::getSuper(void) {
return remote_state[kWhirlpoolAcSuperPos] & kWhirlpoolAcSuperMask;
}
@@ -429,34 +437,60 @@ uint8_t IRWhirlpoolAc::convertFan(const stdAc::fanspeed_t speed) {
}
}
-#ifdef ARDUINO
-String IRWhirlpoolAc::timeToString(const uint16_t minspastmidnight) {
- String result = "";
-#else
-std::string IRWhirlpoolAc::timeToString(const uint16_t minspastmidnight) {
- std::string result = "";
-#endif // ARDUINO
- uint8_t hours = minspastmidnight / 60;
- if (hours < 10) result += '0';
- result += uint64ToString(hours);
- result += ':';
- uint8_t mins = minspastmidnight % 60;
- if (mins < 10) result += '0';
- result += uint64ToString(mins);
+// Convert a native mode to it's common equivalent.
+stdAc::opmode_t IRWhirlpoolAc::toCommonMode(const uint8_t mode) {
+ switch (mode) {
+ case kWhirlpoolAcCool: return stdAc::opmode_t::kCool;
+ case kWhirlpoolAcHeat: return stdAc::opmode_t::kHeat;
+ case kWhirlpoolAcDry: return stdAc::opmode_t::kDry;
+ case kWhirlpoolAcFan: return stdAc::opmode_t::kFan;
+ default: return stdAc::opmode_t::kAuto;
+ }
+}
+
+// Convert a native fan speed to it's common equivalent.
+stdAc::fanspeed_t IRWhirlpoolAc::toCommonFanSpeed(const uint8_t speed) {
+ switch (speed) {
+ case kWhirlpoolAcFanHigh: return stdAc::fanspeed_t::kMax;
+ case kWhirlpoolAcFanMedium: return stdAc::fanspeed_t::kMedium;
+ case kWhirlpoolAcFanLow: return stdAc::fanspeed_t::kMin;
+ default: return stdAc::fanspeed_t::kAuto;
+ }
+}
+
+// Convert the A/C state to it's common equivalent.
+stdAc::state_t IRWhirlpoolAc::toCommon(void) {
+ stdAc::state_t result;
+ result.protocol = decode_type_t::WHIRLPOOL_AC;
+ result.model = this->getModel();
+ result.power = this->getPowerToggle();
+ result.mode = this->toCommonMode(this->getMode());
+ result.celsius = true;
+ result.degrees = this->getTemp();
+ result.fanspeed = this->toCommonFanSpeed(this->getFan());
+ result.swingv = this->getSwing() ? stdAc::swingv_t::kAuto :
+ stdAc::swingv_t::kOff;
+ result.turbo = this->getSuper();
+ result.light = this->getLight();
+ result.sleep = this->getSleep() ? 0 : -1;
+ // Not supported.
+ result.swingh = stdAc::swingh_t::kOff;
+ result.quiet = false;
+ result.filter = false;
+ result.econo = false;
+ result.clean = false;
+ result.beep = false;
+ result.clock = -1;
return result;
}
// Convert the internal state into a human readable string.
-#ifdef ARDUINO
-String IRWhirlpoolAc::toString() {
+String IRWhirlpoolAc::toString(void) {
String result = "";
-#else
-std::string IRWhirlpoolAc::toString() {
- std::string result = "";
-#endif // ARDUINO
+ result.reserve(200); // Reserve some heap for the string to reduce fragging.
result += F("Model: ");
- result += uint64ToString(getModel());
- switch (getModel()) {
+ result += uint64ToString(this->getModel());
+ switch (this->getModel()) {
case DG11J191:
result += F(" (DG11J191)");
break;
@@ -466,88 +500,26 @@ std::string IRWhirlpoolAc::toString() {
default:
result += F(" (UNKNOWN)");
}
- result += F(", Power toggle: ");
- if (getPowerToggle())
- result += F("On");
- else
- result += F("Off");
- result += F(", Mode: ");
- result += uint64ToString(getMode());
- switch (getMode()) {
- case kWhirlpoolAcHeat:
- result += F(" (HEAT)");
- break;
- case kWhirlpoolAcAuto:
- result += F(" (AUTO)");
- break;
- case kWhirlpoolAcCool:
- result += F(" (COOL)");
- break;
- case kWhirlpoolAcDry:
- result += F(" (DRY)");
- break;
- case kWhirlpoolAcFan:
- result += F(" (FAN)");
- break;
- default:
- result += F(" (UNKNOWN)");
- }
- result += F(", Temp: ");
- result += uint64ToString(getTemp());
- result += F("C, Fan: ");
- result += uint64ToString(getFan());
- switch (getFan()) {
- case kWhirlpoolAcFanAuto:
- result += F(" (AUTO)");
- break;
- case kWhirlpoolAcFanHigh:
- result += F(" (HIGH)");
- break;
- case kWhirlpoolAcFanMedium:
- result += F(" (MEDIUM)");
- break;
- case kWhirlpoolAcFanLow:
- result += F(" (LOW)");
- break;
- default:
- result += F(" (UNKNOWN)");
- break;
- }
- result += F(", Swing: ");
- if (getSwing())
- result += F("On");
- else
- result += F("Off");
- result += F(", Light: ");
- if (getLight())
- result += F("On");
- else
- result += F("Off");
- result += F(", Clock: ");
- result += timeToString(getClock());
- result += F(", On Timer: ");
- if (isOnTimerEnabled())
- result += timeToString(getOnTimer());
- else
- result += F("Off");
- result += F(", Off Timer: ");
- if (isOffTimerEnabled())
- result += timeToString(getOffTimer());
- else
- result += F("Off");
- result += F(", Sleep: ");
- if (getSleep())
- result += F("On");
- else
- result += F("Off");
- result += F(", Super: ");
- if (getSuper())
- result += F("On");
- else
- result += F("Off");
- result += F(", Command: ");
- result += uint64ToString(getCommand());
- switch (getCommand()) {
+ result += addBoolToString(getPowerToggle(), F("Power toggle"));
+ result += addModeToString(getMode(), kWhirlpoolAcAuto, kWhirlpoolAcCool,
+ kWhirlpoolAcHeat, kWhirlpoolAcDry, kWhirlpoolAcFan);
+ result += addTempToString(getTemp());
+ result += addFanToString(getFan(), kWhirlpoolAcFanHigh, kWhirlpoolAcFanLow,
+ kWhirlpoolAcFanAuto, kWhirlpoolAcFanAuto,
+ kWhirlpoolAcFanMedium);
+ result += addBoolToString(getSwing(), F("Swing"));
+ result += addBoolToString(getLight(), F("Light"));
+ result += addLabeledString(minsToString(getClock()), F("Clock"));
+ result += addLabeledString(
+ isOnTimerEnabled() ? minsToString(getOnTimer()) : F("Off"),
+ F("On Timer"));
+ result += addLabeledString(
+ isOffTimerEnabled() ? minsToString(getOffTimer()) : F("Off"),
+ F("Off Timer"));
+ result += addBoolToString(getSleep(), F("Sleep"));
+ result += addBoolToString(getSuper(), F("Super"));
+ result += addIntToString(getCommand(), F("Command"));
+ switch (this->getCommand()) {
case kWhirlpoolAcCommandLight:
result += F(" (LIGHT)");
break;
@@ -605,9 +577,9 @@ std::string IRWhirlpoolAc::toString() {
//
//
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/509
-bool IRrecv::decodeWhirlpoolAC(decode_results *results, uint16_t nbits,
- bool strict) {
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/509
+bool IRrecv::decodeWhirlpoolAC(decode_results *results, const uint16_t nbits,
+ const bool strict) {
if (results->rawlen < 2 * nbits + 4 + kHeader + kFooter - 1)
return false; // Can't possibly be a valid Whirlpool A/C message.
if (strict) {
@@ -615,9 +587,6 @@ bool IRrecv::decodeWhirlpoolAC(decode_results *results, uint16_t nbits,
}
uint16_t offset = kStartOffset;
- uint16_t dataBitsSoFar = 0;
- uint16_t i = 0;
- match_result_t data_result;
uint8_t sectionSize[kWhirlpoolAcSections] = {6, 8, 7};
// Header
@@ -625,44 +594,36 @@ bool IRrecv::decodeWhirlpoolAC(decode_results *results, uint16_t nbits,
if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcHdrSpace))
return false;
- // Data Section
- // Keep reading bytes until we either run out of section or state to fill.
- for (uint8_t section = 0, pos = 0; section < kWhirlpoolAcSections;
+ // Data Sections
+ uint16_t pos = 0;
+ for (uint8_t section = 0; section < kWhirlpoolAcSections;
section++) {
+ uint16_t used;
+ // Section Data
+ used = matchGeneric(results->rawbuf + offset, results->state + pos,
+ results->rawlen - offset, sectionSize[section] * 8,
+ 0, 0,
+ kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace,
+ kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace,
+ kWhirlpoolAcBitMark, kWhirlpoolAcGap,
+ section >= kWhirlpoolAcSections - 1,
+ _tolerance, kMarkExcess, false);
+ if (used == 0) return false;
+ offset += used;
pos += sectionSize[section];
- for (; offset <= results->rawlen - 16 && i < pos;
- i++, dataBitsSoFar += 8, offset += data_result.used) {
- data_result =
- matchData(&(results->rawbuf[offset]), 8, kWhirlpoolAcBitMark,
- kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark,
- kWhirlpoolAcZeroSpace, kTolerance, kMarkExcess, false);
- if (data_result.success == false) break; // Fail
- // Data is in LSB order. We need to reverse it.
- results->state[i] = (uint8_t)data_result.data;
- }
- // Section Footer
- if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcBitMark))
- return false;
- if (section < kWhirlpoolAcSections - 1) { // Inter-section gaps.
- if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcGap)) return false;
- } else { // Last section / End of message gap.
- if (offset <= results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kWhirlpoolAcGap))
- return false;
- }
}
// Compliance
if (strict) {
// Re-check we got the correct size/length due to the way we read the data.
- if (dataBitsSoFar != kWhirlpoolAcBits) return false;
- if (!IRWhirlpoolAc::validChecksum(results->state, dataBitsSoFar / 8))
+ if (pos * 8 != nbits) return false;
+ if (!IRWhirlpoolAc::validChecksum(results->state, nbits / 8))
return false;
}
// Success
results->decode_type = WHIRLPOOL_AC;
- results->bits = dataBitsSoFar;
+ results->bits = nbits;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.h b/lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.h
similarity index 75%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.h
rename to lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.h
index 9604d025c..156c4b631 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.h
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.h
@@ -2,6 +2,16 @@
//
// Copyright 2018 David Conran
+// Supports:
+// Brand: Whirlpool, Model: DG11J1-3A remote
+// Brand: Whirlpool, Model: DG11J1-04 remote
+// Brand: Whirlpool, Model: DG11J1-91 remote
+// Brand: Whirlpool, Model: SPIS409L A/C
+// Brand: Whirlpool, Model: SPIS412L A/C
+// Brand: Whirlpool, Model: SPIW409L A/C
+// Brand: Whirlpool, Model: SPIW412L A/C
+// Brand: Whirlpool, Model: SPIW418L A/C
+
#ifndef IR_WHIRLPOOL_H_
#define IR_WHIRLPOOL_H_
@@ -9,8 +19,6 @@
#include
#ifndef UNIT_TEST
#include
-#else
-#include
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
@@ -18,14 +26,8 @@
#include "IRsend_test.h"
#endif
-// WW WW HH HH IIIII RRRRRR LL PPPPPP OOOOO OOOOO LL
-// WW WW HH HH III RR RR LL PP PP OO OO OO OO LL
-// WW W WW HHHHHHH III RRRRRR LL PPPPPP OO OO OO OO LL
-// WW WWW WW HH HH III RR RR LL PP OO OO OO OO LL
-// WW WW HH HH IIIII RR RR LLLLLLL PP OOOO0 OOOO0 LLLLLLL
-
// Ref:
-// https://github.com/markszabo/IRremoteESP8266/issues/509
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/509
// Constants
const uint8_t kWhirlpoolAcChecksumByte1 = 13;
@@ -87,45 +89,47 @@ enum whirlpool_ac_remote_model_t {
// Classes
class IRWhirlpoolAc {
public:
- explicit IRWhirlpoolAc(uint16_t pin);
+ explicit IRWhirlpoolAc(const uint16_t pin, const bool inverted = false,
+ const bool use_modulation = true);
- void stateReset();
+ void stateReset(void);
#if SEND_WHIRLPOOL_AC
void send(const uint16_t repeat = kWhirlpoolAcDefaultRepeat,
const bool calcchecksum = true);
+ uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_WHIRLPOOL_AC
- void begin();
- void on();
- void off();
+ void begin(void);
+ void on(void);
+ void off(void);
void setPowerToggle(const bool on);
- bool getPowerToggle();
+ bool getPowerToggle(void);
void setSleep(const bool on);
- bool getSleep();
+ bool getSleep(void);
void setSuper(const bool on);
- bool getSuper();
+ bool getSuper(void);
void setTemp(const uint8_t temp);
- uint8_t getTemp();
+ uint8_t getTemp(void);
void setFan(const uint8_t speed);
- uint8_t getFan();
+ uint8_t getFan(void);
void setMode(const uint8_t mode);
- uint8_t getMode();
+ uint8_t getMode(void);
void setSwing(const bool on);
- bool getSwing();
+ bool getSwing(void);
void setLight(const bool on);
- bool getLight();
- uint16_t getClock();
+ bool getLight(void);
+ uint16_t getClock(void);
void setClock(const uint16_t minspastmidnight);
- uint16_t getOnTimer();
+ uint16_t getOnTimer(void);
void setOnTimer(const uint16_t minspastmidnight);
- void enableOnTimer(const bool state);
- bool isOnTimerEnabled();
- uint16_t getOffTimer();
+ void enableOnTimer(const bool on);
+ bool isOnTimerEnabled(void);
+ uint16_t getOffTimer(void);
void setOffTimer(const uint16_t minspastmidnight);
- void enableOffTimer(const bool state);
- bool isOffTimerEnabled();
+ void enableOffTimer(const bool on);
+ bool isOffTimerEnabled(void);
void setCommand(const uint8_t code);
- uint8_t getCommand();
- whirlpool_ac_remote_model_t getModel();
+ uint8_t getCommand(void);
+ whirlpool_ac_remote_model_t getModel(void);
void setModel(const whirlpool_ac_remote_model_t model);
uint8_t* getRaw(const bool calcchecksum = true);
void setRaw(const uint8_t new_code[],
@@ -134,11 +138,10 @@ class IRWhirlpoolAc {
const uint16_t length = kWhirlpoolAcStateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
-#ifdef ARDUINO
- String toString();
-#else
- std::string toString();
-#endif
+ static stdAc::opmode_t toCommonMode(const uint8_t mode);
+ static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
+ stdAc::state_t toCommon(void);
+ String toString(void);
#ifndef UNIT_TEST
private:
@@ -156,12 +159,7 @@ class IRWhirlpoolAc {
void enableTimer(const uint16_t pos, const bool state);
void _setTemp(const uint8_t temp, const bool remember = true);
void _setMode(const uint8_t mode);
- int8_t getTempOffset();
-#ifdef ARDUINO
- String timeToString(uint16_t minspastmidnight);
-#else
- std::string timeToString(uint16_t minspastmidnight);
-#endif
+ int8_t getTempOffset(void);
};
#endif // IR_WHIRLPOOL_H_
diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Whynter.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Whynter.cpp
similarity index 69%
rename from lib/IRremoteESP8266-2.6.0/src/ir_Whynter.cpp
rename to lib/IRremoteESP8266-2.6.5/src/ir_Whynter.cpp
index 555c50788..c5634f381 100644
--- a/lib/IRremoteESP8266-2.6.0/src/ir_Whynter.cpp
+++ b/lib/IRremoteESP8266-2.6.5/src/ir_Whynter.cpp
@@ -1,20 +1,17 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017 David Conran
+// Whynter A/C ARC-110WD added by Francesco Meschia
+// Whynter originally added from https://github.com/shirriff/Arduino-IRremote/
+
+// Supports:
+// Brand: Whynter, Model: ARC-110WD A/C
+
#include
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
-// W W H H Y Y N N TTTTT EEEEE RRRRR
-// W W H H Y Y NN N T E R R
-// W W W HHHHH Y N N N T EEE RRRR
-// W W W H H Y N NN T E R R
-// WWW H H Y N N T EEEEE R R
-
-// Whynter A/C ARC-110WD added by Francesco Meschia
-// Whynter originally added from https://github.com/shirriff/Arduino-IRremote/
-
// Constants
const uint16_t kWhynterTick = 50;
@@ -91,39 +88,18 @@ bool IRrecv::decodeWhynter(decode_results *results, uint16_t nbits,
return false; // Incorrect nr. of bits per spec.
uint16_t offset = kStartOffset;
-
- // Header
+ uint64_t data = 0;
+ // Pre-Header
// Sequence begins with a bit mark and a zero space.
- // These are typically small, so we'll prefer to do the calibration
- // on the much larger header mark & space that are next.
if (!matchMark(results->rawbuf[offset++], kWhynterBitMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kWhynterZeroSpace)) return false;
- // Main header mark and space
- if (!matchMark(results->rawbuf[offset], kWhynterHdrMark)) return false;
- // Calculate how long the common tick time is based on the header mark.
- uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kWhynterHdrMarkTicks;
- if (!matchSpace(results->rawbuf[offset], kWhynterHdrSpace)) return false;
- // Calculate how long the common tick time is based on the header space.
- uint32_t s_tick =
- results->rawbuf[offset++] * kRawTick / kWhynterHdrSpaceTicks;
-
- // Data
- uint64_t data = 0;
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), nbits,
- kWhynterBitMarkTicks * m_tick, kWhynterOneSpaceTicks * s_tick,
- kWhynterBitMarkTicks * m_tick, kWhynterZeroSpaceTicks * s_tick);
- if (data_result.success == false) return false;
- data = data_result.data;
- offset += data_result.used;
-
- // Footer
- if (!matchMark(results->rawbuf[offset++], kWhynterBitMarkTicks * m_tick))
- return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset], kWhynterMinGapTicks * s_tick))
- return false;
-
+ // Match Main Header + Data + Footer
+ if (!matchGeneric(results->rawbuf + offset, &data,
+ results->rawlen - offset, nbits,
+ kWhynterHdrMark, kWhynterHdrSpace,
+ kWhynterBitMark, kWhynterOneSpace,
+ kWhynterBitMark, kWhynterZeroSpace,
+ kWhynterBitMark, kWhynterMinGap, true)) return false;
// Success
results->decode_type = WHYNTER;
results->bits = nbits;
diff --git a/lib/IRremoteESP8266-2.6.0/test/IRac_test.cpp b/lib/IRremoteESP8266-2.6.5/test/IRac_test.cpp
similarity index 53%
rename from lib/IRremoteESP8266-2.6.0/test/IRac_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/IRac_test.cpp
index 39c17a84b..3afc89c6e 100644
--- a/lib/IRremoteESP8266-2.6.0/test/IRac_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/IRac_test.cpp
@@ -1,8 +1,12 @@
// Copyright 2019 David Conran
+#include
+#include "ir_Amcor.h"
#include "ir_Argo.h"
#include "ir_Daikin.h"
+#include "ir_Electra.h"
#include "ir_Fujitsu.h"
+#include "ir_Goodweather.h"
#include "ir_Gree.h"
#include "ir_Haier.h"
#include "ir_Hitachi.h"
@@ -10,8 +14,10 @@
#include "ir_Midea.h"
#include "ir_Mitsubishi.h"
#include "ir_MitsubishiHeavy.h"
+#include "ir_Neoclima.h"
#include "ir_Panasonic.h"
#include "ir_Samsung.h"
+#include "ir_Sharp.h"
#include "ir_Tcl.h"
#include "ir_Teco.h"
#include "ir_Toshiba.h"
@@ -28,6 +34,27 @@
// Tests for IRac class.
+TEST(TestIRac, Amcor) {
+ IRAmcorAc ac(0);
+ IRac irac(0);
+ IRrecv capture(0);
+ char expected[] =
+ "Power: On, Mode: 5 (AUTO), Fan: 3 (High), Temp: 19C, Max: Off";
+
+ ac.begin();
+ irac.amcor(&ac,
+ true, // Power
+ stdAc::opmode_t::kAuto, // Mode
+ 19, // Celsius
+ stdAc::fanspeed_t::kHigh); // Fan speed
+ ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(AMCOR, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kAmcorBits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
+}
+
TEST(TestIRac, Argo) {
IRArgoAC ac(0);
IRac irac(0);
@@ -42,7 +69,7 @@ TEST(TestIRac, Argo) {
false, // Turbo
-1); // Sleep
EXPECT_TRUE(ac.getPower());
- EXPECT_EQ(1, ac.getMode());
+ EXPECT_EQ(kArgoHeat, ac.getMode());
EXPECT_EQ(21, ac.getTemp());
EXPECT_EQ(kArgoFlapAuto, ac.getFlap());
EXPECT_FALSE(ac.getMax()); // Turbo
@@ -74,25 +101,57 @@ TEST(TestIRac, Coolix) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(COOLIX, ac._irsend.capture.decode_type);
ASSERT_EQ(kCoolixBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.value);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
+ // Confirm we are sending with a repeat of 1. i.e. two messages.
+ EXPECT_EQ(
+ "f38000d50" // 38kHz Frequency and 50% duty-cycle.
+ // Start of message #1 (i.e. Repeat '0')
+ // Header
+ "m4480s4480"
+ // Data
+ "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560"
+ "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680"
+ "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
+ "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560"
+ "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s560"
+ "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680"
+ // Footer
+ "m560s5040"
+ // End of message #1 (i.e. Repeat '0')
+ // Start of message #2 (i.e. Repeat '1')
+ // Header
+ "m4480s4480"
+ // Data
+ "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560"
+ "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680"
+ "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
+ "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560"
+ "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s560"
+ "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680"
+ // Footer
+ "m560s105040",
+ // End of message #2 (i.e. Repeat '1')
+ // Note: the two messages (#1 & #2) are identical.
+ ac._irsend.outputStr());
}
TEST(TestIRac, Daikin) {
IRDaikinESP ac(0);
IRac irac(0);
+ IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 3 (COOL), Temp: 19C, Fan: 2, Powerful: Off, "
- "Quiet: Off, Sensor: Off, Eye: Off, Mold: On, Comfort: Off, "
+ "Power: On, Mode: 3 (COOL), Temp: 19C, Fan: 5 (High), Powerful: Off, "
+ "Quiet: Off, Sensor: Off, Mold: On, Comfort: Off, "
"Swing (Horizontal): Off, Swing (Vertical): Off, "
- "Current Time: 0:00, On Time: Off, Off Time: Off";
+ "Current Time: 00:00, Current Day: (UNKNOWN), On Time: Off, "
+ "Off Time: Off, Weekly Timer: On";
ac.begin();
irac.daikin(&ac,
true, // Power
stdAc::opmode_t::kCool, // Mode
19, // Celsius
- stdAc::fanspeed_t::kMedium, // Fan speed
+ stdAc::fanspeed_t::kMax, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Quiet
@@ -100,6 +159,87 @@ TEST(TestIRac, Daikin) {
true, // Filter
true); // Clean
ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(DAIKIN, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kDaikinBits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
+}
+
+TEST(TestIRac, Daikin128) {
+ IRDaikin128 ac(0);
+ IRac irac(0);
+ IRrecv capture(0);
+ char expected[] =
+ "Power Toggle: On, Mode: 8 (HEAT), Temp: 27C, Fan: 9 (Quiet), "
+ "Powerful: Off, Quiet: On, Swing (V): On, Sleep: On, "
+ "Econo: Off, Clock: 21:57, On Timer: Off, On Time: 00:00, "
+ "Off Timer: Off, Off Time: 00:00, Light Toggle: 8 (Wall)";
+
+ ac.begin();
+ irac.daikin128(&ac,
+ true, // Power
+ stdAc::opmode_t::kHeat, // Mode
+ 27, // Celsius
+ stdAc::fanspeed_t::kMin, // Fan speed
+ stdAc::swingv_t::kAuto, // Veritcal swing
+ true, // Quiet
+ false, // Turbo
+ true, // Light
+ false, // Econo
+ 18 * 60, // Sleep
+ 21 * 60 + 57); // Clock
+ ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(DAIKIN128, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kDaikin128Bits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
+}
+
+TEST(TestIRac, Daikin160) {
+ IRDaikin160 ac(0);
+ IRac irac(0);
+ IRrecv capture(0);
+ char expected[] =
+ "Power: On, Mode: 2 (DRY), Temp: 23C, Fan: 1 (Low), "
+ "Vent Position (V): 3 (Middle)";
+
+ ac.begin();
+ irac.daikin160(&ac,
+ true, // Power
+ stdAc::opmode_t::kDry, // Mode
+ 23, // Celsius
+ stdAc::fanspeed_t::kMin, // Fan speed
+ stdAc::swingv_t::kMiddle); // Veritcal swing
+ ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(DAIKIN160, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kDaikin160Bits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
+}
+
+TEST(TestIRac, Daikin176) {
+ IRDaikin176 ac(0);
+ IRac irac(0);
+ IRrecv capture(0);
+ char expected[] =
+ "Power: On, Mode: 7 (COOL), Temp: 26C, Fan: 1 (Low), Swing (H): 5 (Auto)";
+
+ ac.begin();
+ irac.daikin176(&ac,
+ true, // Power
+ stdAc::opmode_t::kCool, // Mode
+ 26, // Celsius
+ stdAc::fanspeed_t::kLow, // Fan speed
+ stdAc::swingh_t::kAuto); // Horizontal swing
+ ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(DAIKIN176, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kDaikin176Bits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Daikin2) {
@@ -107,18 +247,18 @@ TEST(TestIRac, Daikin2) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 3 (COOL), Temp: 19C, Fan: 2, Swing (V): 14 (Auto), "
- "Swing (H): 0, Clock: 0:00, On Time: Off, Off Time: Off, "
- "Sleep Time: Off, Beep: 1 (Quiet), Light: 1 (Bright), Mold: On, "
- "Clean: Off, Fresh Air: Off, Eye: Off, Eye Auto: Off, Quiet: Off, "
- "Powerful: Off, Purify: On, Econo: Off";
+ "Power: On, Mode: 3 (COOL), Temp: 19C, Fan: 1 (Low), "
+ "Swing (V): 14 (Auto), Swing (H): 0, Clock: 00:00, On Time: Off, "
+ "Off Time: Off, Sleep Time: Off, Beep: 1 (Quiet), Light: 1 (Bright), "
+ "Mold: On, Clean: Off, Fresh Air: Off, Eye: Off, Eye Auto: Off, "
+ "Quiet: Off, Powerful: Off, Purify: On, Econo: Off";
ac.begin();
irac.daikin2(&ac,
true, // Power
stdAc::opmode_t::kCool, // Mode
19, // Celsius
- stdAc::fanspeed_t::kMedium, // Fan speed
+ stdAc::fanspeed_t::kLow, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Quiet
@@ -134,8 +274,7 @@ TEST(TestIRac, Daikin2) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(DAIKIN2, ac._irsend.capture.decode_type);
ASSERT_EQ(kDaikin2Bits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Daikin216) {
@@ -143,8 +282,8 @@ TEST(TestIRac, Daikin216) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 4 (HEAT), Temp: 31C, Fan: 11 (QUIET), "
- "Swing (Horizontal): On, Swing (Vertical): On, Quiet: On";
+ "Power: On, Mode: 4 (HEAT), Temp: 31C, Fan: 11 (Quiet), "
+ "Swing (Horizontal): On, Swing (Vertical): On, Quiet: On, Powerful: Off";
ac.begin();
irac.daikin216(&ac,
@@ -154,12 +293,37 @@ TEST(TestIRac, Daikin216) {
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingh_t::kLeft, // Horizontal swing
- true); // Quiet
+ true, // Quiet
+ false); // Turbo (Powerful)
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(DAIKIN216, ac._irsend.capture.decode_type);
ASSERT_EQ(kDaikin216Bits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
+}
+
+TEST(TestIRac, Electra) {
+ IRElectraAc ac(0);
+ IRac irac(0);
+ IRrecv capture(0);
+ char expected[] =
+ "Power: On, Mode: 6 (FAN), Temp: 26C, Fan: 1 (High), "
+ "Swing(V): On, Swing(H): On";
+
+ ac.begin();
+ irac.electra(&ac,
+ true, // Power
+ stdAc::opmode_t::kFan, // Mode
+ 26, // Celsius
+ stdAc::fanspeed_t::kHigh, // Fan speed
+ stdAc::swingv_t::kAuto, // Veritcal swing
+ stdAc::swingh_t::kLeft); // Horizontal swing
+ ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(ELECTRA_AC, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kElectraAcBits, ac._irsend.capture.bits);
ac.setRaw(ac._irsend.capture.state);
ASSERT_EQ(expected, ac.toString());
}
@@ -168,9 +332,12 @@ TEST(TestIRac, Fujitsu) {
IRFujitsuAC ac(0);
IRac irac(0);
IRrecv capture(0);
- char expected[] =
- "Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 2 (MED), "
- "Swing: Off, Command: N/A";
+ std::string ardb1_expected =
+ "Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 19C, "
+ "Fan: 2 (Medium), Command: N/A";
+ std::string arrah2e_expected =
+ "Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 19C, "
+ "Fan: 2 (Medium), Swing: Off, Command: N/A";
ac.begin();
irac.fujitsu(&ac,
@@ -181,14 +348,15 @@ TEST(TestIRac, Fujitsu) {
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingh_t::kOff, // Horizontal swing
- false); // Quiet
- ASSERT_EQ(expected, ac.toString());
+ false, // Quiet
+ false, // Turbo (Powerful)
+ false); // Econo
+ ASSERT_EQ(ardb1_expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kFujitsuAcBits - 8, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state, ac._irsend.capture.bits / 8);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(ardb1_expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
ac._irsend.reset();
irac.fujitsu(&ac,
@@ -199,14 +367,41 @@ TEST(TestIRac, Fujitsu) {
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingh_t::kOff, // Horizontal swing
- false); // Quiet
- ASSERT_EQ(expected, ac.toString());
+ false, // Quiet
+ false, // Turbo (Powerful)
+ false); // Econo
+ ASSERT_EQ(arrah2e_expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kFujitsuAcBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state, ac._irsend.capture.bits / 8);
+ ASSERT_EQ(arrah2e_expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
+}
+
+TEST(TestIRac, Goodweather) {
+ IRGoodweatherAc ac(0);
+ IRac irac(0);
+ IRrecv capture(0);
+ char expected[] =
+ "Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 2 (Medium), Turbo: Toggle, "
+ "Light: Toggle, Sleep: Toggle, Swing: 1 (Slow), Command: 0 (Power)";
+
+ ac.begin();
+ irac.goodweather(&ac,
+ true, // Power
+ stdAc::opmode_t::kCool, // Mode
+ 19, // Celsius
+ stdAc::fanspeed_t::kMedium, // Fan speed
+ stdAc::swingv_t::kHigh, // Veritcal swing
+ true, // Turbo
+ true, // Light
+ 8 * 60 + 0); // Sleep time
ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(GOODWEATHER, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kGoodweatherBits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Gree) {
@@ -214,28 +409,29 @@ TEST(TestIRac, Gree) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 1 (COOL), Temp: 22C, Fan: 2, Turbo: Off, XFan: On, "
+ "Model: 1 (YAW1F), Power: On, Mode: 1 (COOL), Temp: 22C, "
+ "Fan: 2 (Medium), Turbo: Off, IFeel: Off, WiFi: Off, XFan: On, "
"Light: On, Sleep: On, Swing Vertical Mode: Manual, "
- "Swing Vertical Pos: 3";
+ "Swing Vertical Pos: 3, Timer: Off";
ac.begin();
irac.gree(&ac,
- true, // Power
- stdAc::opmode_t::kCool, // Mode
- 22, // Celsius
- stdAc::fanspeed_t::kMedium, // Fan speed
- stdAc::swingv_t::kHigh, // Veritcal swing
- false, // Turbo
- true, // Light
- true, // Clean (aka Mold/XFan)
- 8 * 60 + 0); // Sleep time
+ gree_ac_remote_model_t::YAW1F, // Model
+ true, // Power
+ stdAc::opmode_t::kCool, // Mode
+ 22, // Celsius
+ stdAc::fanspeed_t::kMedium, // Fan speed
+ stdAc::swingv_t::kHigh, // Veritcal swing
+ false, // Turbo
+ true, // Light
+ true, // Clean (aka Mold/XFan)
+ 8 * 60 + 0); // Sleep time
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(GREE, ac._irsend.capture.decode_type);
ASSERT_EQ(kGreeBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Haier) {
@@ -243,9 +439,9 @@ TEST(TestIRac, Haier) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Command: 1 (On), Mode: 3 (HEAT), Temp: 24C, Fan: 2, Swing: 1 (Up), "
- "Sleep: On, Health: On, Current Time: 13:45, On Timer: Off, "
- "Off Timer: Off";
+ "Command: 1 (On), Mode: 1 (COOL), Temp: 24C, Fan: 2 (Medium), "
+ "Swing: 1 (Up), Sleep: On, Health: On, Current Time: 13:45, "
+ "On Timer: Off, Off Timer: Off";
ac.begin();
irac.haier(&ac,
@@ -262,8 +458,7 @@ TEST(TestIRac, Haier) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(HAIER_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kHaierACBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
@@ -272,8 +467,8 @@ TEST(TestIRac, HaierYrwo2) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Button: 5 (Power), Mode: 2 (Cool), Temp: 23C, Fan: 4 (Med), "
- "Turbo: 1 (High), Swing: 1 (Top), Sleep: On, Health: On";
+ "Power: On, Button: 5 (Power), Mode: 2 (COOL), Temp: 23C, "
+ "Fan: 4 (Medium), Turbo: 1 (High), Swing: 1 (Top), Sleep: On, Health: On";
ac.begin();
irac.haierYrwo2(&ac,
@@ -290,8 +485,7 @@ TEST(TestIRac, HaierYrwo2) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(HAIER_AC_YRW02, ac._irsend.capture.decode_type);
ASSERT_EQ(kHaierACYRW02Bits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Hitachi) {
@@ -299,7 +493,7 @@ TEST(TestIRac, Hitachi) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 2 (AUTO), Temp: 22C, Fan: 3 (UNKNOWN), "
+ "Power: On, Mode: 2 (AUTO), Temp: 22C, Fan: 3 (Medium), "
"Swing (Vertical): Off, Swing (Horizontal): On";
ac.begin();
@@ -316,8 +510,7 @@ TEST(TestIRac, Hitachi) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(HITACHI_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kHitachiAcBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Kelvinator) {
@@ -325,9 +518,9 @@ TEST(TestIRac, Kelvinator) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 3, Turbo: Off, Quiet: Off, "
- "XFan: On, IonFilter: On, Light: On, Swing (Horizontal): Off, "
- "Swing (Vertical): Off";
+ "Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 3 (Medium), Turbo: Off, "
+ "Quiet: Off, XFan: On, IonFilter: On, Light: On, "
+ "Swing (Horizontal): Off, Swing (Vertical): Off";
ac.begin();
irac.kelvinator(&ac,
@@ -348,8 +541,7 @@ TEST(TestIRac, Kelvinator) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(KELVINATOR, ac._irsend.capture.decode_type);
ASSERT_EQ(kKelvinatorBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Midea) {
@@ -357,14 +549,17 @@ TEST(TestIRac, Midea) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 1 (DRY), Temp: 27C/81F, Fan: 2 (MED), Sleep: On";
+ "Power: On, Mode: 1 (DRY), Celsius: On, Temp: 27C/80F, Fan: 2 (Medium), "
+ "Sleep: On, Swing(V) Toggle: Off";
ac.begin();
irac.midea(&ac,
true, // Power
stdAc::opmode_t::kDry, // Mode
- 27, // Celsius
+ true, // Celsius
+ 27, // Degrees
stdAc::fanspeed_t::kMedium, // Fan speed
+ stdAc::swingv_t::kOff, // Swing (V)
8 * 60 + 0); // Sleep time
ASSERT_EQ(expected, ac.toString());
@@ -372,8 +567,7 @@ TEST(TestIRac, Midea) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(MIDEA, ac._irsend.capture.decode_type);
ASSERT_EQ(kMideaBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.value);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Mitsubishi) {
@@ -381,8 +575,8 @@ TEST(TestIRac, Mitsubishi) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On (COOL), Temp: 20C, FAN: 2, VANE: AUTO, Time: 14:30, "
- "On timer: 00:00, Off timer: 00:00, Timer: -";
+ "Power: On, Mode: 24 (COOL), Temp: 20C, Fan: 2 (Medium), Vane: AUTO, "
+ "Wide Vane: 3, Time: 14:30, On timer: 00:00, Off timer: 00:00, Timer: -";
ac.begin();
irac.mitsubishi(&ac,
@@ -391,6 +585,7 @@ TEST(TestIRac, Mitsubishi) {
20, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
+ stdAc::swingh_t::kOff, // Horizontal swing
false, // Silent
14 * 60 + 35); // Clock
ASSERT_EQ(expected, ac.toString());
@@ -398,8 +593,7 @@ TEST(TestIRac, Mitsubishi) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(MITSUBISHI_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kMitsubishiACBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, MitsubishiHeavy88) {
@@ -407,7 +601,7 @@ TEST(TestIRac, MitsubishiHeavy88) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 1 (Cool), Temp: 21C, Fan: 3 (Med), "
+ "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (Medium), "
"Swing (V): 16 (Auto), Swing (H): 0 (Off), Turbo: Off, Econo: Off, "
"3D: Off, Clean: On";
@@ -427,8 +621,7 @@ TEST(TestIRac, MitsubishiHeavy88) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(MITSUBISHI_HEAVY_88, ac._irsend.capture.decode_type);
ASSERT_EQ(kMitsubishiHeavy88Bits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, MitsubishiHeavy152) {
@@ -436,7 +629,7 @@ TEST(TestIRac, MitsubishiHeavy152) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 6 (Econo), "
+ "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 6 (Econo), "
"Swing (V): 6 (Off), Swing (H): 0 (Auto), Silent: On, Turbo: Off, "
"Econo: On, Night: On, Filter: On, 3D: Off, Clean: Off";
@@ -459,8 +652,37 @@ TEST(TestIRac, MitsubishiHeavy152) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(MITSUBISHI_HEAVY_152, ac._irsend.capture.decode_type);
ASSERT_EQ(kMitsubishiHeavy152Bits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
+}
+
+TEST(TestIRac, Neoclima) {
+ IRNeoclimaAc ac(0);
+ IRac irac(0);
+ IRrecv capture(0);
+ char expected[] =
+ "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 3 (Low), "
+ "Swing(V): Off, Swing(H): On, Sleep: On, Turbo: Off, Hold: Off, Ion: On, "
+ "Eye: Off, Light: On, Follow: Off, 8C Heat: Off, Fresh: Off, "
+ "Button: 0 (Power)";
+
+ ac.begin();
+ irac.neoclima(&ac,
+ true, // Power
+ stdAc::opmode_t::kCool, // Mode
+ 20, // Celsius
+ stdAc::fanspeed_t::kLow, // Fan speed
+ stdAc::swingv_t::kOff, // Veritcal swing
+ stdAc::swingh_t::kAuto, // Horizontal swing
+ false, // Turbo
+ true, // Light
+ true, // Filter
+ 8 * 60); // Sleep
ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(decode_type_t::NEOCLIMA, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kNeoclimaBits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Panasonic) {
@@ -468,7 +690,7 @@ TEST(TestIRac, Panasonic) {
IRac irac(0);
IRrecv capture(0);
char expected_nke[] =
- "Model: 2 (NKE), Power: On, Mode: 4 (HEAT), Temp: 28C, Fan: 2 (UNKNOWN), "
+ "Model: 2 (NKE), Power: On, Mode: 4 (HEAT), Temp: 28C, Fan: 2 (Medium), "
"Swing (Vertical): 15 (AUTO), Swing (Horizontal): 6 (Middle), Quiet: On, "
"Powerful: Off, Clock: 19:17, On Timer: Off, Off Timer: Off";
@@ -489,11 +711,10 @@ TEST(TestIRac, Panasonic) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(PANASONIC_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kPanasonicAcBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected_nke, ac.toString());
+ ASSERT_EQ(expected_nke, IRAcUtils::resultAcToString(&ac._irsend.capture));
char expected_dke[] =
- "Model: 3 (DKE), Power: On, Mode: 3 (COOL), Temp: 18C, Fan: 4 (MAX), "
+ "Model: 3 (DKE), Power: On, Mode: 3 (COOL), Temp: 18C, Fan: 4 (High), "
"Swing (Vertical): 1 (Full Up), Swing (Horizontal): 6 (Middle), "
"Quiet: Off, Powerful: On, Clock: 19:17, On Timer: Off, Off Timer: Off";
ac._irsend.reset();
@@ -513,8 +734,7 @@ TEST(TestIRac, Panasonic) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(PANASONIC_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kPanasonicAcBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected_dke, ac.toString());
+ ASSERT_EQ(expected_dke, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Samsung) {
@@ -522,8 +742,8 @@ TEST(TestIRac, Samsung) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 0 (AUTO), Temp: 28C, Fan: 6 (AUTO), Swing: On, "
- "Beep: On, Clean: On, Quiet: On";
+ "Power: On, Mode: 0 (AUTO), Temp: 28C, Fan: 6 (Auto), Swing: On, "
+ "Beep: On, Clean: On, Quiet: On, Powerful: Off";
ac.begin();
irac.samsung(&ac,
@@ -536,14 +756,13 @@ TEST(TestIRac, Samsung) {
false, // Turbo
true, // Clean
true, // Beep
- false); // with the Hack Off
+ false); // with dopower Off
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kSamsungAcBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
ac._irsend.reset();
irac.samsung(&ac,
@@ -556,19 +775,39 @@ TEST(TestIRac, Samsung) {
false, // Turbo
true, // Clean
true, // Beep
- true); // with the Hack On
+ true); // with dopower On
ASSERT_EQ(expected, ac.toString()); // Class should be in the desired mode.
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
// However, we expect a plain "on" state as it should be sent before the
// desired state.
char expected_on[] =
- "Power: On, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), Swing: Off, "
- "Beep: Off, Clean: Off, Quiet: Off";
- ASSERT_EQ(expected_on, ac.toString());
+ "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off";
+ ASSERT_EQ(expected_on, IRAcUtils::resultAcToString(&ac._irsend.capture));
+}
+
+TEST(TestIRac, Sharp) {
+ IRSharpAc ac(0);
+ IRac irac(0);
+ IRrecv capture(0);
+ char expected[] =
+ "Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 3 (Medium)";
+
+ ac.begin();
+ irac.sharp(&ac,
+ true, // Power
+ stdAc::opmode_t::kCool, // Mode
+ 28, // Celsius
+ stdAc::fanspeed_t::kMedium); // Fan speed
+ ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(SHARP_AC, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kSharpAcBits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Tcl112) {
@@ -576,7 +815,7 @@ TEST(TestIRac, Tcl112) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 3 (Med), Econo: On, "
+ "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 3 (Medium), Econo: On, "
"Health: On, Light: On, Turbo: Off, Swing (H): On, Swing (V): Off";
ac.begin();
@@ -596,8 +835,7 @@ TEST(TestIRac, Tcl112) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(TCL112AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kTcl112AcBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Teco) {
@@ -605,8 +843,8 @@ TEST(TestIRac, Teco) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 0 (AUTO), Temp: 21C, Fan: 2 (Med), Sleep: On, "
- "Swing: On";
+ "Power: On, Mode: 0 (AUTO), Temp: 21C, Fan: 2 (Medium), Sleep: On, "
+ "Swing: On, Light: On, Humid: Off, Save: Off";
ac.begin();
irac.teco(&ac,
@@ -615,21 +853,21 @@ TEST(TestIRac, Teco) {
21, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
+ true, // Light
8 * 60 + 30); // Sleep
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(TECO, ac._irsend.capture.decode_type);
ASSERT_EQ(kTecoBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.value);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Toshiba) {
IRToshibaAC ac(0);
IRac irac(0);
IRrecv capture(0);
- char expected[] = "Power: On, Mode: 2 (DRY), Temp: 29C, Fan: 2";
+ char expected[] = "Power: On, Mode: 2 (DRY), Temp: 29C, Fan: 2 (UNKNOWN)";
ac.begin();
irac.toshiba(&ac,
@@ -642,13 +880,15 @@ TEST(TestIRac, Toshiba) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(TOSHIBA_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kToshibaACBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Trotec) {
IRTrotecESP ac(0);
IRac irac(0);
+ IRrecv capture(0);
+ char expected[] =
+ "Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 3 (High), Sleep: On";
ac.begin();
irac.trotec(&ac,
@@ -662,6 +902,12 @@ TEST(TestIRac, Trotec) {
EXPECT_EQ(18, ac.getTemp());
EXPECT_EQ(kTrotecFanHigh, ac.getSpeed());
EXPECT_TRUE(ac.getSleep());
+ ASSERT_EQ(expected, ac.toString());
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(TROTEC, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kTrotecBits, ac._irsend.capture.bits);
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Vestel) {
@@ -669,7 +915,7 @@ TEST(TestIRac, Vestel) {
IRac irac(0);
IRrecv capture(0);
char expected[] =
- "Power: On, Mode: 0 (AUTO), Temp: 22C, Fan: 5 (LOW), Sleep: On, "
+ "Power: On, Mode: 0 (AUTO), Temp: 22C, Fan: 5 (Low), Sleep: On, "
"Turbo: Off, Ion: On, Swing: On";
ac.begin();
@@ -688,8 +934,7 @@ TEST(TestIRac, Vestel) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(VESTEL_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kVestelAcBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
ac._irsend.reset();
char expected_clocks[] =
@@ -713,8 +958,7 @@ TEST(TestIRac, Vestel) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(VESTEL_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kVestelAcBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected_clocks, ac.toString());
+ ASSERT_EQ(expected_clocks, IRAcUtils::resultAcToString(&ac._irsend.capture));
// Now check it sends both messages during normal operation when the
// clock is set.
@@ -760,7 +1004,7 @@ TEST(TestIRac, Whirlpool) {
IRrecv capture(0);
char expected[] =
"Model: 1 (DG11J13A), Power toggle: On, Mode: 1 (AUTO), Temp: 21C, "
- "Fan: 3 (LOW), Swing: On, Light: On, Clock: 23:58, On Timer: Off, "
+ "Fan: 3 (Low), Swing: On, Light: On, Clock: 23:58, On Timer: Off, "
"Off Timer: Off, Sleep: On, Super: Off, Command: 1 (POWER)";
ac.begin();
@@ -780,8 +1024,114 @@ TEST(TestIRac, Whirlpool) {
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(WHIRLPOOL_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kWhirlpoolAcBits, ac._irsend.capture.bits);
- ac.setRaw(ac._irsend.capture.state);
- ASSERT_EQ(expected, ac.toString());
+ ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
+}
+
+TEST(TestIRac, cmpStates) {
+ stdAc::state_t a, b;
+ a.protocol = decode_type_t::COOLIX;
+ a.model = -1;
+ a.power = true;
+ a.celsius = true;
+ a.degrees = 25;
+ a.mode = stdAc::opmode_t::kAuto;
+ a.fanspeed = stdAc::fanspeed_t::kAuto;
+ a.swingh = stdAc::swingh_t::kOff;
+ a.swingv = stdAc::swingv_t::kOff;
+ a.quiet = false;
+ a.turbo = false;
+ a.light = false;
+ a.econo = false;
+ a.beep = false;
+ a.filter = false;
+ a.clean = false;
+ a.quiet = false;
+ a.sleep = -1;
+ a.clock = -1;
+
+ ASSERT_FALSE(IRac::cmpStates(a, a));
+ ASSERT_TRUE(IRac::cmpStates(a, b));
+
+ b = a;
+ ASSERT_FALSE(IRac::cmpStates(a, b));
+
+ // Check we don't compare the clock.
+ b.clock = 1234;
+ ASSERT_FALSE(IRac::cmpStates(a, b));
+
+ // Now make them different.
+ b.power = false;
+ ASSERT_TRUE(IRac::cmpStates(a, b));
+}
+
+TEST(TestIRac, handleToggles) {
+ stdAc::state_t desired, prev, result;
+ desired.protocol = decode_type_t::COOLIX;
+ desired.model = -1;
+ desired.power = true;
+ desired.celsius = true;
+ desired.degrees = 25;
+ desired.mode = stdAc::opmode_t::kAuto;
+ desired.fanspeed = stdAc::fanspeed_t::kAuto;
+ desired.swingh = stdAc::swingh_t::kOff;
+ desired.swingv = stdAc::swingv_t::kOff;
+ desired.quiet = false;
+ desired.turbo = false;
+ desired.light = false;
+ desired.econo = false;
+ desired.beep = false;
+ desired.filter = false;
+ desired.clean = false;
+ desired.quiet = false;
+ desired.sleep = -1;
+ desired.clock = -1;
+
+ // The states should be the same as we gave no previous state.
+ EXPECT_FALSE(IRac::cmpStates(desired, IRac::handleToggles(desired)));
+ // The states should be the same as we gave no settings that changed.
+ prev = desired;
+ EXPECT_FALSE(IRac::cmpStates(desired, IRac::handleToggles(desired, &prev)));
+ // Change something that isn't a toggle.
+ desired.degrees = 26;
+ ASSERT_TRUE(IRac::cmpStates(desired, prev));
+ // Still shouldn't change.
+ EXPECT_FALSE(IRac::cmpStates(desired, IRac::handleToggles(desired, &prev)));
+ prev.turbo = true; // This requires a toggle.
+ result = IRac::handleToggles(desired, &prev);
+ EXPECT_TRUE(IRac::cmpStates(desired, result));
+ EXPECT_TRUE(result.turbo);
+ desired.turbo = true; // As the desired setting hasn't changed from previous
+ // the result should not have turbo set, as it is
+ // a toggle setting.
+ result = IRac::handleToggles(desired, &prev);
+ EXPECT_TRUE(IRac::cmpStates(desired, result));
+ EXPECT_FALSE(result.turbo);
+
+ // Go back to the same states.
+ prev = desired;
+ ASSERT_FALSE(IRac::cmpStates(desired, prev));
+ // Test swing, as it is more complicated.
+ result = IRac::handleToggles(desired, &prev);
+ EXPECT_EQ(stdAc::swingv_t::kOff, result.swingv);
+ desired.swingv = stdAc::swingv_t::kAuto;
+ result = IRac::handleToggles(desired, &prev);
+ EXPECT_NE(stdAc::swingv_t::kOff, result.swingv);
+
+ prev = desired; // Pretend it was sent and time has passed.
+ ASSERT_FALSE(IRac::cmpStates(desired, prev));
+ ASSERT_NE(stdAc::swingv_t::kOff, desired.swingv);
+
+ // User changes setting but it's still an "on" setting, as this device
+ // only has a binary on/off for swingv. Nothing should change.
+ desired.swingv = stdAc::swingv_t::kHigh;
+ result = IRac::handleToggles(desired, &prev);
+ ASSERT_EQ(stdAc::swingv_t::kOff, result.swingv); // i.e No toggle.
+
+ prev = desired; // Pretend it was sent and time has passed.
+ // User changes setting to off. i.e. It is no longer on, so it should toggle.
+ desired.swingv = stdAc::swingv_t::kOff;
+ result = IRac::handleToggles(desired, &prev);
+ ASSERT_NE(stdAc::swingv_t::kOff, result.swingv); // i.e A toggle.
}
TEST(TestIRac, strToBool) {
@@ -863,3 +1213,152 @@ TEST(TestIRac, strToModel) {
EXPECT_EQ(-1, IRac::strToModel("FOOBAR"));
EXPECT_EQ(0, IRac::strToModel("FOOBAR", 0));
}
+
+TEST(TestIRac, boolToString) {
+ EXPECT_EQ("on", IRac::boolToString(true));
+ EXPECT_EQ("off", IRac::boolToString(false));
+}
+
+TEST(TestIRac, opmodeToString) {
+ EXPECT_EQ("off", IRac::opmodeToString(stdAc::opmode_t::kOff));
+ EXPECT_EQ("auto", IRac::opmodeToString(stdAc::opmode_t::kAuto));
+ EXPECT_EQ("cool", IRac::opmodeToString(stdAc::opmode_t::kCool));
+ EXPECT_EQ("unknown", IRac::opmodeToString((stdAc::opmode_t)500));
+}
+
+TEST(TestIRac, fanspeedToString) {
+ EXPECT_EQ("low", IRac::fanspeedToString(stdAc::fanspeed_t::kLow));
+ EXPECT_EQ("auto", IRac::fanspeedToString(stdAc::fanspeed_t::kAuto));
+ EXPECT_EQ("unknown", IRac::fanspeedToString((stdAc::fanspeed_t)500));
+}
+
+TEST(TestIRac, swingvToString) {
+ EXPECT_EQ("off", IRac::swingvToString(stdAc::swingv_t::kOff));
+ EXPECT_EQ("low", IRac::swingvToString(stdAc::swingv_t::kLow));
+ EXPECT_EQ("auto", IRac::swingvToString(stdAc::swingv_t::kAuto));
+ EXPECT_EQ("unknown", IRac::swingvToString((stdAc::swingv_t)500));
+}
+
+TEST(TestIRac, swinghToString) {
+ EXPECT_EQ("off", IRac::swinghToString(stdAc::swingh_t::kOff));
+ EXPECT_EQ("left", IRac::swinghToString(stdAc::swingh_t::kLeft));
+ EXPECT_EQ("auto", IRac::swinghToString(stdAc::swingh_t::kAuto));
+ EXPECT_EQ("wide", IRac::swinghToString(stdAc::swingh_t::kWide));
+ EXPECT_EQ("unknown", IRac::swinghToString((stdAc::swingh_t)500));
+}
+
+// Check that we keep the previous state info if the message is a special
+// state-less command.
+TEST(TestIRac, CoolixDecodeToState) {
+ stdAc::state_t prev;
+ prev.mode = stdAc::opmode_t::kHeat;
+ prev.power = true;
+ prev.celsius = true;
+ prev.degrees = 20;
+ prev.fanspeed = stdAc::fanspeed_t::kLow;
+
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+ irsend.sendCOOLIX(kCoolixOff); // Special state-less "off" message.
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ stdAc::state_t result;
+ ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev));
+ ASSERT_EQ(decode_type_t::COOLIX, result.protocol);
+ ASSERT_FALSE(result.power);
+ ASSERT_EQ(stdAc::opmode_t::kHeat, result.mode);
+ ASSERT_TRUE(result.celsius);
+ ASSERT_EQ(20, result.degrees);
+ ASSERT_EQ(stdAc::fanspeed_t::kLow, result.fanspeed);
+}
+
+// Check light on/off functionality in Coolix common a/c handling.
+TEST(TestIRac, Issue821) {
+ stdAc::state_t prev;
+ stdAc::state_t next;
+ stdAc::state_t result;
+ // state info from:
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/821#issuecomment-513708970
+ prev.protocol = decode_type_t::COOLIX;
+ prev.model = -1;
+ prev.power = true;
+ prev.mode = stdAc::opmode_t::kAuto;
+ prev.degrees = 24;
+ prev.celsius = true;
+ prev.fanspeed = stdAc::fanspeed_t::kAuto;
+ prev.swingv = stdAc::swingv_t::kOff;
+ prev.swingh = stdAc::swingh_t::kOff;
+ prev.quiet = false;
+ prev.turbo = false;
+ prev.econo = false;
+ prev.light = false;
+ prev.filter = false;
+ prev.clean = false;
+ prev.beep = false;
+
+ next = prev;
+ next.light = true;
+
+ IRac irac(0);
+ IRrecv capture(0);
+ IRCoolixAC ac(0);
+
+ ac.begin();
+ result = irac.handleToggles(next, &prev);
+ ASSERT_TRUE(result.light);
+ irac.sendAc(next, &prev);
+ ASSERT_TRUE(next.light);
+ irac.coolix(&ac,
+ result.power, // Power
+ result.mode, // Mode
+ result.degrees, // Celsius
+ result.fanspeed, // Fan speed
+ result.swingv, // Veritcal swing
+ result.swingh, // Horizontal swing
+ result.turbo, // Turbo
+ result.light, // Light
+ result.clean, // Clean
+ -1); // Sleep
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(capture.decode(&ac._irsend.capture));
+ ASSERT_EQ(COOLIX, ac._irsend.capture.decode_type);
+ ASSERT_EQ(kCoolixBits, ac._irsend.capture.bits);
+ ASSERT_EQ("Power: On, Led: Toggle",
+ IRAcUtils::resultAcToString(&ac._irsend.capture));
+ EXPECT_EQ(
+ "f38000d50m"
+ "4480s4480"
+ "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s1680"
+ "m560s560m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s560"
+ "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680"
+ "m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680m560s560"
+ "m560s1680m560s560m560s1680m560s560m560s560m560s1680m560s560m560s1680"
+ "m560s560m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560"
+ "m560s5040"
+ "m4480s4480"
+ "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s1680"
+ "m560s560m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s560"
+ "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680"
+ "m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680m560s560"
+ "m560s1680m560s560m560s1680m560s560m560s560m560s1680m560s560m560s1680"
+ "m560s560m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560"
+ "m560s105040"
+ "m4480s4480"
+ "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560"
+ "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680"
+ "m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680"
+ "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560"
+ "m560s560m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560"
+ "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680"
+ "m560s5040"
+ "m4480s4480"
+ "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560"
+ "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680"
+ "m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680"
+ "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560"
+ "m560s560m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560"
+ "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680"
+ "m560s105040",
+ ac._irsend.outputStr());
+}
diff --git a/lib/IRremoteESP8266-2.6.5/test/IRrecv_test.cpp b/lib/IRremoteESP8266-2.6.5/test/IRrecv_test.cpp
new file mode 100644
index 000000000..cda7b747f
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/test/IRrecv_test.cpp
@@ -0,0 +1,1246 @@
+// Copyright 2017 David Conran
+
+#include "IRrecv_test.h"
+#include "IRrecv.h"
+#include "IRremoteESP8266.h"
+#include "IRsend.h"
+#include "IRsend_test.h"
+#include "gtest/gtest.h"
+
+// Tests for the IRrecv object.
+TEST(TestIRrecv, DefaultBufferSize) {
+ IRrecv irrecv_default(1);
+ EXPECT_EQ(kRawBuf, irrecv_default.getBufSize());
+}
+
+TEST(TestIRrecv, LargeBufferSize) {
+ IRrecv irrecv_large(3, 1024);
+ EXPECT_EQ(1024, irrecv_large.getBufSize());
+}
+
+TEST(TestIRrecv, SmallBufferSize) {
+ IRrecv irrecv_small(4, 80);
+ EXPECT_EQ(80, irrecv_small.getBufSize());
+}
+
+TEST(TestIRrecv, MediumBufferSize) {
+ IRrecv irrecv_medium(4, 512);
+ EXPECT_EQ(512, irrecv_medium.getBufSize());
+}
+
+TEST(TestIRrecv, IRrecvDestructor) {
+ IRrecv *irrecv_ptr = new IRrecv(1);
+ EXPECT_EQ(kRawBuf, irrecv_ptr->getBufSize());
+
+ delete irrecv_ptr;
+ irrecv_ptr = new IRrecv(1, 1234);
+ EXPECT_EQ(1234, irrecv_ptr->getBufSize());
+ delete irrecv_ptr;
+
+ irrecv_ptr = new IRrecv(1, 123);
+ EXPECT_EQ(123, irrecv_ptr->getBufSize());
+ delete irrecv_ptr;
+}
+
+// Tests for copyIrParams()
+
+TEST(TestCopyIrParams, CopyEmpty) {
+ irparams_t src;
+ irparams_t dst;
+ uint16_t test_size = 1234;
+ src.bufsize = test_size;
+ src.rawlen = 0;
+ src.rawbuf = new uint16_t[test_size];
+ src.overflow = false;
+ dst.bufsize = 4567;
+ dst.rawlen = 123;
+ dst.rawbuf = new uint16_t[test_size];
+ dst.overflow = true;
+ // Confirm we are looking at different memory for the buffers.
+ ASSERT_NE(src.rawbuf, dst.rawbuf);
+
+ IRrecv irrecv(4);
+ irrecv.copyIrParams(&src, &dst);
+
+ ASSERT_EQ(src.bufsize, dst.bufsize);
+ ASSERT_EQ(src.rawlen, dst.rawlen);
+ ASSERT_NE(src.rawbuf, dst.rawbuf); // Pointers, not content.
+ ASSERT_EQ(src.overflow, dst.overflow);
+ // Contents of the buffers needs to match.
+ EXPECT_EQ(0, memcmp(src.rawbuf, dst.rawbuf, src.bufsize * sizeof(uint16_t)));
+}
+
+TEST(TestCopyIrParams, CopyNonEmpty) {
+ irparams_t src;
+ irparams_t dst;
+ uint16_t test_size = 1234;
+ src.bufsize = test_size;
+ src.rawlen = 67;
+ src.rawbuf = new uint16_t[test_size];
+ src.rawbuf[0] = 0xF00D;
+ src.rawbuf[1] = 0xBEEF;
+ src.rawbuf[test_size - 1] = 0xDEAD;
+ src.overflow = true;
+ dst.bufsize = 0;
+ dst.rawlen = 0;
+ dst.rawbuf = new uint16_t[test_size];
+ dst.overflow = false;
+ // Confirm we are looking at different memory for the buffers.
+ ASSERT_NE(src.rawbuf, dst.rawbuf);
+ // and that they differ before we test.
+ EXPECT_NE(0, memcmp(src.rawbuf, dst.rawbuf, src.bufsize * sizeof(uint16_t)));
+
+ IRrecv irrecv(4);
+ irrecv.copyIrParams(&src, &dst);
+
+ ASSERT_EQ(src.bufsize, dst.bufsize);
+ EXPECT_EQ(test_size, dst.bufsize);
+ ASSERT_EQ(src.rawlen, dst.rawlen);
+ EXPECT_EQ(67, dst.rawlen);
+ ASSERT_EQ(src.overflow, dst.overflow);
+ EXPECT_TRUE(dst.overflow);
+ ASSERT_NE(src.rawbuf, dst.rawbuf); // Pointers, not content.
+ // Contents of the buffers needs to match.
+ EXPECT_EQ(0, memcmp(src.rawbuf, dst.rawbuf, src.bufsize * sizeof(uint16_t)));
+ // Check the canary values.
+ EXPECT_EQ(0xF00D, dst.rawbuf[0]);
+ EXPECT_EQ(0xBEEF, dst.rawbuf[1]);
+ EXPECT_EQ(0xDEAD, dst.rawbuf[test_size - 1]);
+}
+
+// Tests for decode().
+
+// Test decode of a NEC message.
+TEST(TestDecode, DecodeNEC) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendNEC(0x807F40BF);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(NEC, irsend.capture.decode_type);
+ EXPECT_EQ(kNECBits, irsend.capture.bits);
+ EXPECT_EQ(0x807F40BF, irsend.capture.value);
+}
+
+// Test decode of a JVC message.
+TEST(TestDecode, DecodeJVC) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendJVC(0xC2B8);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(JVC, irsend.capture.decode_type);
+ EXPECT_EQ(kJvcBits, irsend.capture.bits);
+ EXPECT_EQ(0xC2B8, irsend.capture.value);
+}
+
+// Test decode of a LG message.
+TEST(TestDecode, DecodeLG) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendLG(0x4B4AE51);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(LG, irsend.capture.decode_type);
+ EXPECT_EQ(kLgBits, irsend.capture.bits);
+ EXPECT_EQ(0x4B4AE51, irsend.capture.value);
+
+ irsend.reset();
+ irsend.sendLG(0xB4B4AE51, kLg32Bits);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(LG, irsend.capture.decode_type);
+ EXPECT_EQ(kLg32Bits, irsend.capture.bits);
+ EXPECT_EQ(0xB4B4AE51, irsend.capture.value);
+}
+
+// Test decode of a Panasonic message.
+TEST(TestDecode, DecodePanasonic) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendPanasonic64(0x40040190ED7C);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true));
+ EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
+ EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
+ EXPECT_EQ(0x40040190ED7C, irsend.capture.value);
+}
+
+// Test decode of a Samsun message.
+TEST(TestDecode, DecodeSamsung) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendSAMSUNG(0xE0E09966);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(SAMSUNG, irsend.capture.decode_type);
+ EXPECT_EQ(kSamsungBits, irsend.capture.bits);
+ EXPECT_EQ(0xE0E09966, irsend.capture.value);
+}
+
+// Test decode of a Sherwood message.
+TEST(TestDecode, DecodeSherwood) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendSherwood(0x807F40BF);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ // Sherwood codes are really NEC codes.
+ EXPECT_EQ(NEC, irsend.capture.decode_type);
+ EXPECT_EQ(kNECBits, irsend.capture.bits);
+ EXPECT_EQ(0x807F40BF, irsend.capture.value);
+}
+
+// Test decode of a Whynter message.
+TEST(TestDecode, DecodeWhynter) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendWhynter(0x87654321);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(WHYNTER, irsend.capture.decode_type);
+ EXPECT_EQ(kWhynterBits, irsend.capture.bits);
+ EXPECT_EQ(0x87654321, irsend.capture.value);
+}
+
+// Test decode of Sony messages.
+TEST(TestDecode, DecodeSony) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ // Synthesised Normal Sony 20-bit message.
+ irsend.reset();
+ irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1));
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(SONY, irsend.capture.decode_type);
+ EXPECT_EQ(kSony20Bits, irsend.capture.bits);
+ EXPECT_EQ(0x81080, irsend.capture.value);
+
+ // Synthesised Normal Sony 15-bit message.
+ irsend.reset();
+ irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(SONY, irsend.capture.decode_type);
+ EXPECT_EQ(kSony15Bits, irsend.capture.bits);
+ EXPECT_EQ(0x5480, irsend.capture.value);
+
+ // Synthesised Normal Sony 12-bit message.
+ irsend.reset();
+ irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(SONY, irsend.capture.decode_type);
+ EXPECT_EQ(kSony12Bits, irsend.capture.bits);
+ EXPECT_EQ(0xA90, irsend.capture.value);
+}
+
+// Test decode of Sharp messages.
+TEST(TestDecode, DecodeSharp) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendSharpRaw(0x454A);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(SHARP, irsend.capture.decode_type);
+ EXPECT_EQ(kSharpBits, irsend.capture.bits);
+ EXPECT_EQ(0x454A, irsend.capture.value);
+}
+
+// Test decode of Sanyo messages.
+TEST(TestDecode, DecodeSanyo) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendSanyoLC7461(0x2468DCB56A9);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type);
+ EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits);
+ EXPECT_EQ(0x2468DCB56A9, irsend.capture.value);
+}
+
+// Test decode of RC-MM messages.
+TEST(TestDecode, DecodeRCMM) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ // Normal RCMM 24-bit message.
+ irsend.reset();
+ irsend.sendRCMM(0xe0a600);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(RCMM, irsend.capture.decode_type);
+ EXPECT_EQ(kRCMMBits, irsend.capture.bits);
+ EXPECT_EQ(0xe0a600, irsend.capture.value);
+
+ // Normal RCMM 12-bit message.
+ irsend.reset();
+ irsend.sendRCMM(0x600, 12);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(RCMM, irsend.capture.decode_type);
+ EXPECT_EQ(12, irsend.capture.bits);
+ EXPECT_EQ(0x600, irsend.capture.value);
+
+ // Normal RCMM 32-bit message.
+ irsend.reset();
+ irsend.sendRCMM(0x28e0a600, 32);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(RCMM, irsend.capture.decode_type);
+ EXPECT_EQ(32, irsend.capture.bits);
+ EXPECT_EQ(0x28e0a600, irsend.capture.value);
+}
+
+// Test decode of Mitsubishi messages.
+TEST(TestDecode, DecodeMitsubishi) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendMitsubishi(0xC2B8);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type);
+ EXPECT_EQ(kMitsubishiBits, irsend.capture.bits);
+ EXPECT_EQ(0xC2B8, irsend.capture.value);
+}
+
+// Test decode of RC-5/RC-5X messages.
+TEST(TestDecode, DecodeRC5) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ // Normal RC-5 12-bit message.
+ irsend.reset();
+ irsend.sendRC5(0x175);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(RC5, irsend.capture.decode_type);
+ EXPECT_EQ(kRC5Bits, irsend.capture.bits);
+ EXPECT_EQ(0x175, irsend.capture.value);
+ // Synthesised Normal RC-5X 13-bit message.
+ irsend.reset();
+ irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(RC5X, irsend.capture.decode_type);
+ EXPECT_EQ(kRC5XBits, irsend.capture.bits);
+ EXPECT_EQ(0x1881, irsend.capture.value);
+}
+
+// Test decode of RC-6 messages.
+TEST(TestDecode, DecodeRC6) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ // Normal RC-6 Mode 0 (20-bit) message.
+ irsend.reset();
+ irsend.sendRC6(0x175);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(RC6, irsend.capture.decode_type);
+ EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits);
+ EXPECT_EQ(0x175, irsend.capture.value);
+
+ // Normal RC-6 36-bit message.
+ irsend.reset();
+ irsend.sendRC6(0xC800F742A, kRC6_36Bits);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(RC6, irsend.capture.decode_type);
+ EXPECT_EQ(kRC6_36Bits, irsend.capture.bits);
+ EXPECT_EQ(0xC800F742A, irsend.capture.value);
+}
+
+// Test decode of Dish messages.
+TEST(TestDecode, DecodeDish) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendDISH(0x9C00);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(DISH, irsend.capture.decode_type);
+ EXPECT_EQ(kDishBits, irsend.capture.bits);
+ EXPECT_EQ(0x9C00, irsend.capture.value);
+}
+
+// Test decode of Denon messages.
+TEST(TestDecode, DecodeDenon) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ // Normal Denon 15-bit message. (Sharp)
+ irsend.reset();
+ irsend.sendDenon(0x2278);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(DENON, irsend.capture.decode_type);
+ EXPECT_EQ(kDenonBits, irsend.capture.bits);
+ EXPECT_EQ(0x2278, irsend.capture.value);
+ // Legacy Denon 14-bit message.
+ irsend.reset();
+ irsend.sendDenon(0x1278, kDenonLegacyBits);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(DENON, irsend.capture.decode_type);
+ EXPECT_EQ(kDenonBits, irsend.capture.bits);
+ EXPECT_EQ(0x1278, irsend.capture.value);
+ // Normal Denon 48-bit message. (Panasonic/Kaseikyo)
+ irsend.reset();
+ irsend.sendDenon(0x2A4C028D6CE3, kDenon48Bits);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(DENON, irsend.capture.decode_type);
+ EXPECT_EQ(kDenon48Bits, irsend.capture.bits);
+ EXPECT_EQ(0x2A4C028D6CE3, irsend.capture.value);
+}
+
+// Test decode of Coolix messages.
+TEST(TestDecode, DecodeCoolix) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendCOOLIX(0x123456);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(COOLIX, irsend.capture.decode_type);
+ EXPECT_EQ(kCoolixBits, irsend.capture.bits);
+ EXPECT_EQ(0x123456, irsend.capture.value);
+}
+
+// Test decode of Aiwa messages.
+TEST(TestDecode, DecodeAiwa) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+ irsend.reset();
+ irsend.sendAiwaRCT501(0x7F);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type);
+ EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits);
+ EXPECT_EQ(0x7F, irsend.capture.value);
+}
+
+// Test matchData() on space encoded data.
+TEST(TestMatchData, SpaceEncoded) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t space_encoded_raw[11] = {500, 500, 500, 1500, 499, 499,
+ 501, 1501, 499, 1490, 500};
+ match_result_t result;
+
+ irsend.reset();
+ irsend.sendRaw(space_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 500, 1500, 500, 500);
+ ASSERT_TRUE(result.success);
+ EXPECT_EQ(0b01011, result.data);
+ EXPECT_EQ(10, result.used);
+
+ irsend.reset();
+ irsend.sendRaw(space_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 500, 1000, 500, 500);
+ ASSERT_FALSE(result.success);
+}
+
+// Test matchData() on mark encoded data.
+TEST(TestMatchData, MarkEncoded) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t mark_encoded_raw[11] = {500, 500, 1500, 500, 499, 499,
+ 1501, 501, 1499, 490, 500};
+ match_result_t result;
+
+ irsend.reset();
+ irsend.sendRaw(mark_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ // MSBF order.
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 500);
+ ASSERT_TRUE(result.success);
+ EXPECT_EQ(0b01011, result.data);
+ EXPECT_EQ(10, result.used);
+ // LSBF order.
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 500,
+ kTolerance, kMarkExcess, false);
+ ASSERT_TRUE(result.success);
+ EXPECT_EQ(0b11010, result.data); // Bits reversed of the previous test.
+ EXPECT_EQ(10, result.used);
+
+ irsend.reset();
+ irsend.sendRaw(mark_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ // MSBF order.
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 500);
+ ASSERT_FALSE(result.success);
+ // LSBF order.
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 500,
+ kTolerance, kMarkExcess, false);
+ ASSERT_FALSE(result.success);
+}
+
+// Test matchData() on "equal total bit time" encoded data.
+TEST(TestMatchData, EqualTotalBitTimeEncoded) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t equal_encoded_raw[11] = {500, 1500, 1500, 500, 499, 1499,
+ 1501, 501, 1499, 490, 500};
+ match_result_t result;
+
+ irsend.reset();
+ irsend.sendRaw(equal_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 1500);
+ ASSERT_TRUE(result.success);
+ EXPECT_EQ(0b01011, result.data);
+ EXPECT_EQ(10, result.used);
+
+ irsend.reset();
+ irsend.sendRaw(equal_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 1000);
+ ASSERT_FALSE(result.success);
+}
+
+// Test matchData() on arbitrary encoded data.
+TEST(TestMatchData, ArbitraryEncoded) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t arbitrary_encoded_raw[11] = {500, 1500, 3000, 1000, 499, 1499,
+ 3001, 1001, 2999, 990, 500};
+ match_result_t result;
+
+ irsend.reset();
+ irsend.sendRaw(arbitrary_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ result =
+ irrecv.matchData(irsend.capture.rawbuf + 1, 5, 3000, 1000, 500, 1500);
+ ASSERT_TRUE(result.success);
+ EXPECT_EQ(0b01011, result.data);
+ EXPECT_EQ(10, result.used);
+
+ irsend.reset();
+ irsend.sendRaw(arbitrary_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 1000);
+ ASSERT_FALSE(result.success);
+}
+
+TEST(TestMatchGeneric, NormalWithNoAtleast) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t good_entries_trailing_space = 12;
+ uint16_t good_trailing_space_data[good_entries_trailing_space] = {
+ 8000, // Header mark
+ 4000, // Header space
+ 500, 2000, // Bit #0 (1)
+ 500, 1000, // Bit #1 (0)
+ 500, 2000, // Bit #2 (1)
+ 500, 1000, // Bit #3 (0)
+ 3000, // Footer mark
+ 15000}; // Footer space
+
+ uint16_t good_entries_no_trailing_space = 11;
+ uint16_t good_no_trailing_space_data[good_entries_no_trailing_space] = {
+ 8000, // Header mark
+ 4000, // Header space
+ 500, 2000, // Bit #0 (1)
+ 500, 1000, // Bit #1 (0)
+ 500, 2000, // Bit #2 (1)
+ 500, 1000, // Bit #3 (0)
+ 3000}; // Footer mark (No Footer space.)
+
+ uint16_t offset = kStartOffset;
+ irsend.reset();
+ irsend.sendRaw(good_trailing_space_data, good_entries_trailing_space, 38000);
+ irsend.makeDecodeResult();
+ uint64_t result_data = 0;
+ uint16_t entries_used = 0;
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ false, // No atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b1010, result_data);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(good_entries_trailing_space, entries_used);
+
+ // Same again but with a footer space mis-match, which should fail.
+ result_data = 0;
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 30000, // Footer
+ false, // no atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Same again as first part but with no footer space data as the last entry.
+ irsend.reset();
+ result_data = 0;
+ irsend.sendRaw(good_no_trailing_space_data, good_entries_no_trailing_space,
+ 38000);
+ irsend.makeDecodeResult();
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ false, // No atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b1010, result_data);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(good_entries_no_trailing_space, entries_used);
+}
+
+
+TEST(TestMatchGeneric, NormalWithAtleast) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t good_entries_trailing_space = 12;
+ uint16_t good_trailing_space_data[good_entries_trailing_space] = {
+ 8000, // Header mark
+ 4000, // Header space
+ 500, 2000, // Bit #0 (1)
+ 500, 1000, // Bit #1 (0)
+ 500, 2000, // Bit #2 (1)
+ 500, 1000, // Bit #3 (0)
+ 3000, // Footer mark
+ 15000}; // Footer space
+
+ uint16_t good_entries_no_trailing_space = 11;
+ uint16_t good_no_trailing_space_data[good_entries_no_trailing_space] = {
+ 8000, // Header mark
+ 4000, // Header space
+ 500, 2000, // Bit #0 (1)
+ 500, 1000, // Bit #1 (0)
+ 500, 2000, // Bit #2 (1)
+ 500, 1000, // Bit #3 (0)
+ 3000}; // Footer mark (No Footer space.)
+
+ uint16_t offset = kStartOffset;
+ irsend.reset();
+ irsend.sendRaw(good_trailing_space_data, good_entries_trailing_space, 38000);
+ irsend.makeDecodeResult();
+ uint64_t result_data = 0;
+ uint16_t entries_used = 0;
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b1010, result_data);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(good_entries_trailing_space, entries_used);
+
+ // Same again but with a footer space under-match.
+ result_data = 0;
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 1500, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b1010, result_data);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(good_entries_trailing_space, entries_used);
+
+ // Same again but with a footer space under-match using less bits so the
+ // atleast footer isn't the last entry in the buffer.
+ result_data = 0;
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 3, // nbits (1 less than normal)
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 500, 500, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b101, result_data);
+ // -2 because we reduced nbits by 1.
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset - 2, entries_used);
+ EXPECT_EQ(good_entries_trailing_space - 2, entries_used);
+
+ // Same again but with a footer space over-match, which should fail.
+ result_data = 0;
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 3, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 500, 10000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Same as first part but with no footer space data as the last entry.
+ irsend.reset();
+ result_data = 0;
+ irsend.sendRaw(good_no_trailing_space_data, good_entries_no_trailing_space,
+ 38000);
+ irsend.makeDecodeResult();
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b1010, result_data);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(good_entries_no_trailing_space, entries_used);
+}
+
+TEST(TestMatchGeneric, FailureCases) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t entries = 11;
+ uint16_t data[entries] = {
+ 8000, // Header mark
+ 4000, // Header space
+ 500, 2000, // Bit #0 (1)
+ 500, 1000, // Bit #1 (0)
+ 500, 2000, // Bit #2 (1)
+ 500, 1000, // Bit #3 (0)
+ 3000}; // Footer mark (No Footer space.)
+
+ uint16_t offset = kStartOffset;
+ irsend.reset();
+ irsend.sendRaw(data, entries, 38000);
+ irsend.makeDecodeResult();
+ uint16_t entries_used = 0;
+
+ // Wanting too many bits should fail.
+ uint64_t result_data = 0;
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 5, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Bad header mark.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 2000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Bad header space.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 2000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Bad one mark.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 600, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Bad one space.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2500, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Bad zero space.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1500, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Bad zero mark.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 900, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Bad Footer mark.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 1000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Confirm it really does match as expected..
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+}
+
+TEST(TestMatchGeneric, MissingHeaderFooter) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t entries = 11;
+ uint16_t data[entries] = {
+ 8000, // Header mark
+ 4000, // Header space
+ 500, 2000, // Bit #0 (1)
+ 500, 1000, // Bit #1 (0)
+ 500, 2000, // Bit #2 (1)
+ 500, 1000, // Bit #3 (0)
+ 3000}; // Footer mark (No Footer space.)
+
+ uint16_t offset = kStartOffset;
+ irsend.reset();
+ irsend.sendRaw(data, entries, 38000);
+ irsend.makeDecodeResult();
+ uint16_t entries_used = 0;
+
+ uint64_t result_data = 0;
+
+ // No footer match
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 0, 0, // NO Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b1010, result_data);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset - 1, entries_used);
+ EXPECT_EQ(entries - 1, entries_used);
+
+ // No header match (should fail)
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 0, 0, // NO Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 0, 0, // NO Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // No header match but starting after header
+ offset += 2;
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 0, 0, // NO Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b1010, result_data);
+ EXPECT_EQ(irsend.capture.rawlen - offset, entries_used);
+ EXPECT_EQ(entries - 2, entries_used);
+}
+
+TEST(TestMatchGeneric, BitOrdering) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t entries = 11;
+ uint16_t data[entries] = {
+ 8000, // Header mark
+ 4000, // Header space
+ 500, 2000, // Bit #0 (1)
+ 500, 1000, // Bit #1 (0)
+ 500, 2000, // Bit #2 (1)
+ 500, 1000, // Bit #3 (0)
+ 3000}; // Footer mark (No Footer space.)
+
+ uint16_t offset = kStartOffset;
+ irsend.reset();
+ irsend.sendRaw(data, entries, 38000);
+ irsend.makeDecodeResult();
+ uint16_t entries_used = 0;
+
+ uint64_t result_data = 0;
+
+ // MSB order
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b1010, result_data);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(entries, entries_used);
+
+ // LSB order
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, &result_data,
+ irsend.capture.rawlen - offset,
+ 4, // nbits
+ 8000, 4000, // Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 3000, 15000, // Footer
+ true, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ false); // LSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b0101, result_data);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(entries, entries_used);
+}
+
+TEST(TestMatchGeneric, UsingBytes) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t entries = 32;
+ uint16_t data[entries] = {
+ // No header
+ 500, 2000, // Byte #0 Bit #0 (1)
+ 500, 1000, // Byte #0 Bit #1 (0)
+ 500, 2000, // Byte #0 Bit #2 (1)
+ 500, 1000, // Byte #0 Bit #3 (0)
+ 500, 2000, // Byte #0 Bit #4 (1)
+ 500, 1000, // Byte #0 Bit #5 (0)
+ 500, 2000, // Byte #0 Bit #6 (1)
+ 500, 1000, // Byte #0 Bit #7 (0)
+ 500, 2000, // Byte #1 Bit #0 (1)
+ 500, 2000, // Byte #1 Bit #1 (1)
+ 500, 2000, // Byte #1 Bit #2 (1)
+ 500, 2000, // Byte #1 Bit #3 (1)
+ 500, 1000, // Byte #1 Bit #4 (0)
+ 500, 1000, // Byte #1 Bit #5 (0)
+ 500, 1000, // Byte #1 Bit #6 (0)
+ 500, 1000}; // Byte #1 Bit #7 (0) & No footer
+
+ uint16_t offset = kStartOffset;
+ irsend.reset();
+ irsend.sendRaw(data, entries, 38000);
+ irsend.makeDecodeResult();
+ uint16_t entries_used = 0;
+
+ uint8_t result_data[4] = {}; // Bigger than we need.
+
+ // MSB order
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, result_data,
+ irsend.capture.rawlen - offset,
+ 2 * 8, // nbits
+ 0, 0, // No Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 0, 0, // No Footer
+ false, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b10101010, result_data[0]);
+ EXPECT_EQ(0b11110000, result_data[1]);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(entries, entries_used);
+
+ // LSB order
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, result_data,
+ irsend.capture.rawlen - offset,
+ 2 * 8, // nbits
+ 0, 0, // No Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 0, 0, // No Footer
+ false, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ false); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b01010101, result_data[0]);
+ EXPECT_EQ(0b00001111, result_data[1]);
+ EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(entries, entries_used);
+
+ // Asking for too much.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, result_data,
+ irsend.capture.rawlen - offset,
+ 3 * 8, // nbits
+ 0, 0, // No Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 0, 0, // No Footer
+ false, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Asking for less than what is there.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, result_data,
+ irsend.capture.rawlen - offset,
+ 1 * 8, // nbits
+ 0, 0, // No Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 0, 0, // No Footer
+ false, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_NE(0, entries_used);
+ EXPECT_EQ(0b10101010, result_data[0]);
+ EXPECT_GT(irsend.capture.rawlen - kStartOffset, entries_used);
+ EXPECT_EQ(16, entries_used);
+
+ // Asking for non mod-8 size should fail.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, result_data,
+ irsend.capture.rawlen - offset,
+ 9, // nbits
+ 0, 0, // No Header
+ 500, 2000, // one mark & space
+ 500, 1000, // zero mark & space
+ 0, 0, // No Footer
+ false, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+
+ // Expecting different timings should fail.
+ entries_used = irrecv.matchGeneric(
+ irsend.capture.rawbuf + offset, result_data,
+ irsend.capture.rawlen - offset,
+ 8, // nbits
+ 0, 0, // No Header
+ 500, 900, // one mark & space
+ 500, 1000, // zero mark & space
+ 0, 0, // No Footer
+ false, // atleast on the footer space.
+ 1, // 1% Tolerance
+ 0, // No excess margin
+ true); // MSB first.
+ ASSERT_EQ(0, entries_used);
+}
+
+TEST(TestIRrecv, Tolerance) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ uint16_t equal_encoded_raw[11] = {500, 1500, 1500, 500, 499, 1499,
+ 1501, 501, 1499, 490, 500};
+ match_result_t result;
+
+ ASSERT_EQ(kTolerance, irrecv.getTolerance());
+ irrecv.setTolerance();
+ ASSERT_EQ(kTolerance, irrecv.getTolerance());
+ irrecv.setTolerance(kTolerance + 1);
+ ASSERT_EQ(kTolerance + 1, irrecv.getTolerance());
+ irrecv.setTolerance(kTolerance - 1);
+ ASSERT_EQ(kTolerance - 1, irrecv.getTolerance());
+
+ irrecv.setTolerance();
+ ASSERT_EQ(kTolerance, irrecv.getTolerance());
+
+ irsend.reset();
+ irsend.sendRaw(equal_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 1500);
+ ASSERT_TRUE(result.success);
+ EXPECT_EQ(0b01011, result.data);
+ EXPECT_EQ(10, result.used);
+
+ irrecv.setTolerance(0);
+ ASSERT_EQ(0, irrecv.getTolerance());
+ irsend.reset();
+ irsend.sendRaw(equal_encoded_raw, 11, 38000);
+ irsend.makeDecodeResult();
+ result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 1500);
+ ASSERT_FALSE(result.success);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/IRrecv_test.h b/lib/IRremoteESP8266-2.6.5/test/IRrecv_test.h
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/IRrecv_test.h
rename to lib/IRremoteESP8266-2.6.5/test/IRrecv_test.h
diff --git a/lib/IRremoteESP8266-2.6.0/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.6.5/test/IRsend_test.cpp
similarity index 84%
rename from lib/IRremoteESP8266-2.6.0/test/IRsend_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/IRsend_test.cpp
index ffd69cf71..fbf8ba229 100644
--- a/lib/IRremoteESP8266-2.6.0/test/IRsend_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/IRsend_test.cpp
@@ -1,6 +1,7 @@
// Copyright 2017,2019 David Conran
#include "IRsend_test.h"
+#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRutils.h"
#include "gtest/gtest.h"
@@ -378,7 +379,7 @@ TEST(TestLowLevelSend, SpaceNoModulation) {
EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence);
}
-// Test expected to work/produce a message for irsend:send()
+// Test expected to work/produce a message for simple irsend:send()
TEST(TestSend, GenericSimpleSendMethod) {
IRsendTest irsend(0);
IRrecv irrecv(0);
@@ -657,7 +658,7 @@ TEST(TestSend, GenericSimpleSendMethod) {
EXPECT_EQ(0x1234, irsend.capture.value);
}
-// Test some expected types to NOT work/produce a message via irsend:send()
+// Test some expected types to NOT work/produce a message via irsend:send()
TEST(TestSend, GenericSimpleSendMethodFailure) {
IRsendTest irsend(0);
IRrecv irrecv(0);
@@ -670,17 +671,118 @@ TEST(TestSend, GenericSimpleSendMethodFailure) {
ASSERT_FALSE(irrecv.decode(&irsend.capture));
// For every A/C protocol which decodes to having a state[].
- for (int i = 0; i < 200; i++) {
+ for (int i = 0; i <= kLastDecodeType; i++) {
if (hasACState((decode_type_t)i) && i != GREE) { // Gree is an exception.
// Check it fails.
- ASSERT_FALSE(irsend.send((decode_type_t)i, 0, 0));
+ ASSERT_FALSE(irsend.send((decode_type_t)i, (uint64_t)0, 0));
}
}
// Test some other special cases.
- ASSERT_FALSE(irsend.send(UNKNOWN, 0, 0));
- ASSERT_FALSE(irsend.send(UNUSED, 0, 0));
- ASSERT_FALSE(irsend.send(RAW, 0, 0));
- ASSERT_FALSE(irsend.send(PRONTO, 0, 0));
- ASSERT_FALSE(irsend.send(GLOBALCACHE, 0, 0));
+ ASSERT_FALSE(irsend.send(UNKNOWN, (uint64_t)0, 0));
+ ASSERT_FALSE(irsend.send(UNUSED, (uint64_t)0, 0));
+ ASSERT_FALSE(irsend.send(RAW, (uint64_t)0, 0));
+ ASSERT_FALSE(irsend.send(PRONTO, (uint64_t)0, 0));
+ ASSERT_FALSE(irsend.send(GLOBALCACHE, (uint64_t)0, 0));
+}
+
+// Test expected to work/produce a message for complex irsend:send()
+TEST(TestSend, GenericComplexSendMethod) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ irsend.reset();
+ uint8_t kelvinator[kKelvinatorStateLength] = {
+ 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0,
+ 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xF0};
+ ASSERT_TRUE(irsend.send(KELVINATOR, kelvinator, kKelvinatorStateLength));
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(KELVINATOR, irsend.capture.decode_type);
+ EXPECT_EQ(kKelvinatorStateLength * 8, irsend.capture.bits);
+ EXPECT_STATE_EQ(kelvinator, irsend.capture.state, irsend.capture.bits / 8);
+
+ irsend.reset();
+ uint8_t panasonic[kPanasonicAcStateLength] = {
+ 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
+ 0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00,
+ 0x00, 0x0E, 0xE0, 0x11, 0x00, 0x01, 0x00, 0x06, 0xB7};
+ ASSERT_TRUE(irsend.send(PANASONIC_AC, panasonic, kPanasonicAcStateLength));
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(PANASONIC_AC, irsend.capture.decode_type);
+ EXPECT_EQ(kPanasonicAcStateLength * 8, irsend.capture.bits);
+ EXPECT_STATE_EQ(panasonic, irsend.capture.state, irsend.capture.bits / 8);
+}
+
+// Test some expected types to NOT work/produce a complex message via
+// irsend:send()
+TEST(TestSend, GenericComplexSendMethodFailure) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ // Check nothing is sent for unexpected protocols
+ uint8_t state[kStateSizeMax] = {};
+ irsend.reset();
+ ASSERT_FALSE(irsend.send(NEC, state, kNECBits));
+ irsend.makeDecodeResult();
+ ASSERT_FALSE(irrecv.decode(&irsend.capture));
+
+ // For every A/C protocol which DOESN'T decode to having a state[].
+ for (int i = -1; i <= kLastDecodeType; i++) {
+ if (!hasACState((decode_type_t)i))
+ // Check it fails.
+ ASSERT_FALSE(irsend.send((decode_type_t)i, state, 0));
+ else // Or if it is okay.
+ ASSERT_TRUE(irsend.send((decode_type_t)i, state, 0));
+ }
+}
+
+TEST(TestSend, GenericSendExistsForEveryRealProtocol) {
+ IRsendTest irsend(0);
+ irsend.begin();
+
+ uint8_t state[kStateSizeMax] = {};
+ uint64_t value = 0;
+ for (int i = 1; i <= kLastDecodeType; i++) {
+ switch (i) {
+ // Protocols that don't have a generic send equiv.
+ case PRONTO:
+ case RAW:
+ case GLOBALCACHE:
+ // Protocols that are disabled because they don't work.
+ case SANYO:
+ break;
+ default:
+ EXPECT_TRUE(irsend.send((decode_type_t)i, state, 0) ||
+ irsend.send((decode_type_t)i, value, 0)) <<
+ "Protocol " << typeToString((decode_type_t)i) << "(" << i <<
+ ") doesn't have a generic send option for it.";
+ }
+ }
+}
+
+TEST(TestSend, defaultBits) {
+ for (int i = 1; i <= kLastDecodeType; i++) {
+ switch (i) {
+ // Protocols that don't have have a default bit size.
+ case PRONTO:
+ case RAW:
+ case GLOBALCACHE:
+ case SANYO: // Not implemented / disabled.
+ // Deliberate no default size.
+ case FUJITSU_AC:
+ case MWM:
+ EXPECT_EQ(IRsend::defaultBits((decode_type_t)i), 0) <<
+ "Protocol " << typeToString((decode_type_t)i) << "(" << i <<
+ ") doesn't have a correct value for it.";
+ break;
+ default:
+ EXPECT_GT(IRsend::defaultBits((decode_type_t)i), 0) <<
+ "Protocol " << typeToString((decode_type_t)i) << "(" << i <<
+ ") doesn't have a correct value for it.";
+ }
+ }
}
diff --git a/lib/IRremoteESP8266-2.6.0/test/IRsend_test.h b/lib/IRremoteESP8266-2.6.5/test/IRsend_test.h
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/IRsend_test.h
rename to lib/IRremoteESP8266-2.6.5/test/IRsend_test.h
diff --git a/lib/IRremoteESP8266-2.6.0/test/IRutils_test.cpp b/lib/IRremoteESP8266-2.6.5/test/IRutils_test.cpp
similarity index 74%
rename from lib/IRremoteESP8266-2.6.0/test/IRutils_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/IRutils_test.cpp
index 4a4907649..366deba32 100644
--- a/lib/IRremoteESP8266-2.6.0/test/IRutils_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/IRutils_test.cpp
@@ -1,8 +1,9 @@
-// Copyright 2017 David Conran
+// Copyright 2017-2019 David Conran
#include "IRutils.h"
#include
#include "IRrecv.h"
+#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
@@ -403,15 +404,139 @@ TEST(TestStrToDecodeType, strToDecodeType) {
}
TEST(TestUtils, htmlEscape) {
- EXPECT_EQ("", htmlEscape(""));
- EXPECT_EQ("No Changes", htmlEscape("No Changes"));
- EXPECT_EQ("No\tChanges+_%^$@~`\n:\\", htmlEscape("No\tChanges+_%^$@~`\n:\\"));
- EXPECT_EQ(""With Changes"", htmlEscape("\"With Changes\""));
+ EXPECT_EQ("", irutils::htmlEscape(""));
+ EXPECT_EQ("No Changes", irutils::htmlEscape("No Changes"));
+ EXPECT_EQ("No\tChanges+_%^$@~`\n:\\",
+ irutils::htmlEscape("No\tChanges+_%^$@~`\n:\\"));
+ EXPECT_EQ(""With Changes"",
+ irutils::htmlEscape("\"With Changes\""));
EXPECT_EQ(
"';!‐"<>equals;&#{}"
- "()", htmlEscape("';!-\"<>={}()"));
- EXPECT_EQ("""", htmlEscape("\"\""));
+ "()", irutils::htmlEscape("';!-\"<>={}()"));
+ EXPECT_EQ("""", irutils::htmlEscape("\"\""));
EXPECT_EQ(
"";<;&apos;>;&;",
- htmlEscape(""<'>&"));
+ irutils::htmlEscape(""<'>&"));
+}
+
+TEST(TestUtils, TemperatureConversion) {
+ // Freezing point of water.
+ ASSERT_EQ(32.0, celsiusToFahrenheit(0.0));
+ ASSERT_EQ(0.0, fahrenheitToCelsius(32.0));
+ // Boiling point of water.
+ ASSERT_EQ(212.0, celsiusToFahrenheit(100.0));
+ ASSERT_EQ(100.0, fahrenheitToCelsius(212.0));
+ // Room Temp. (RTP)
+ ASSERT_EQ(77.0, celsiusToFahrenheit(25.0));
+ ASSERT_EQ(25.0, fahrenheitToCelsius(77.0));
+ // Misc
+ ASSERT_EQ(-40.0, fahrenheitToCelsius(-40.0));
+}
+
+TEST(TestResultToRawArray, TypicalCase) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ irsend.begin();
+
+ // Generate a known message.
+ irsend.reset();
+ irsend.sendNikai(0xD0F2F);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(NIKAI, irsend.capture.decode_type);
+ ASSERT_EQ(kNikaiBits, irsend.capture.bits);
+ EXPECT_EQ(
+ "uint16_t rawData[52] = {4000, 4000, 500, 2000, 500, 2000, "
+ "500, 2000, 500, 2000, 500, 1000, 500, 1000, 500, 2000, 500, 1000, "
+ "500, 2000, 500, 2000, 500, 2000, 500, 2000, 500, 1000, 500, 1000, "
+ "500, 1000, 500, 1000, 500, 2000, 500, 2000, 500, 1000, 500, 2000, "
+ "500, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 8500 };"
+ " // NIKAI D0F2F\n"
+ "uint64_t data = 0xD0F2F;\n",
+ resultToSourceCode(&irsend.capture));
+ uint16_t rawData[52] = { // Data taken from above.
+ 4000, 4000, 500, 2000, 500, 2000, 500, 2000, 500, 2000, 500, 1000, 500,
+ 1000, 500, 2000, 500, 1000, 500, 2000, 500, 2000, 500, 2000, 500, 2000,
+ 500, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 2000, 500, 2000, 500,
+ 1000, 500, 2000, 500, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 8500};
+ uint16_t * result = resultToRawArray(&irsend.capture);
+ ASSERT_EQ(52, getCorrectedRawLength(&irsend.capture));
+ EXPECT_STATE_EQ(rawData, result, getCorrectedRawLength(&irsend.capture));
+ if (result != NULL) delete[] result;
+}
+
+TEST(TestResultToRawArray, LargeValues) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(1);
+ uint16_t test_data[9] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
+ irsend.begin();
+ irsend.reset();
+ irsend.sendRaw(test_data, 9, 38000);
+ irsend.makeDecodeResult();
+ irrecv.decode(&irsend.capture);
+ uint16_t * result = resultToRawArray(&irsend.capture);
+ ASSERT_EQ(9, getCorrectedRawLength(&irsend.capture));
+ EXPECT_STATE_EQ(test_data, result, 9);
+ if (result != NULL) delete[] result;
+ // Stick in some large values.
+ irsend.capture.rawbuf[3] = 60000;
+ EXPECT_EQ(
+ "uint16_t rawData[11] = {10, 20, 65535, 0, 54465, 40, 50, 60, 70, "
+ "80, 90}; // UNKNOWN 54051FFD\n",
+ resultToSourceCode(&irsend.capture));
+ uint16_t large_test_data[11] = {
+ 10, 20, 65535, 0, 54465, 40, 50, 60, 70, 80, 90};
+ ASSERT_EQ(11, getCorrectedRawLength(&irsend.capture));
+ result = resultToRawArray(&irsend.capture);
+ EXPECT_STATE_EQ(large_test_data, result, 11);
+ if (result != NULL) delete[] result;
+}
+
+TEST(TestUtils, TypeStringConversionRangeTests) {
+ ASSERT_EQ("UNKNOWN", typeToString((decode_type_t)(kLastDecodeType + 1)));
+ ASSERT_EQ("UNKNOWN", typeToString(decode_type_t::UNKNOWN));
+ for (int i = 0; i <= kLastDecodeType; i++) {
+ EXPECT_NE("UNKNOWN", typeToString((decode_type_t)i)) << "Protocol " << i <<
+ " doesn't have a valid string for it.";
+ EXPECT_EQ(i, strToDecodeType(typeToString((decode_type_t)i).c_str())) <<
+ "Protocol " << typeToString((decode_type_t)i) <<
+ " doesn't decode from a string correctly";
+ }
+}
+
+TEST(TestUtils, MinsToString) {
+ EXPECT_EQ("00:00", irutils::minsToString(0));
+ EXPECT_EQ("00:01", irutils::minsToString(1));
+ EXPECT_EQ("00:10", irutils::minsToString(10));
+ EXPECT_EQ("00:59", irutils::minsToString(59));
+
+ EXPECT_EQ("01:00", irutils::minsToString(60));
+ EXPECT_EQ("01:01", irutils::minsToString(61));
+ EXPECT_EQ("01:59", irutils::minsToString(60 + 59));
+ EXPECT_EQ("18:59", irutils::minsToString(18 * 60 + 59));
+ EXPECT_EQ("23:59", irutils::minsToString(23 * 60 + 59));
+}
+
+TEST(TestUtils, sumNibbles) {
+ uint8_t testdata[] = {0x01, 0x23, 0x45};
+ EXPECT_EQ(0, irutils::sumNibbles(testdata, 0));
+ EXPECT_EQ(1, irutils::sumNibbles(testdata, 0, 1));
+ EXPECT_EQ(1, irutils::sumNibbles(testdata, 1));
+ EXPECT_EQ(2, irutils::sumNibbles(testdata, 1, 1));
+ EXPECT_EQ(15, irutils::sumNibbles(testdata, 3));
+ EXPECT_EQ(115, irutils::sumNibbles(testdata, 3, 100));
+}
+
+TEST(TestUtils, BCD) {
+ EXPECT_EQ(0, irutils::uint8ToBcd(0));
+ EXPECT_EQ(0, irutils::bcdToUint8(0));
+ EXPECT_EQ(1, irutils::uint8ToBcd(1));
+ EXPECT_EQ(10, irutils::bcdToUint8(0x10));
+ EXPECT_EQ(0x10, irutils::uint8ToBcd(10));
+ EXPECT_EQ(11, irutils::bcdToUint8(0x11));
+ EXPECT_EQ(0x11, irutils::uint8ToBcd(11));
+ EXPECT_EQ(99, irutils::bcdToUint8(0x99));
+ EXPECT_EQ(0x99, irutils::uint8ToBcd(99));
+ EXPECT_EQ(255, irutils::bcdToUint8(0x9A));
+ EXPECT_EQ(255, irutils::uint8ToBcd(100));
}
diff --git a/lib/IRremoteESP8266-2.6.0/test/Makefile b/lib/IRremoteESP8266-2.6.5/test/Makefile
similarity index 89%
rename from lib/IRremoteESP8266-2.6.0/test/Makefile
rename to lib/IRremoteESP8266-2.6.5/test/Makefile
index 9a64aaaaa..0e721d58c 100644
--- a/lib/IRremoteESP8266-2.6.0/test/Makefile
+++ b/lib/IRremoteESP8266-2.6.5/test/Makefile
@@ -38,7 +38,8 @@ TESTS = IRutils_test IRsend_test ir_NEC_test ir_GlobalCache_test \
ir_Carrier_test ir_Haier_test ir_Hitachi_test ir_GICable_test \
ir_Whirlpool_test ir_Lutron_test ir_Electra_test ir_Pioneer_test \
ir_MWM_test ir_Vestel_test ir_Teco_test ir_Tcl_test ir_Lego_test IRac_test \
- ir_MitsubishiHeavy_test
+ ir_MitsubishiHeavy_test ir_Trotec_test ir_Argo_test ir_Goodweather_test \
+ ir_Inax_test ir_Neoclima_test ir_Amcor_test
# All Google Test headers. Usually you shouldn't change this
# definition.
@@ -83,21 +84,27 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \
ir_Midea.o ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o \
ir_Hitachi.o ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o \
ir_Pioneer.o ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o ir_Lego.o ir_Argo.o \
- ir_Trotec.o ir_MitsubishiHeavy.o
+ ir_Trotec.o ir_MitsubishiHeavy.o ir_Goodweather.o ir_Inax.o ir_Neoclima.o \
+ ir_Amcor.o
# All the IR Protocol header files.
-PROTOCOLS_H = $(USER_DIR)/ir_Argo.h \
+PROTOCOLS_H = $(USER_DIR)/ir_Amcor.h \
+ $(USER_DIR)/ir_Argo.h \
$(USER_DIR)/ir_Gree.h \
$(USER_DIR)/ir_Magiquest.h \
$(USER_DIR)/ir_Coolix.h \
+ $(USER_DIR)/ir_Electra.h \
$(USER_DIR)/ir_Haier.h \
$(USER_DIR)/ir_Midea.h \
$(USER_DIR)/ir_Toshiba.h \
$(USER_DIR)/ir_Daikin.h \
+ $(USER_DIR)/ir_Goodweather.h \
$(USER_DIR)/ir_Kelvinator.h \
$(USER_DIR)/ir_Mitsubishi.h \
$(USER_DIR)/ir_MitsubishiHeavy.h \
$(USER_DIR)/ir_NEC.h \
+ $(USER_DIR)/ir_Neoclima.h \
+ $(USER_DIR)/ir_Sharp.h \
$(USER_DIR)/ir_Samsung.h \
$(USER_DIR)/ir_Trotec.h \
$(USER_DIR)/ir_Fujitsu.h \
@@ -106,7 +113,8 @@ PROTOCOLS_H = $(USER_DIR)/ir_Argo.h \
$(USER_DIR)/ir_Whirlpool.h \
$(USER_DIR)/ir_Vestel.h \
$(USER_DIR)/ir_Tcl.h \
- $(USER_DIR)/ir_Teco.h
+ $(USER_DIR)/ir_Teco.h \
+ $(USER_DIR)/ir_Trotec.h
# Common object files
COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o IRac.o ir_GlobalCache.o \
$(PROTOCOLS) gtest_main.a
@@ -288,7 +296,7 @@ ir_Fujitsu_test : $(COMMON_OBJ) ir_Fujitsu_test.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
ir_Sharp.o : $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sharp.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Sharp.cpp
ir_Sharp_test.o : ir_Sharp_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Sharp_test.cpp
@@ -494,8 +502,8 @@ ir_Lutron_test.o : ir_Lutron_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
ir_Lutron_test : $(COMMON_OBJ) ir_Lutron_test.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
-ir_Electra.o : $(USER_DIR)/ir_Electra.cpp $(COMMON_DEPS) $(GTEST_HEADERS)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Electra.cpp
+ir_Electra.o : $(USER_DIR)/ir_Electra.h $(USER_DIR)/ir_Electra.cpp $(COMMON_DEPS) $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Electra.cpp
ir_Electra_test.o : ir_Electra_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Electra_test.cpp
@@ -560,5 +568,53 @@ ir_Lego_test : $(COMMON_OBJ) ir_Lego_test.o
ir_Argo.o : $(USER_DIR)/ir_Argo.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Argo.cpp
+ir_Argo_test.o : ir_Argo_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Argo_test.cpp
+
+ir_Argo_test : $(COMMON_OBJ) ir_Argo_test.o
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
+
ir_Trotec.o : $(USER_DIR)/ir_Trotec.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Trotec.cpp
+
+ir_Trotec_test.o : ir_Trotec_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Trotec_test.cpp
+
+ir_Trotec_test : $(COMMON_OBJ) ir_Trotec_test.o
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
+
+ir_Goodweather.o : $(USER_DIR)/ir_Goodweather.cpp $(COMMON_DEPS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Goodweather.cpp
+
+ir_Goodweather_test.o : ir_Goodweather_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Goodweather_test.cpp
+
+ir_Goodweather_test : $(COMMON_OBJ) ir_Goodweather_test.o
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
+
+ir_Inax.o : $(USER_DIR)/ir_Inax.cpp $(COMMON_DEPS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Inax.cpp
+
+ir_Inax_test.o : ir_Inax_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Inax_test.cpp
+
+ir_Inax_test : $(COMMON_OBJ) ir_Inax_test.o
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
+
+ir_Neoclima.o : $(USER_DIR)/ir_Neoclima.h $(USER_DIR)/ir_Neoclima.cpp $(COMMON_DEPS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Neoclima.cpp
+
+ir_Neoclima_test.o : ir_Neoclima_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Neoclima_test.cpp
+
+ir_Neoclima_test : $(COMMON_OBJ) ir_Neoclima_test.o
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
+
+ir_Amcor.o : $(USER_DIR)/ir_Amcor.h $(USER_DIR)/ir_Amcor.cpp $(COMMON_DEPS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Amcor.cpp
+
+ir_Amcor_test.o : ir_Amcor_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Amcor_test.cpp
+
+ir_Amcor_test : $(COMMON_OBJ) ir_Amcor_test.o
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Aiwa_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Aiwa_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Aiwa_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Aiwa_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Amcor_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Amcor_test.cpp
new file mode 100644
index 000000000..265c61500
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Amcor_test.cpp
@@ -0,0 +1,351 @@
+// Copyright 2019 David Conran
+
+#include "IRac.h"
+#include "ir_Amcor.h"
+#include "IRrecv.h"
+#include "IRrecv_test.h"
+#include "IRsend.h"
+#include "IRsend_test.h"
+#include "IRutils.h"
+#include "gtest/gtest.h"
+
+TEST(TestUtils, Housekeeping) {
+ ASSERT_EQ("AMCOR", typeToString(decode_type_t::AMCOR));
+ ASSERT_EQ(decode_type_t::AMCOR, strToDecodeType("AMCOR"));
+ ASSERT_TRUE(hasACState(decode_type_t::AMCOR));
+ ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::AMCOR));
+}
+
+// Test sending typical data only.
+TEST(TestSendAmcor, SendDataOnly) {
+ IRsendTest irsend(0);
+ irsend.begin();
+
+ uint8_t expectedState[kAmcorStateLength] = {
+ 0x01, 0x41, 0x36, 0x00, 0x00, 0x30, 0x00, 0x12};
+
+ irsend.reset();
+ irsend.sendAmcor(expectedState);
+ EXPECT_EQ(
+ "f38000d50"
+ "m8200s4200"
+ "m1500s600m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500"
+ "m1500s600m600s1500m600s1500m600s1500m600s1500m600s1500m1500s600m600s1500"
+ "m600s1500m1500s600m1500s600m600s1500m1500s600m1500s600m600s1500m600s1500"
+ "m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500"
+ "m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500"
+ "m600s1500m600s1500m600s1500m600s1500m1500s600m1500s600m600s1500m600s1500"
+ "m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500"
+ "m600s1500m1500s600m600s1500m600s1500m1500s600m600s1500m600s1500m600s1500"
+ "m1900s34300"
+ "m8200s4200"
+ "m1500s600m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500"
+ "m1500s600m600s1500m600s1500m600s1500m600s1500m600s1500m1500s600m600s1500"
+ "m600s1500m1500s600m1500s600m600s1500m1500s600m1500s600m600s1500m600s1500"
+ "m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500"
+ "m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500"
+ "m600s1500m600s1500m600s1500m600s1500m1500s600m1500s600m600s1500m600s1500"
+ "m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500m600s1500"
+ "m600s1500m1500s600m600s1500m600s1500m1500s600m600s1500m600s1500m600s1500"
+ "m1900s34300",
+ irsend.outputStr());
+}
+
+TEST(TestDecodeAmcor, SyntheticSelfDecode) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ IRAmcorAc ac(0);
+
+ uint8_t expectedState[kAmcorStateLength] = {
+ 0x01, 0x41, 0x30, 0x00, 0x00, 0x30, 0x00, 0x0C};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendAmcor(expectedState);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(AMCOR, irsend.capture.decode_type);
+ EXPECT_EQ(kAmcorBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+ ac.setRaw(irsend.capture.state);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Fan: 4 (Auto), Temp: 24C, Max: Off",
+ ac.toString());
+}
+
+TEST(TestDecodeAmcor, RealExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ // Data from Issue #834 captured by ldellus
+ // Turn on, cooling, 27 deg C.
+ uint16_t rawData[263] = {
+ 8210, 4276, 1544, 480, 596, 1510, 596, 1510, 596, 1692, 388, 1534, 596,
+ 1510, 596, 1510, 596, 1684, 1450, 480, 596, 1510, 570, 1534, 570, 1718, 386,
+ 1536, 594, 1500, 1632, 482, 596, 1694, 362, 1550, 1632, 472, 1658, 456, 596,
+ 1684, 1474, 446, 1634, 480, 572, 1534, 572, 1718, 362, 1558, 572, 1534, 570,
+ 1534, 570, 1720, 360, 1558, 572, 1534, 570, 1534, 570, 1718, 360, 1560, 572,
+ 1534, 570, 1534, 570, 1718, 362, 1560, 572, 1532, 572, 1534, 570, 1718, 362,
+ 1558, 572, 1532, 572, 1534, 570, 1710, 1448, 472, 1634, 480, 572, 1534, 570,
+ 1718, 362, 1558, 572, 1534, 570, 1534, 572, 1716, 362, 1560, 572, 1534, 572,
+ 1534, 570, 1718, 362, 1550, 1634, 480, 570, 1536, 570, 1710, 1448, 482, 570,
+ 1534, 570, 1536, 570, 1508, 1856, 34298,
+ // rawData[132] is here. (8218)
+ 8218, 4314, 1502, 522, 530, 1576, 504, 1602, 504, 1786, 392, 1528, 504,
+ 1600, 504, 1600, 504, 1770, 1414, 522, 528, 1578, 502, 1602, 504, 1784, 394,
+ 1528, 504, 1584, 1574, 548, 528, 1762, 392, 1512, 1572, 530, 1600, 524, 528,
+ 1744, 1390, 530, 1574, 546, 506, 1600, 504, 1784, 394, 1528, 504, 1600, 578,
+ 1528, 504, 1784, 394, 1526, 504, 1600, 504, 1600, 506, 1784, 394, 1528, 504,
+ 1602, 504, 1602, 504, 1784, 394, 1526, 506, 1600, 504, 1600, 506, 1784, 392,
+ 1526, 506, 1600, 504, 1602, 502, 1768, 1390, 530, 1574, 548, 504, 1600, 504,
+ 1786, 392, 1530, 504, 1600, 504, 1600, 504, 1786, 392, 1528, 504, 1600, 504,
+ 1600, 506, 1784, 394, 1512, 1574, 548, 504, 1602, 504, 1768, 1388, 548, 504,
+ 1602, 504, 1602, 502, 1574, 1792}; // UNKNOWN D510A6EF
+
+ uint8_t expectedState[kAmcorStateLength] = {
+ 0x01, 0x41, 0x36, 0x00, 0x00, 0x30, 0x00, 0x12};
+
+ irsend.reset();
+ irsend.sendRaw(rawData, 263, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(AMCOR, irsend.capture.decode_type);
+ EXPECT_EQ(kAmcorBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+
+ // Verify the repeat is the same decode.
+ irsend.reset();
+ irsend.sendRaw(rawData + 132, 131, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(AMCOR, irsend.capture.decode_type);
+ EXPECT_EQ(kAmcorBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/834#issuecomment-515700254
+ uint16_t rawData2[263] = {8252, 4294, 1518, 508, 544, 1560, 546, 1560, 570,
+ 1718, 416, 1504, 546, 1560, 570, 1532, 572, 1718, 1414, 506, 544, 1560, 570,
+ 1534, 570, 1718, 416, 1506, 544, 1558, 1598, 508, 544, 1746, 416, 1504, 546,
+ 1560, 570, 1534, 1598, 690, 1414, 508, 544, 1560, 546, 1560, 544, 1746, 416,
+ 1504, 546, 1560, 546, 1560, 570, 1718, 416, 1504, 544, 1560, 570, 1536, 544,
+ 1744, 416, 1506, 570, 1534, 546, 1558, 546, 1744, 418, 1502, 572, 1534, 544,
+ 1560, 570, 1720, 416, 1506, 544, 1560, 546, 1560, 544, 1744, 1414, 506,
+ 1572, 534, 544, 1560, 570, 1720, 416, 1504, 570, 1536, 544, 1560, 572, 1718,
+ 416, 1504, 570, 1542, 592, 1504, 570, 1720, 416, 1502, 1572, 534, 544, 1560,
+ 572, 1718, 1414, 508, 544, 1560, 570, 1534, 570, 1508, 1840, 34174, 8230,
+ 4292, 1546, 480, 546, 1560, 572, 1534, 570, 1718, 416, 1502, 572, 1532, 572,
+ 1532, 572, 1718, 1440, 480, 570, 1534, 572, 1534, 572, 1716, 418, 1504, 572,
+ 1532, 1626, 480, 572, 1718, 418, 1502, 574, 1534, 572, 1530, 1626, 662,
+ 1442, 480, 572, 1534, 572, 1534, 572, 1716, 418, 1502, 574, 1542, 592, 1504,
+ 598, 1692, 418, 1504, 572, 1532, 574, 1530, 574, 1716, 418, 1502, 598, 1508,
+ 572, 1532, 598, 1692, 418, 1502, 598, 1508, 572, 1532, 574, 1716, 418, 1504,
+ 598, 1508, 572, 1532, 574, 1716, 1442, 478, 1626, 480, 572, 1534, 572, 1718,
+ 392, 1526, 574, 1532, 572, 1532, 572, 1716, 418, 1502, 598, 1508, 574, 1532,
+ 598, 1700, 408, 1504, 1624, 480, 572, 1532, 574, 1716, 1440, 480, 572, 1532,
+ 572, 1532, 572, 1506, 1814}; // UNKNOWN ADA838FB
+
+ uint8_t expectedState2[kAmcorStateLength] = {
+ 0x01, 0x41, 0x18, 0x00, 0x00, 0x30, 0x00, 0x12};
+
+ irsend.reset();
+ irsend.sendRaw(rawData2, 263, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(AMCOR, irsend.capture.decode_type);
+ EXPECT_EQ(kAmcorBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState2, irsend.capture.state, irsend.capture.bits);
+}
+
+// Tests for IRAmcorAc class.
+
+TEST(TestAmcorAcClass, Power) {
+ IRAmcorAc ac(0);
+ ac.begin();
+
+ ac.on();
+ EXPECT_TRUE(ac.getPower());
+
+ ac.off();
+ EXPECT_FALSE(ac.getPower());
+
+ ac.setPower(true);
+ EXPECT_TRUE(ac.getPower());
+
+ ac.setPower(false);
+ EXPECT_FALSE(ac.getPower());
+}
+
+TEST(TestAmcorAcClass, Temperature) {
+ IRAmcorAc ac(0);
+ ac.begin();
+
+ ac.setTemp(0);
+ EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
+
+ ac.setTemp(255);
+ EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
+
+ ac.setTemp(kAmcorMinTemp);
+ EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
+
+ ac.setTemp(kAmcorMaxTemp);
+ EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
+
+ ac.setTemp(kAmcorMinTemp - 1);
+ EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
+
+ ac.setTemp(kAmcorMaxTemp + 1);
+ EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
+
+ ac.setTemp(17);
+ EXPECT_EQ(17, ac.getTemp());
+
+ ac.setTemp(21);
+ EXPECT_EQ(21, ac.getTemp());
+
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+
+ ac.setTemp(29);
+ EXPECT_EQ(29, ac.getTemp());
+}
+
+TEST(TestAmcorAcClass, OperatingMode) {
+ IRAmcorAc ac(0);
+ ac.begin();
+
+ ac.setMode(kAmcorAuto);
+ EXPECT_EQ(kAmcorAuto, ac.getMode());
+
+ ac.setMode(kAmcorCool);
+ EXPECT_EQ(kAmcorCool, ac.getMode());
+
+ ac.setMode(kAmcorHeat);
+ EXPECT_EQ(kAmcorHeat, ac.getMode());
+
+ ac.setMode(kAmcorDry);
+ EXPECT_EQ(kAmcorDry, ac.getMode());
+
+ ac.setMode(kAmcorFan);
+ EXPECT_EQ(kAmcorFan, ac.getMode());
+
+ ac.setMode(kAmcorAuto + 1);
+ EXPECT_EQ(kAmcorAuto, ac.getMode());
+
+ ac.setMode(255);
+ EXPECT_EQ(kAmcorAuto, ac.getMode());
+}
+
+TEST(TestAmcorAcClass, FanSpeed) {
+ IRAmcorAc ac(0);
+ ac.begin();
+
+ ac.setFan(0);
+ EXPECT_EQ(kAmcorFanAuto, ac.getFan());
+
+ ac.setFan(255);
+ EXPECT_EQ(kAmcorFanAuto, ac.getFan());
+
+ ac.setFan(kAmcorFanMax);
+ EXPECT_EQ(kAmcorFanMax, ac.getFan());
+
+ ac.setFan(kAmcorFanMax + 1);
+ EXPECT_EQ(kAmcorFanAuto, ac.getFan());
+
+ ac.setFan(kAmcorFanMax - 1);
+ EXPECT_EQ(kAmcorFanMax - 1, ac.getFan());
+
+ ac.setFan(1);
+ EXPECT_EQ(1, ac.getFan());
+
+ ac.setFan(1);
+ EXPECT_EQ(1, ac.getFan());
+
+ ac.setFan(3);
+ EXPECT_EQ(3, ac.getFan());
+}
+
+TEST(TestAmcorAcClass, Checksums) {
+ uint8_t state[kAmcorStateLength] = {
+ 0x01, 0x41, 0x30, 0x00, 0x00, 0x30, 0x00, 0x0C};
+
+ ASSERT_EQ(0x0C, IRAmcorAc::calcChecksum(state));
+ EXPECT_TRUE(IRAmcorAc::validChecksum(state));
+ // Change the array so the checksum is invalid.
+ state[0] ^= 0xFF;
+ EXPECT_FALSE(IRAmcorAc::validChecksum(state));
+ // Restore the previous change, and change another byte.
+ state[0] ^= 0xFF;
+ state[4] ^= 0xFF;
+ EXPECT_FALSE(IRAmcorAc::validChecksum(state));
+ state[4] ^= 0xFF;
+ EXPECT_TRUE(IRAmcorAc::validChecksum(state));
+
+ // Additional known good states.
+ uint8_t knownGood1[kAmcorStateLength] = {
+ 0x01, 0x11, 0x3E, 0x00, 0x00, 0x30, 0x00, 0x17};
+ EXPECT_TRUE(IRAmcorAc::validChecksum(knownGood1));
+ ASSERT_EQ(0x17, IRAmcorAc::calcChecksum(knownGood1));
+ uint8_t knownGood2[kAmcorStateLength] = {
+ 0x01, 0x22, 0x26, 0x00, 0x00, 0x30, 0x00, 0x10};
+ EXPECT_TRUE(IRAmcorAc::validChecksum(knownGood2));
+ ASSERT_EQ(0x10, IRAmcorAc::calcChecksum(knownGood2));
+ uint8_t knownGood3[kAmcorStateLength] = {
+ 0x01, 0x41, 0x24, 0x00, 0x00, 0xC0, 0x00, 0x18};
+ EXPECT_TRUE(IRAmcorAc::validChecksum(knownGood3));
+ ASSERT_EQ(0x18, IRAmcorAc::calcChecksum(knownGood3));
+
+ // For a recalculation.
+ uint8_t knownBad[kAmcorStateLength] = {
+ // Same as knownGood3 except for the checksum.
+ 0x01, 0x41, 0x24, 0x00, 0x00, 0xC0, 0x00, 0x00};
+ EXPECT_FALSE(IRAmcorAc::validChecksum(knownBad));
+ IRAmcorAc ac(0);
+ ac.setRaw(knownBad);
+ EXPECT_STATE_EQ(knownGood3, ac.getRaw(), kAmcorBits);
+}
+
+TEST(TestAmcorAcClass, Max) {
+ IRAmcorAc ac(0);
+ ac.begin();
+
+ ac.setMode(kAmcorCool);
+ ac.setMax(true);
+ EXPECT_EQ(kAmcorCool, ac.getMode());
+ EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
+ EXPECT_TRUE(ac.getMax());
+ ac.setMax(false);
+ EXPECT_EQ(kAmcorCool, ac.getMode());
+ EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
+ EXPECT_FALSE(ac.getMax());
+
+ ac.setMode(kAmcorHeat);
+ ac.setMax(true);
+ EXPECT_EQ(kAmcorHeat, ac.getMode());
+ EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
+ EXPECT_TRUE(ac.getMax());
+ ac.setMax(false);
+ EXPECT_EQ(kAmcorHeat, ac.getMode());
+ EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
+ EXPECT_FALSE(ac.getMax());
+
+ ac.setMode(kAmcorAuto);
+ ac.setTemp(25);
+ ac.setMax(true);
+ EXPECT_EQ(kAmcorAuto, ac.getMode());
+ EXPECT_EQ(25, ac.getTemp());
+ EXPECT_FALSE(ac.getMax());
+
+ // Test known real data.
+ uint8_t lo[kAmcorStateLength] = {
+ 0x01, 0x41, 0x18, 0x00, 0x00, 0x30, 0x03, 0x15};
+ uint8_t hi[kAmcorStateLength] = {
+ 0x01, 0x12, 0x40, 0x00, 0x00, 0x30, 0x03, 0x0E};
+ ac.setRaw(lo);
+ EXPECT_EQ("Power: On, Mode: 1 (COOL), Fan: 4 (Auto), Temp: 12C, Max: On",
+ ac.toString());
+ ac.setRaw(hi);
+ EXPECT_EQ("Power: On, Mode: 2 (HEAT), Fan: 1 (Low), Temp: 32C, Max: On",
+ ac.toString());
+}
diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Argo_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Argo_test.cpp
new file mode 100644
index 000000000..7932416e0
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Argo_test.cpp
@@ -0,0 +1,221 @@
+// Copyright 2019 David Conran
+#include "ir_Argo.h"
+#include "IRrecv.h"
+#include "IRrecv_test.h"
+#include "IRsend.h"
+#include "IRsend_test.h"
+#include "gtest/gtest.h"
+
+
+TEST(TestArgoACClass, toCommon) {
+ IRArgoAC ac(0);
+ ac.setPower(true);
+ ac.setMode(kArgoCool);
+ ac.setTemp(20);
+ ac.setFan(kArgoFan3);
+ ac.setMax(true);
+ ac.setNight(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::ARGO, ac.toCommon().protocol);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(0, ac.toCommon().sleep);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ // Unsupported.
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestArgoACClass, MessageConstructon) {
+ IRArgoAC ac(0);
+ ac.setPower(true);
+ ac.setTemp(20);
+ ac.setMode(kArgoCool);
+ ac.setFan(kArgoFanAuto);
+ ac.setRoomTemp(21);
+ ac.setiFeel(true);
+ ac.setMax(true);
+ ac.setNight(true);
+
+ // Don't implicitly trust this. It's just a guess.
+ uint8_t expected[kArgoStateLength] = {
+ 0xAC, 0xF5, 0x00, 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xD6, 0x01};
+ EXPECT_STATE_EQ(expected, ac.getRaw(), kArgoBits);
+ EXPECT_EQ(
+ "Power: On, Mode: 0 (COOL), Fan: 0 (AUTO), Temp: 20C, Room Temp: 21C, "
+ "Max: On, iFeel: On, Night: On",
+ ac.toString());
+}
+
+// Tests for sendArgo().
+
+// Test sending typical data only.
+TEST(TestSendArgo, SendDataOnly) {
+ IRsendTest irsend(0);
+ irsend.begin();
+ uint8_t data[kArgoStateLength] = {
+ 0xAC, 0xF5, 0x00, 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xD6, 0x01};
+
+ irsend.sendArgo(data);
+ EXPECT_EQ(
+ "f38000d50"
+ "m6400s3300"
+ "m400s900m400s900m400s2200m400s2200m400s900m400s2200m400s900m400s2200"
+ "m400s2200m400s900m400s2200m400s900m400s2200m400s2200m400s2200m400s2200"
+ "m400s900m400s900m400s900m400s900m400s900m400s900m400s900m400s900"
+ "m400s900m400s900m400s2200m400s900m400s900m400s2200m400s900m400s900"
+ "m400s900m400s2200m400s900m400s900m400s900m400s900m400s900m400s900"
+ "m400s900m400s900m400s900m400s900m400s900m400s900m400s900m400s900"
+ "m400s900m400s900m400s900m400s900m400s900m400s900m400s900m400s900"
+ "m400s900m400s900m400s900m400s900m400s900m400s900m400s900m400s900"
+ "m400s900m400s900m400s900m400s900m400s900m400s900m400s900m400s900"
+ "m400s900m400s900m400s2200m400s2200m400s900m400s2200m400s900m400s2200"
+ "m400s900m400s2200m400s2200m400s900m400s2200m400s900m400s2200m400s2200"
+ "m400s2200m400s900m400s900m400s900m400s900m400s900m400s900"
+ "m400s900",
+ irsend.outputStr());
+}
+
+// Tests for decodeArgo().
+// Decode normal Argo messages.
+
+TEST(TestDecodeArgo, SyntheticDecode) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ // Synthesised Normal Argo message.
+ irsend.reset();
+ uint8_t expectedState[kArgoStateLength] = {
+ 0xAC, 0xF5, 0x00, 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xD6, 0x01};
+ irsend.sendArgo(expectedState);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::ARGO, irsend.capture.decode_type);
+ EXPECT_EQ(kArgoBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+}
+
+
+TEST(TestArgoACClass, SetAndGetTemp) {
+ IRArgoAC ac(0);
+
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+ ac.setTemp(kArgoMinTemp);
+ EXPECT_EQ(kArgoMinTemp, ac.getTemp());
+ ac.setTemp(kArgoMaxTemp);
+ EXPECT_EQ(kArgoMaxTemp, ac.getTemp());
+ ac.setTemp(kArgoMinTemp - 1);
+ EXPECT_EQ(kArgoMinTemp, ac.getTemp());
+ ac.setTemp(kArgoMaxTemp + 1);
+ EXPECT_EQ(kArgoMaxTemp, ac.getTemp());
+}
+
+TEST(TestArgoACClass, SetAndGetRoomTemp) {
+ IRArgoAC ac(0);
+
+ ac.setRoomTemp(25);
+ EXPECT_EQ(25, ac.getRoomTemp());
+ ac.setRoomTemp(kArgoTempOffset);
+ EXPECT_EQ(kArgoTempOffset, ac.getRoomTemp());
+ ac.setRoomTemp(kArgoMaxRoomTemp);
+ EXPECT_EQ(kArgoMaxRoomTemp, ac.getRoomTemp());
+ ac.setRoomTemp(kArgoTempOffset - 1);
+ EXPECT_EQ(kArgoTempOffset, ac.getRoomTemp());
+ ac.setRoomTemp(kArgoMaxRoomTemp + 1);
+ EXPECT_EQ(kArgoMaxRoomTemp, ac.getRoomTemp());
+}
+
+TEST(TestArgoACClass, SetAndGetMode) {
+ IRArgoAC ac(0);
+
+ ac.setMode(kArgoHeat);
+ EXPECT_EQ(kArgoHeat, ac.getMode());
+ ac.setMode(kArgoCool);
+ EXPECT_EQ(kArgoCool, ac.getMode());
+ ac.setMode(kArgoDry);
+ EXPECT_EQ(kArgoDry, ac.getMode());
+ ac.setMode(kArgoAuto);
+ EXPECT_EQ(kArgoAuto, ac.getMode());
+ ac.setMode(kArgoHeatAuto);
+ EXPECT_EQ(kArgoHeatAuto, ac.getMode());
+ ac.setMode(kArgoOff);
+ EXPECT_EQ(kArgoOff, ac.getMode());
+ ac.setMode(255);
+ EXPECT_EQ(kArgoAuto, ac.getMode());
+}
+
+TEST(TestArgoACClass, SetAndGetFan) {
+ IRArgoAC ac(0);
+
+ ac.setFan(kArgoFan3);
+ EXPECT_EQ(kArgoFan3, ac.getFan());
+ ac.setFan(kArgoFan1);
+ EXPECT_EQ(kArgoFan1, ac.getFan());
+ ac.setFan(kArgoFanAuto);
+ EXPECT_EQ(kArgoFanAuto, ac.getFan());
+ ac.setFan(kArgoFan3);
+ EXPECT_EQ(kArgoFan3, ac.getFan());
+ ASSERT_NE(7, kArgoFan3);
+ // Now try some unexpected value.
+ ac.setFan(7);
+ EXPECT_EQ(kArgoFan3, ac.getFan());
+}
+
+TEST(TestArgoACClass, Night) {
+ IRArgoAC ac(0);
+ ac.setNight(false);
+ ASSERT_FALSE(ac.getNight());
+ ac.setNight(true);
+ ASSERT_TRUE(ac.getNight());
+ ac.setNight(false);
+ ASSERT_FALSE(ac.getNight());
+}
+
+TEST(TestArgoACClass, iFeel) {
+ IRArgoAC ac(0);
+ ac.setiFeel(false);
+ ASSERT_FALSE(ac.getiFeel());
+ ac.setiFeel(true);
+ ASSERT_TRUE(ac.getiFeel());
+ ac.setiFeel(false);
+ ASSERT_FALSE(ac.getiFeel());
+}
+
+TEST(TestArgoACClass, Power) {
+ IRArgoAC ac(0);
+ ac.setPower(false);
+ ASSERT_FALSE(ac.getPower());
+ ac.setPower(true);
+ ASSERT_TRUE(ac.getPower());
+ ac.setPower(false);
+ ASSERT_FALSE(ac.getPower());
+}
+
+TEST(TestArgoACClass, Max) {
+ IRArgoAC ac(0);
+ ac.setMax(false);
+ ASSERT_FALSE(ac.getMax());
+ ac.setMax(true);
+ ASSERT_TRUE(ac.getMax());
+ ac.setMax(false);
+ ASSERT_FALSE(ac.getMax());
+}
+
+TEST(TestUtils, Housekeeping) {
+ ASSERT_EQ("ARGO", typeToString(decode_type_t::ARGO));
+ ASSERT_EQ(decode_type_t::ARGO, strToDecodeType("ARGO"));
+ ASSERT_TRUE(hasACState(decode_type_t::ARGO));
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Carrier_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Carrier_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Carrier_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Carrier_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Coolix_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Coolix_test.cpp
similarity index 79%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Coolix_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Coolix_test.cpp
index 0f97c5ead..618d825a0 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Coolix_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Coolix_test.cpp
@@ -31,7 +31,7 @@ TEST(TestSendCoolix, SendDataOnly) {
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
- "m560s5040",
+ "m560s105040",
irsend.outputStr());
irsend.reset();
@@ -53,7 +53,7 @@ TEST(TestSendCoolix, SendDataOnly) {
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680"
- "m560s5040",
+ "m560s105040",
irsend.outputStr());
irsend.reset();
@@ -75,7 +75,7 @@ TEST(TestSendCoolix, SendDataOnly) {
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s5040",
+ "m560s105040",
irsend.outputStr());
}
@@ -103,7 +103,7 @@ TEST(TestSendCoolix, SendWithRepeats) {
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680"
- "m560s5040",
+ "m560s105040",
irsend.outputStr());
irsend.sendCOOLIX(0xAA55AA, kCoolixBits, 2); // 2 repeats.
EXPECT_EQ(
@@ -131,7 +131,7 @@ TEST(TestSendCoolix, SendWithRepeats) {
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680"
- "m560s5040",
+ "m560s105040",
irsend.outputStr());
}
@@ -151,7 +151,7 @@ TEST(TestSendCoolix, SendUnusualSize) {
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
- "m560s5040",
+ "m560s105040",
irsend.outputStr());
irsend.reset();
@@ -193,7 +193,7 @@ TEST(TestSendCoolix, SendUnusualSize) {
"m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560"
"m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560"
- "m560s5040",
+ "m560s105040",
irsend.outputStr());
// Bit sizes must be a multiple of 8.
@@ -395,6 +395,8 @@ TEST(TestCoolixACClass, SetAndGetMode) {
TEST(TestCoolixACClass, SetAndGetFan) {
IRCoolixAC ircoolix(0);
+ // This mode allows pretty much everything except Auto0 speed.
+ ircoolix.setMode(kCoolixCool);
ircoolix.setFan(kCoolixFanMax);
EXPECT_EQ(kCoolixFanMax, ircoolix.getFan());
ircoolix.setFan(kCoolixFanMin);
@@ -403,12 +405,29 @@ TEST(TestCoolixACClass, SetAndGetFan) {
EXPECT_EQ(kCoolixFanZoneFollow, ircoolix.getFan());
ircoolix.setFan(kCoolixFanAuto);
EXPECT_EQ(kCoolixFanAuto, ircoolix.getFan());
+ ircoolix.setFan(kCoolixFanAuto0);
+ EXPECT_EQ(kCoolixFanAuto, ircoolix.getFan());
ircoolix.setFan(kCoolixFanMax);
EXPECT_EQ(kCoolixFanMax, ircoolix.getFan());
ASSERT_NE(3, kCoolixFanAuto);
// Now try some unexpected value.
ircoolix.setFan(3);
EXPECT_EQ(kCoolixFanAuto, ircoolix.getFan());
+
+ // These modes allows pretty much everything except Auto speed.
+ ircoolix.setMode(kCoolixDry);
+ EXPECT_EQ(kCoolixFanAuto0, ircoolix.getFan());
+ ircoolix.setFan(kCoolixFanMax);
+ EXPECT_EQ(kCoolixFanMax, ircoolix.getFan());
+ ircoolix.setFan(kCoolixFanAuto);
+ EXPECT_EQ(kCoolixFanAuto0, ircoolix.getFan());
+
+ ircoolix.setMode(kCoolixAuto);
+ EXPECT_EQ(kCoolixFanAuto0, ircoolix.getFan());
+ ircoolix.setFan(kCoolixFanMax);
+ EXPECT_EQ(kCoolixFanMax, ircoolix.getFan());
+ ircoolix.setFan(kCoolixFanAuto0);
+ EXPECT_EQ(kCoolixFanAuto0, ircoolix.getFan());
}
TEST(TestCoolixACClass, SetGetClearSensorTempAndZoneFollow) {
@@ -547,7 +566,7 @@ TEST(TestCoolixACClass, RealCaptureExample) {
// Tests to debug/fix:
-// https://github.com/markszabo/IRremoteESP8266/issues/624
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/624
TEST(TestCoolixACClass, Issue624HandleSpecialStatesBetter) {
IRCoolixAC ac(0);
ac.begin();
@@ -597,3 +616,132 @@ TEST(TestCoolixACClass, Issue624HandleSpecialStatesBetter) {
ac.toString());
EXPECT_EQ(0xB2BF40, ac.getRaw());
}
+
+TEST(TestCoolixACClass, toCommon) {
+ IRCoolixAC ac(0);
+ ac.setPower(true);
+ ac.setMode(kCoolixCool);
+ ac.setTemp(20);
+ ac.setFan(kCoolixFanMax);
+
+ // Now test it.
+ ASSERT_EQ(decode_type_t::COOLIX, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestCoolixACClass, Issue722) {
+ IRrecv irrecv(0);
+ IRCoolixAC ac(0);
+
+ // Auto 17C ON pressed
+ uint32_t on_auto_17c_fan_auto0 = 0xB21F08;
+ ac.begin();
+ ac.setPower(true);
+ ac.setMode(kCoolixAuto);
+ ac.setFan(kCoolixFanAuto);
+ ac.setTemp(17);
+ EXPECT_EQ(on_auto_17c_fan_auto0, ac.getRaw());
+
+ // Off
+ uint32_t off = 0xB27BE0;
+ ac.off();
+ EXPECT_EQ(off, ac.getRaw());
+
+ // ON Auto Temp 18C
+ uint32_t on_auto_18c_fan_auto0 = 0xB21F18;
+ ac.setTemp(18);
+ EXPECT_EQ(on_auto_18c_fan_auto0, ac.getRaw());
+
+ // Set Mode Cool 18C
+ uint32_t on_cool_18c_fan_auto = 0xB2BF10;
+ ac.setMode(kCoolixCool);
+ EXPECT_EQ(on_cool_18c_fan_auto, ac.getRaw());
+
+ // Set Mode DRY 18C
+ uint32_t on_dry_18c_fan_auto0 = 0xB21F14;
+ ac.setMode(kCoolixDry);
+ EXPECT_EQ(on_dry_18c_fan_auto0, ac.getRaw());
+
+ // Set Mode HEAT 18C
+ uint32_t on_heat_18c_fan_auto = 0xB2BF1C;
+ ac.setMode(kCoolixHeat);
+ EXPECT_EQ(on_heat_18c_fan_auto, ac.getRaw());
+
+ // Set mode FAN
+ uint32_t on_fan_18c_fan_auto = 0xB2BFE4;
+ ac.setMode(kCoolixFan);
+ EXPECT_EQ(on_fan_18c_fan_auto, ac.getRaw());
+
+ // Fan level 2 (initial was auto)
+ uint32_t on_fan_18c_fan_min = 0xB29FE4;
+ ac.setFan(kCoolixFanMin);
+ EXPECT_EQ(on_fan_18c_fan_min, ac.getRaw());
+
+ // Fan level 3
+ uint32_t on_fan_18c_fan_med = 0xB25FE4;
+ ac.setFan(kCoolixFanMed);
+ EXPECT_EQ(on_fan_18c_fan_med, ac.getRaw());
+
+ // Fan level 4
+ uint32_t on_fan_18c_fan_max = 0xB23FE4;
+ ac.setFan(kCoolixFanMax);
+ EXPECT_EQ(on_fan_18c_fan_max, ac.getRaw());
+
+ // Test sending the last message to verify the class send() method works.
+ ac.send();
+ ac._irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&ac._irsend.capture));
+ EXPECT_EQ(COOLIX, ac._irsend.capture.decode_type);
+ EXPECT_EQ(kCoolixBits, ac._irsend.capture.bits);
+ EXPECT_EQ(on_fan_18c_fan_max, ac._irsend.capture.value);
+ EXPECT_EQ(0x0, ac._irsend.capture.address);
+ EXPECT_EQ(0x0, ac._irsend.capture.command);
+ EXPECT_EQ(
+ // Raw data supplied by @mariusmotea
+ "f38000d50"
+ // 4434,4376,
+ "m4480s4480"
+ // 566,1614,592,504,566,1618,566,1616,568,528,564,532,564,1616,568,532,
+ "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560"
+ // 566,530,566,1620,568,528,566,530,566,1618,564,1618,566,530,564,1624,
+ "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680"
+ // 538,560,566,530,564,1620,566,1618,566,1618,566,1616,566,1616,566,1620,
+ "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
+ // 568,1620,566,1616,566,530,566,530,564,530,562,532,564,530,566,530,
+ "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560"
+ // 566,1622,566,1616,540,1642,566,528,566,530,566,1616,566,530,566,532,
+ "m560s1680m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s560"
+ // 564,532,564,530,566,530,566,1614,566,1616,562,532,564,1620,566,1618,
+ "m560s560m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s1680"
+ // 538,5254,4432,4364,566,1616,568,530,564,1620,568,1616,564,532,564,530,
+ "m560s5040m4480s4480m560s1680m560s560m560s1680m560s1680m560s560m560s560"
+ // 566,1616,566,532,564,532,566,1620,568,528,566,530,566,1616,564,1618,
+ "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680"
+ // 566,530,566,1622,566,532,566,528,566,1620,568,1614,566,1618,566,1618,
+ "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680"
+ // 566,1614,568,1618,566,1622,568,1616,566,530,564,530,566,530,566,528,
+ "m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560"
+ // 564,530,566,532,566,1622,564,1616,566,1616,564,532,564,530,564,1616,
+ "m560s560m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s1680"
+ // 564,530,564,532,566,530,564,530,566,528,564,1618,564,1618,564,532,
+ "m560s560m560s560m560s560m560s560m560s560m560s1680m560s1680m560s560"
+ // 564,1620,566,1618,562 // Raw data matches what is expected.
+ "m560s1680m560s1680m560s105040", ac._irsend.outputStr());
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Daikin_test.cpp
similarity index 62%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Daikin_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Daikin_test.cpp
index 67d144d54..774109c3a 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Daikin_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Daikin_test.cpp
@@ -1,5 +1,6 @@
-// Copyright 2017 David Conran
+// Copyright 2017-2019 David Conran
#include "ir_Daikin.h"
+#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
@@ -540,33 +541,47 @@ TEST(TestDaikinClass, OnOffTimers) {
ASSERT_FALSE(ac.getPowerful());
}
-// Test Eye mode.
-TEST(TestDaikinClass, EyeSetting) {
+TEST(TestDaikinClass, WeeklyTimerEnable) {
IRDaikinESP ac(0);
ac.begin();
- // The Eye setting is stored in the same byte as Econo mode.
+ // The Weekly Timer Enabled flag is stored in the same byte as Econo mode.
// Econo mode tests are there to make sure it isn't harmed and vice-versa.
ac.setEcono(false);
- ac.setEye(false);
- ASSERT_FALSE(ac.getEye());
+ ac.setWeeklyTimerEnable(false);
+ ASSERT_FALSE(ac.getWeeklyTimerEnable());
EXPECT_FALSE(ac.getEcono());
- ac.setEye(true);
- ASSERT_TRUE(ac.getEye());
+ ac.setWeeklyTimerEnable(true);
+ ASSERT_TRUE(ac.getWeeklyTimerEnable());
EXPECT_FALSE(ac.getEcono());
ac.setEcono(false);
- ASSERT_TRUE(ac.getEye());
+ ASSERT_TRUE(ac.getWeeklyTimerEnable());
EXPECT_FALSE(ac.getEcono());
ac.setEcono(true);
- ASSERT_TRUE(ac.getEye());
+ ASSERT_TRUE(ac.getWeeklyTimerEnable());
EXPECT_TRUE(ac.getEcono());
- ac.setEye(false);
- ASSERT_FALSE(ac.getEye());
+ ac.setWeeklyTimerEnable(false);
+ ASSERT_FALSE(ac.getWeeklyTimerEnable());
EXPECT_TRUE(ac.getEcono());
+
+ // Tests with real data from:
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/704#issuecomment-493731421
+ uint8_t on[kDaikinStateLength] = {
+ 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, 0x11, 0xDA, 0x27, 0x00,
+ 0x42, 0xE3, 0x0B, 0x42, 0x11, 0xDA, 0x27, 0x00, 0x00, 0x68, 0x32, 0x00,
+ 0x30, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x03};
+ uint8_t off[kDaikinStateLength] = {
+ 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, 0x11, 0xDA, 0x27, 0x00,
+ 0x42, 0xE3, 0x0B, 0x42, 0x11, 0xDA, 0x27, 0x00, 0x00, 0x68, 0x32, 0x00,
+ 0x30, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x80, 0x00, 0x83};
+ ac.setRaw(on);
+ EXPECT_TRUE(ac.getWeeklyTimerEnable());
+ ac.setRaw(off);
+ EXPECT_FALSE(ac.getWeeklyTimerEnable());
}
// Test Mold mode.
@@ -614,13 +629,6 @@ TEST(TestDaikinClass, SensorSetting) {
ASSERT_FALSE(ac.getSensor());
}
-TEST(TestDaikinClass, RenderTime) {
- EXPECT_EQ("0:00", IRDaikinESP::renderTime(0));
- EXPECT_EQ("0:10", IRDaikinESP::renderTime(10));
- EXPECT_EQ("1:00", IRDaikinESP::renderTime(1 * 60 + 0));
- EXPECT_EQ("23:59", IRDaikinESP::renderTime(23 * 60 + 59));
-}
-
TEST(TestDaikinClass, SetAndGetRaw) {
IRDaikinESP ac(0);
uint8_t shortState[kDaikinStateLengthShort] = {
@@ -683,30 +691,33 @@ TEST(TestDaikinClass, HumanReadable) {
IRDaikinESP ac(0);
EXPECT_EQ(
- "Power: On, Mode: 4 (HEAT), Temp: 15C, Fan: 11 (QUIET), "
- "Powerful: Off, Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, "
+ "Power: On, Mode: 4 (HEAT), Temp: 15C, Fan: 11 (Quiet), "
+ "Powerful: Off, Quiet: Off, Sensor: Off, Mold: Off, "
"Comfort: Off, Swing (Horizontal): Off, Swing (Vertical): Off, "
- "Current Time: 0:00, On Time: Off, Off Time: Off",
+ "Current Time: 00:00, Current Day: (UNKNOWN), On Time: Off, "
+ "Off Time: Off, Weekly Timer: On",
ac.toString());
ac.setMode(kDaikinAuto);
ac.setTemp(25);
ac.setFan(kDaikinFanAuto);
ac.setQuiet(true);
ac.setSensor(true);
- ac.setEye(true);
ac.setMold(true);
ac.setSwingVertical(true);
ac.setSwingHorizontal(true);
ac.setCurrentTime(9 * 60 + 15);
+ ac.setCurrentDay(4);
ac.enableOnTimer(8 * 60 + 0);
ac.enableOffTimer(17 * 60 + 30);
ac.setComfort(true);
+ ac.setWeeklyTimerEnable(false);
ac.off();
EXPECT_EQ(
- "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 10 (AUTO), "
- "Powerful: Off, Quiet: On, Sensor: On, Eye: On, Mold: On, Comfort: On, "
+ "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 10 (Auto), "
+ "Powerful: Off, Quiet: On, Sensor: On, Mold: On, Comfort: On, "
"Swing (Horizontal): On, Swing (Vertical): On, "
- "Current Time: 9:15, On Time: 8:00, Off Time: 17:30",
+ "Current Time: 09:15, Current Day: WED, On Time: 08:00, Off Time: 17:30, "
+ "Weekly Timer: Off",
ac.toString());
}
@@ -855,10 +866,11 @@ TEST(TestDecodeDaikin, RealExample) {
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (AUTO), Powerful: On, "
- "Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, Comfort: Off, "
+ "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (Auto), Powerful: On, "
+ "Quiet: Off, Sensor: Off, Mold: Off, Comfort: Off, "
"Swing (Horizontal): Off, Swing (Vertical): Off, "
- "Current Time: 22:18, On Time: 21:30, Off Time: 6:10", ac.toString());
+ "Current Time: 22:18, Current Day: (UNKNOWN), "
+ "On Time: 21:30, Off Time: 06:10, Weekly Timer: On", ac.toString());
}
// Decoding a message we entirely constructed based solely on a given state.
@@ -887,10 +899,11 @@ TEST(TestDecodeDaikin, ShortSyntheticExample) {
EXPECT_STATE_EQ(longState, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (AUTO), Powerful: On, "
- "Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, Comfort: Off, "
+ "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (Auto), Powerful: On, "
+ "Quiet: Off, Sensor: Off, Mold: Off, Comfort: Off, "
"Swing (Horizontal): Off, Swing (Vertical): Off, "
- "Current Time: 22:18, On Time: 21:30, Off Time: 6:10", ac.toString());
+ "Current Time: 22:18, Current Day: (UNKNOWN), "
+ "On Time: 21:30, Off Time: 06:10, Weekly Timer: On", ac.toString());
}
// Decoding a message we entirely constructed based solely on a given state.
@@ -915,10 +928,11 @@ TEST(TestDecodeDaikin, LongSyntheticExample) {
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (AUTO), Powerful: On, "
- "Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, Comfort: Off, "
+ "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (Auto), Powerful: On, "
+ "Quiet: Off, Sensor: Off, Mold: Off, Comfort: Off, "
"Swing (Horizontal): Off, Swing (Vertical): Off, "
- "Current Time: 22:18, On Time: 21:30, Off Time: 6:10", ac.toString());
+ "Current Time: 22:18, Current Day: (UNKNOWN), "
+ "On Time: 21:30, Off Time: 06:10, Weekly Timer: On", ac.toString());
}
// Test decoding a message captured from a real IR remote.
@@ -932,7 +946,7 @@ TEST(TestDecodeDaikin2, RealExample) {
0x80, 0x04, 0xB0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xD5, 0xF5,
0x11, 0xDA, 0x27, 0x00, 0x00, 0x08, 0x26, 0x00, 0xA0, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x80, 0x60, 0xE7};
- // "Off" Data from https://github.com/markszabo/IRremoteESP8266/issues/582
+ // "Off" Data from https://github.com/crankyoldgit/IRremoteESP8266/issues/582
uint16_t rawData[633] = { // Data supplied by @sheppy99
10024, 25180, 3494, 1732, 436, 1300, 436, 436, 432, 438, 430, 438,
426, 1306, 430, 442, 430, 438, 428, 440, 430, 440, 430, 1304,
@@ -1428,9 +1442,9 @@ TEST(TestDaikin2Class, HumanReadable) {
ac.setPurify(true);
ac.setEcono(false);
EXPECT_EQ(
- "Power: On, Mode: 3 (COOL), Temp: 21C, Fan: 5 (Max), "
+ "Power: On, Mode: 3 (COOL), Temp: 21C, Fan: 5 (High), "
"Swing (V): 14 (Auto), Swing (H): 191 (Swing), Clock: 12:34, "
- "On Time: Off, Off Time: 20:00, Sleep Time: 4:00, Beep: 2 (Loud), "
+ "On Time: Off, Off Time: 20:00, Sleep Time: 04:00, Beep: 2 (Loud), "
"Light: 2 (Dim), Mold: On, Clean: Off, Fresh Air: On, Eye: On, "
"Eye Auto: On, Quiet: Off, Powerful: On, Purify: On, Econo: Off",
ac.toString());
@@ -1443,9 +1457,9 @@ TEST(TestDaikin2Class, HumanReadable) {
ac.setCurrentTime(23 * 60 + 45); // 23:45
ac.enableOnTimer(9 * 60 + 11); // 9:11
EXPECT_EQ(
- "Power: On, Mode: 4 (HEAT), Temp: 32C, Fan: 1 (Min), "
+ "Power: On, Mode: 4 (HEAT), Temp: 32C, Fan: 1 (Low), "
"Swing (V): 14 (Auto), Swing (H): 191 (Swing), Clock: 23:45, "
- "On Time: 9:11, Off Time: 20:00, Sleep Time: Off, Beep: 1 (Quiet), "
+ "On Time: 09:11, Off Time: 20:00, Sleep Time: Off, Beep: 1 (Quiet), "
"Light: 1 (Bright), Mold: On, Clean: Off, Fresh Air: On, Eye: On, "
"Eye Auto: On, Quiet: On, Powerful: Off, Purify: On, Econo: Off",
ac.toString());
@@ -1498,17 +1512,40 @@ TEST(TestUtils, Housekeeping) {
ASSERT_EQ("DAIKIN", typeToString(decode_type_t::DAIKIN));
ASSERT_EQ(decode_type_t::DAIKIN, strToDecodeType("DAIKIN"));
ASSERT_TRUE(hasACState(decode_type_t::DAIKIN));
+ ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::DAIKIN));
+
+ ASSERT_EQ("DAIKIN128", typeToString(decode_type_t::DAIKIN128));
+ ASSERT_EQ(decode_type_t::DAIKIN128, strToDecodeType("DAIKIN128"));
+ ASSERT_TRUE(hasACState(decode_type_t::DAIKIN128));
+ ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::DAIKIN128));
+
+ ASSERT_EQ("DAIKIN152", typeToString(decode_type_t::DAIKIN152));
+ ASSERT_EQ(decode_type_t::DAIKIN152, strToDecodeType("DAIKIN152"));
+ ASSERT_TRUE(hasACState(decode_type_t::DAIKIN152));
+ ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::DAIKIN152));
+
+ ASSERT_EQ("DAIKIN160", typeToString(decode_type_t::DAIKIN160));
+ ASSERT_EQ(decode_type_t::DAIKIN160, strToDecodeType("DAIKIN160"));
+ ASSERT_TRUE(hasACState(decode_type_t::DAIKIN160));
+ ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::DAIKIN160));
+
+ ASSERT_EQ("DAIKIN176", typeToString(decode_type_t::DAIKIN176));
+ ASSERT_EQ(decode_type_t::DAIKIN176, strToDecodeType("DAIKIN176"));
+ ASSERT_TRUE(hasACState(decode_type_t::DAIKIN176));
+ ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::DAIKIN176));
ASSERT_EQ("DAIKIN2", typeToString(decode_type_t::DAIKIN2));
ASSERT_EQ(decode_type_t::DAIKIN2, strToDecodeType("DAIKIN2"));
ASSERT_TRUE(hasACState(decode_type_t::DAIKIN2));
+ ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::DAIKIN2));
ASSERT_EQ("DAIKIN216", typeToString(decode_type_t::DAIKIN216));
ASSERT_EQ(decode_type_t::DAIKIN216, strToDecodeType("DAIKIN216"));
ASSERT_TRUE(hasACState(decode_type_t::DAIKIN216));
+ ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::DAIKIN216));
}
-// https://github.com/markszabo/IRremoteESP8266/issues/582#issuecomment-453863879
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/582#issuecomment-453863879
TEST(TestDecodeDaikin2, Issue582DeepDecodeExample) {
IRDaikin2 ac(0);
@@ -1524,10 +1561,10 @@ TEST(TestDecodeDaikin2, Issue582DeepDecodeExample) {
ASSERT_TRUE(ac.getPurify());
EXPECT_EQ(
"Power: On, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), "
- "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 9:20, On Time: Off, "
- "Off Time: Off, Sleep Time: Off, Beep: 3 (Off), Light: 3 (Off), "
- "Mold: On, Clean: On, Fresh Air: Off, Eye: On, Eye Auto: Off, "
- "Quiet: Off, Powerful: Off, Purify: On, Econo: Off",
+ "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 09:20, "
+ "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), "
+ "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: On, "
+ "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off",
ac.toString());
}
@@ -1677,7 +1714,6 @@ TEST(TestDaikin216Class, OperatingMode) {
EXPECT_EQ(kDaikinAuto, ac.getMode());
}
-
TEST(TestDaikin216Class, VaneSwing) {
IRDaikin216 ac(0);
ac.begin();
@@ -1744,15 +1780,34 @@ TEST(TestDaikin216Class, FanSpeed) {
EXPECT_EQ(kDaikinFanQuiet, ac.getFan());
}
-TEST(TestDaikin216Class, Quiet) {
+TEST(TestDaikin216Class, QuietAndPowerful) {
IRDaikin216 ac(0);
ac.begin();
+ ac.setQuiet(false);
+ ac.setPowerful(false);
+ EXPECT_FALSE(ac.getQuiet());
+ EXPECT_FALSE(ac.getPowerful());
+
ac.setQuiet(true);
EXPECT_TRUE(ac.getQuiet());
+ EXPECT_FALSE(ac.getPowerful());
+
+ ac.setPowerful(true);
+ EXPECT_FALSE(ac.getQuiet());
+ EXPECT_TRUE(ac.getPowerful());
+
+ ac.setQuiet(true);
+ EXPECT_TRUE(ac.getQuiet());
+ EXPECT_FALSE(ac.getPowerful());
ac.setQuiet(false);
EXPECT_FALSE(ac.getQuiet());
+ EXPECT_FALSE(ac.getPowerful());
+
+ ac.setPowerful(true);
+ EXPECT_FALSE(ac.getQuiet());
+ EXPECT_TRUE(ac.getPowerful());
ac.setQuiet(true);
EXPECT_TRUE(ac.getQuiet());
@@ -1761,22 +1816,23 @@ TEST(TestDaikin216Class, Quiet) {
TEST(TestDaikin216Class, ExampleStates) {
IRDaikin216 ac(0);
ac.begin();
- // https://github.com/markszabo/IRremoteESP8266/pull/690#issuecomment-487770194
+ // https://github.com/crankyoldgit/IRremoteESP8266/pull/690#issuecomment-487770194
uint8_t state[kDaikin216StateLength] = {
0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02,
0x11, 0xDA, 0x27, 0x00, 0x00, 0x21, 0xC0, 0x00, 0xA0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x53};
ac.setRaw(state);
EXPECT_EQ(
- "Power: On, Mode: 2 (DRY), Temp: 32C, Fan: 10 (AUTO), "
- "Swing (Horizontal): Off, Swing (Vertical): Off, Quiet: Off",
+ "Power: On, Mode: 2 (DRY), Temp: 32C, Fan: 10 (Auto), "
+ "Swing (Horizontal): Off, Swing (Vertical): Off, "
+ "Quiet: Off, Powerful: Off",
ac.toString());
}
TEST(TestDaikin216Class, ReconstructKnownState) {
IRDaikin216 ac(0);
ac.begin();
- // https://github.com/markszabo/IRremoteESP8266/issues/689#issue-438086949
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/689#issue-438086949
uint8_t expectedState[kDaikin216StateLength] = {
0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02,
0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0xA0, 0x00,
@@ -1789,18 +1845,19 @@ TEST(TestDaikin216Class, ReconstructKnownState) {
ac.setSwingVertical(false);
ac.setQuiet(false);
EXPECT_EQ(
- "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (AUTO), "
- "Swing (Horizontal): Off, Swing (Vertical): Off, Quiet: Off",
+ "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), "
+ "Swing (Horizontal): Off, Swing (Vertical): Off, "
+ "Quiet: Off, Powerful: Off",
ac.toString());
EXPECT_STATE_EQ(expectedState, ac.getRaw(), kDaikin216Bits);
}
-// https://github.com/markszabo/IRremoteESP8266/issues/689
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/689
TEST(TestDecodeDaikin216, RealExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
- // https://github.com/markszabo/IRremoteESP8266/issues/689#issue-438086949
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/689#issue-438086949
uint16_t rawData[439] = {
3402, 1770, 382, 1340, 382, 480, 382, 478, 382, 480, 380, 1342, 382, 478,
356, 504, 382, 480, 380, 478, 384, 1342, 380, 480, 380, 1342, 382, 1342,
@@ -1852,16 +1909,17 @@ TEST(TestDecodeDaikin216, RealExample) {
IRDaikin216 ac(0);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (AUTO), "
- "Swing (Horizontal): Off, Swing (Vertical): Off, Quiet: Off",
+ "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), "
+ "Swing (Horizontal): Off, Swing (Vertical): Off, "
+ "Quiet: Off, Powerful: Off",
ac.toString());
}
-// https://github.com/markszabo/IRremoteESP8266/issues/689
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/689
TEST(TestDecodeDaikin216, SyntheticExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
- // https://github.com/markszabo/IRremoteESP8266/issues/689#issue-438086949
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/689#issue-438086949
uint8_t expectedState[kDaikin216StateLength] = {
// 8 bytes
0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02,
@@ -1878,3 +1936,1051 @@ TEST(TestDecodeDaikin216, SyntheticExample) {
ASSERT_EQ(kDaikin216Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
}
+
+TEST(TestDaikinClass, toCommon) {
+ IRDaikinESP ac(0);
+ ac.setPower(true);
+ ac.setMode(kDaikinCool);
+ ac.setTemp(20);
+ ac.setFan(kDaikinFanMax);
+ ac.setSwingVertical(true);
+ ac.setSwingHorizontal(true);
+ ac.setQuiet(false);
+ ac.setPowerful(true);
+ ac.setEcono(false);
+ ac.setMold(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::DAIKIN, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestDaikin2Class, toCommon) {
+ IRDaikin2 ac(0);
+ ac.setPower(true);
+ ac.setMode(kDaikinCool);
+ ac.setTemp(20);
+ ac.setFan(kDaikinFanMax);
+ ac.setSwingVertical(kDaikin2SwingVHigh + 3);
+ ac.setSwingHorizontal(kDaikin2SwingHAuto);
+ ac.setQuiet(false);
+ ac.setPowerful(true);
+ ac.setEcono(false);
+ ac.setMold(true);
+ ac.setLight(true);
+ ac.setPurify(true);
+ ac.setBeep(true);
+ ac.enableSleepTimer(6 * 60);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::DAIKIN2, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_TRUE(ac.toCommon().light);
+ ASSERT_TRUE(ac.toCommon().filter);
+ ASSERT_TRUE(ac.toCommon().beep);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kMiddle, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh);
+ ASSERT_EQ(6 * 60, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestDaikin216Class, toCommon) {
+ IRDaikin216 ac(0);
+ ac.setPower(true);
+ ac.setMode(kDaikinCool);
+ ac.setTemp(20);
+ ac.setFan(kDaikinFanMax);
+ ac.setSwingVertical(true);
+ ac.setSwingHorizontal(true);
+ ac.setQuiet(false);
+ ac.setPowerful(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::DAIKIN216, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/731
+TEST(TestDecodeDaikin160, RealExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ uint16_t rawData[327] = {
+ 5024, 2144, 342, 1786, 344, 706, 342, 706, 344, 706, 342, 1786, 342, 706,
+ 342, 708, 342, 708, 342, 708, 342, 1786, 342, 708, 342, 1786, 342, 1788,
+ 342, 708, 342, 1786, 344, 1786, 342, 1786, 342, 1786, 342, 1786, 342, 708,
+ 342, 708, 340, 1786, 344, 706, 342, 708, 342, 706, 342, 708, 342, 708,
+ 342, 706, 342, 1786, 342, 1788, 342, 1786, 342, 1786, 342, 1788, 342, 706,
+ 342, 1788, 342, 1786, 342, 706, 342, 706, 342, 708, 342, 708, 342, 708,
+ 342, 708, 342, 706, 342, 708, 342, 708, 342, 706, 342, 706, 342, 708, 342,
+ 1786, 342, 1786, 342, 1786, 342, 1788, 342, 706, 342, 706, 342, 706, 342,
+ 708, 342, 29442, 5022, 2146, 342, 1786, 342, 706, 342, 708, 342, 708, 342,
+ 1788, 342, 706, 342, 706, 342, 706, 342, 706, 342, 1788, 342, 708, 342,
+ 1786, 342, 1786, 342, 708, 342, 1786, 342, 1788, 342, 1786, 342, 1786,
+ 342, 1786, 342, 706, 342, 706, 342, 1786, 344, 706, 342, 706, 344, 706,
+ 342, 706, 342, 706, 342, 708, 342, 706, 342, 706, 342, 706, 342, 706, 342,
+ 1786, 342, 1786, 342, 706, 342, 706, 342, 1788, 342, 708, 342, 1786, 342,
+ 1786, 342, 706, 342, 706, 342, 706, 342, 708, 342, 1786, 342, 1786, 342,
+ 708, 342, 708, 342, 1786, 342, 706, 342, 706, 344, 706, 342, 1786, 342,
+ 708, 342, 706, 342, 706, 342, 708, 342, 706, 342, 708, 342, 706, 342, 708,
+ 342, 706, 342, 704, 344, 706, 342, 706, 344, 706, 342, 706, 342, 708, 342,
+ 706, 342, 706, 344, 706, 342, 706, 342, 706, 344, 1786, 342, 1786, 342,
+ 1786, 342, 1786, 342, 706, 342, 706, 344, 706, 342, 706, 342, 1786, 344,
+ 706, 342, 1786, 342, 706, 342, 708, 342, 706, 342, 706, 344, 706, 342,
+ 706, 342, 706, 342, 1786, 342, 706, 344, 706, 342, 706, 342, 708, 342,
+ 706, 342, 1788, 342, 1786, 342, 706, 344, 1786, 344, 706, 344, 1786, 342,
+ 708, 342}; // UNKNOWN 99CC993
+
+ uint8_t expectedState[kDaikin160StateLength] = {
+ // 7 bytes
+ 0x11, 0xDA, 0x27, 0xF0, 0x0D, 0x00, 0x0F,
+ // 13 bytes
+ 0x11, 0xDA, 0x27, 0x00, 0xD3, 0x30, 0x11,
+ 0x00, 0x00, 0x1E, 0x0A, 0x08, 0x56};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendRaw(rawData, 327, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(DAIKIN160, irsend.capture.decode_type);
+ ASSERT_EQ(kDaikin160Bits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+ IRDaikin160 ac(0);
+ ac.setRaw(irsend.capture.state);
+ EXPECT_EQ("Power: Off, Mode: 3 (COOL), Temp: 25C, Fan: 10 (Auto), "
+ "Vent Position (V): 1 (Lowest)", ac.toString());
+}
+
+TEST(TestDecodeDaikin160, SyntheticExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+
+ uint8_t expectedState[kDaikin160StateLength] = {
+ // 7 bytes
+ 0x11, 0xDA, 0x27, 0xF0, 0x0D, 0x00, 0x0F,
+ // 13 bytes
+ 0x11, 0xDA, 0x27, 0x00, 0xD3, 0x30, 0x11,
+ 0x00, 0x00, 0x1E, 0x0A, 0x08, 0x56};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendDaikin160(expectedState);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(DAIKIN160, irsend.capture.decode_type);
+ ASSERT_EQ(kDaikin160Bits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+}
+
+TEST(TestDaikin160Class, toCommon) {
+ IRDaikin160 ac(0);
+ ac.setPower(true);
+ ac.setMode(kDaikinCool);
+ ac.setTemp(20);
+ ac.setFan(kDaikinFanMax);
+ ac.setSwingVertical(kDaikin160SwingVAuto);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::DAIKIN160, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ // Unsupported.
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestDaikin160Class, FanSpeed) {
+ IRDaikin160 ac(0);
+ ac.begin();
+
+ // Unexpected value should default to Auto.
+ ac.setFan(0);
+ EXPECT_EQ(kDaikinFanAuto, ac.getFan());
+
+ // Unexpected value should default to Auto.
+ ac.setFan(255);
+ EXPECT_EQ(kDaikinFanAuto, ac.getFan());
+
+ ac.setFan(kDaikinFanMax);
+ EXPECT_EQ(kDaikinFanMax, ac.getFan());
+
+ // Beyond Max should default to Auto.
+ ac.setFan(kDaikinFanMax + 1);
+ EXPECT_EQ(kDaikinFanAuto, ac.getFan());
+
+ ac.setFan(kDaikinFanMax - 1);
+ EXPECT_EQ(kDaikinFanMax - 1, ac.getFan());
+
+ ac.setFan(kDaikinFanMin);
+ EXPECT_EQ(kDaikinFanMin, ac.getFan());
+
+ ac.setFan(kDaikinFanMin + 1);
+ EXPECT_EQ(kDaikinFanMin + 1, ac.getFan());
+
+ // Beyond Min should default to Auto.
+ ac.setFan(kDaikinFanMin - 1);
+ EXPECT_EQ(kDaikinFanAuto, ac.getFan());
+
+ ac.setFan(3);
+ EXPECT_EQ(3, ac.getFan());
+
+ ac.setFan(kDaikinFanAuto);
+ EXPECT_EQ(kDaikinFanAuto, ac.getFan());
+
+ ac.setFan(kDaikinFanQuiet);
+ EXPECT_EQ(kDaikinFanQuiet, ac.getFan());
+}
+
+TEST(TestDaikin160Class, VaneSwing) {
+ IRDaikin160 ac(0);
+ ac.begin();
+
+ ac.setSwingVertical(kDaikin160SwingVAuto);
+ EXPECT_EQ(kDaikin160SwingVAuto, ac.getSwingVertical());
+
+ ac.setSwingVertical(kDaikin160SwingVHigh);
+ EXPECT_EQ(kDaikin160SwingVHigh, ac.getSwingVertical());
+
+ ac.setSwingVertical(255);
+ EXPECT_EQ(kDaikin160SwingVAuto, ac.getSwingVertical());
+
+ EXPECT_EQ(kDaikin160SwingVHighest,
+ IRDaikin160::convertSwingV(stdAc::swingv_t::kHighest));
+ EXPECT_EQ(kDaikin160SwingVLowest,
+ IRDaikin160::convertSwingV(stdAc::swingv_t::kLowest));
+ EXPECT_EQ(kDaikin160SwingVMiddle,
+ IRDaikin160::convertSwingV(stdAc::swingv_t::kMiddle));
+}
+
+TEST(TestDaikin160Class, Power) {
+ IRDaikin160 ac(0);
+ ac.begin();
+
+ ac.on();
+ EXPECT_TRUE(ac.getPower());
+
+ ac.off();
+ EXPECT_FALSE(ac.getPower());
+
+ ac.setPower(true);
+ EXPECT_TRUE(ac.getPower());
+
+ ac.setPower(false);
+ EXPECT_FALSE(ac.getPower());
+}
+
+TEST(TestDaikin160Class, Temperature) {
+ IRDaikin160 ac(0);
+ ac.begin();
+
+ ac.setTemp(0);
+ EXPECT_EQ(kDaikinMinTemp, ac.getTemp());
+
+ ac.setTemp(255);
+ EXPECT_EQ(kDaikinMaxTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMinTemp);
+ EXPECT_EQ(kDaikinMinTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMaxTemp);
+ EXPECT_EQ(kDaikinMaxTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMinTemp - 1);
+ EXPECT_EQ(kDaikinMinTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMaxTemp + 1);
+ EXPECT_EQ(kDaikinMaxTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMinTemp + 1);
+ EXPECT_EQ(kDaikinMinTemp + 1, ac.getTemp());
+
+ ac.setTemp(21);
+ EXPECT_EQ(21, ac.getTemp());
+
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+
+ ac.setTemp(29);
+ EXPECT_EQ(29, ac.getTemp());
+}
+
+TEST(TestDaikin160Class, OperatingMode) {
+ IRDaikin160 ac(0);
+ ac.begin();
+
+ ac.setMode(kDaikinAuto);
+ EXPECT_EQ(kDaikinAuto, ac.getMode());
+
+ ac.setMode(kDaikinCool);
+ EXPECT_EQ(kDaikinCool, ac.getMode());
+
+ ac.setMode(kDaikinHeat);
+ EXPECT_EQ(kDaikinHeat, ac.getMode());
+
+ ac.setMode(kDaikinDry);
+ EXPECT_EQ(kDaikinDry, ac.getMode());
+
+ ac.setMode(kDaikinFan);
+ EXPECT_EQ(kDaikinFan, ac.getMode());
+
+ ac.setMode(kDaikinFan + 1);
+ EXPECT_EQ(kDaikinAuto, ac.getMode());
+
+ ac.setMode(kDaikinAuto + 1);
+ EXPECT_EQ(kDaikinAuto, ac.getMode());
+
+ ac.setMode(255);
+ EXPECT_EQ(kDaikinAuto, ac.getMode());
+}
+
+TEST(TestDaikin160Class, HumanReadable) {
+ IRDaikin160 ac(0);
+
+ EXPECT_EQ(
+ "Power: Off, Mode: 3 (COOL), Temp: 25C, Fan: 10 (Auto), "
+ "Vent Position (V): 1 (Lowest)",
+ ac.toString());
+ ac.setMode(kDaikinAuto);
+ ac.setTemp(19);
+ ac.setFan(kDaikinFanMin);
+ ac.setSwingVertical(kDaikin160SwingVAuto);
+ ac.setPower(true);
+ EXPECT_EQ(
+ "Power: On, Mode: 0 (AUTO), Temp: 19C, Fan: 1 (Low), "
+ "Vent Position (V): 15 (Auto)",
+ ac.toString());
+}
+
+TEST(TestDaikin176Class, FanControl) {
+ IRDaikin176 ac(0);
+
+ EXPECT_EQ(
+ "Power: Off, Mode: 7 (COOL), Temp: 9C, Fan: 1 (Low), Swing (H): 6 (Off)",
+ ac.toString());
+ ac.setFan(kDaikinFanMin);
+ ac.setPower(true);
+ EXPECT_EQ(
+ "Power: On, Mode: 7 (COOL), Temp: 9C, Fan: 1 (Low), Swing (H): 6 (Off)",
+ ac.toString());
+ ac.setFan(kDaikinFanMin + 1);
+ EXPECT_EQ(
+ "Power: On, Mode: 7 (COOL), Temp: 9C, Fan: 3 (High), Swing (H): 6 (Off)",
+ ac.toString());
+ ac.setFan(kDaikin176FanMax);
+ EXPECT_EQ(
+ "Power: On, Mode: 7 (COOL), Temp: 9C, Fan: 3 (High), Swing (H): 6 (Off)",
+ ac.toString());
+
+ // Real state from remote
+ // https://github.com/crankyoldgit/IRremoteESP8266/pull/826#issuecomment-513168270
+ uint8_t state[kDaikin176StateLength] = {
+ 0x11, 0xDA, 0x17, 0x18, 0x04, 0x00, 0x1E,
+ 0x11, 0xDA, 0x17, 0x18, 0x00, 0x73, 0x00, 0x21, 0x00, 0x00, 0x22, 0x35,
+ 0x00, 0x20, 0x25};
+ ac.setRaw(state);
+ EXPECT_EQ(
+ "Power: On, Mode: 7 (COOL), Temp: 26C, Fan: 3 (High), "
+ "Swing (H): 5 (Auto)",
+ ac.toString());
+}
+
+TEST(TestDaikin176Class, convertFan) {
+ EXPECT_EQ(kDaikinFanMin, IRDaikin176::convertFan(stdAc::fanspeed_t::kMin));
+ EXPECT_EQ(kDaikinFanMin, IRDaikin176::convertFan(stdAc::fanspeed_t::kLow));
+ EXPECT_EQ(kDaikin176FanMax,
+ IRDaikin176::convertFan(stdAc::fanspeed_t::kMedium));
+ EXPECT_EQ(kDaikin176FanMax,
+ IRDaikin176::convertFan(stdAc::fanspeed_t::kHigh));
+ EXPECT_EQ(kDaikin176FanMax, IRDaikin176::convertFan(stdAc::fanspeed_t::kMax));
+ EXPECT_EQ(kDaikin176FanMax,
+ IRDaikin176::convertFan(stdAc::fanspeed_t::kAuto));
+}
+
+TEST(TestDaikin176Class, SimulateIRacDaikin176) {
+ IRDaikin176 ac(0);
+
+ ac.setPower(true);
+ ac.setMode(ac.convertMode(stdAc::opmode_t::kCool));
+ ac.setTemp(26);
+ ac.setFan(ac.convertFan(stdAc::fanspeed_t::kMax));
+ ac.setSwingHorizontal(kDaikin176SwingHOff);
+ EXPECT_EQ(
+ "Power: On, Mode: 7 (COOL), Temp: 26C, Fan: 3 (High), Swing (H): 6 (Off)",
+ ac.toString());
+ ac.setSwingHorizontal(ac.convertSwingH(stdAc::swingh_t::kAuto));
+ EXPECT_EQ(
+ "Power: On, Mode: 7 (COOL), Temp: 26C, Fan: 3 (High), "
+ "Swing (H): 5 (Auto)",
+ ac.toString());
+}
+
+TEST(TestDaikin176Class, OperatingMode) {
+ IRDaikin176 ac(0);
+ ac.begin();
+
+ ac.setMode(kDaikinAuto);
+ EXPECT_EQ(kDaikin176Cool, ac.getMode());
+
+ ac.setMode(kDaikin176Cool);
+ EXPECT_EQ(kDaikin176Cool, ac.getMode());
+
+ ac.setMode(kDaikinDry);
+ EXPECT_EQ(kDaikinDry, ac.getMode());
+
+ ac.setMode(kDaikinHeat);
+ EXPECT_EQ(kDaikin176Cool, ac.getMode());
+
+ ac.setMode(kDaikinFan);
+ EXPECT_EQ(kDaikinFan, ac.getMode());
+
+ ac.setMode(kDaikin176Cool + 1);
+ EXPECT_EQ(kDaikin176Cool, ac.getMode());
+
+ ac.setMode(kDaikinAuto + 1);
+ EXPECT_EQ(kDaikin176Cool, ac.getMode());
+
+ ac.setMode(255);
+ EXPECT_EQ(kDaikin176Cool, ac.getMode());
+}
+
+TEST(TestDaikin176Class, Temperature) {
+ IRDaikin176 ac(0);
+ ac.begin();
+ ac.setMode(kDaikinAuto);
+ ac.setTemp(0);
+ EXPECT_EQ(kDaikinMinTemp, ac.getTemp());
+
+ ac.setTemp(255);
+ EXPECT_EQ(kDaikinMaxTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMinTemp);
+ EXPECT_EQ(kDaikinMinTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMaxTemp);
+ EXPECT_EQ(kDaikinMaxTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMinTemp - 1);
+ EXPECT_EQ(kDaikinMinTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMaxTemp + 1);
+ EXPECT_EQ(kDaikinMaxTemp, ac.getTemp());
+
+ ac.setTemp(kDaikinMinTemp + 1);
+ EXPECT_EQ(kDaikinMinTemp + 1, ac.getTemp());
+
+ ac.setTemp(21);
+ EXPECT_EQ(21, ac.getTemp());
+
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+
+ ac.setTemp(29);
+ EXPECT_EQ(29, ac.getTemp());
+
+ // Temp should be locked to kDaikin176DryFanTemp when in Dry or Fan Mode.
+ ac.setMode(kDaikinFan);
+ EXPECT_EQ(kDaikin176DryFanTemp, ac.getTemp());
+ ac.setMode(kDaikin176Cool);
+ EXPECT_EQ(29, ac.getTemp());
+ ac.setMode(kDaikinDry);
+ EXPECT_EQ(kDaikinDry, ac.getMode());
+ EXPECT_EQ(kDaikin176DryFanTemp, ac.getTemp());
+ ac.setMode(kDaikin176Cool);
+ EXPECT_EQ(29, ac.getTemp());
+ ac.setMode(kDaikinFan);
+ ac.setTemp(25);
+ EXPECT_EQ(kDaikin176DryFanTemp, ac.getTemp());
+ ac.setMode(kDaikinHeat);
+ EXPECT_EQ(25, ac.getTemp());
+}
+
+TEST(TestDaikin176Class, Power) {
+ IRDaikin176 ac(0);
+ ac.begin();
+
+ ac.on();
+ EXPECT_TRUE(ac.getPower());
+
+ ac.off();
+ EXPECT_FALSE(ac.getPower());
+
+ ac.setPower(true);
+ EXPECT_TRUE(ac.getPower());
+
+ ac.setPower(false);
+ EXPECT_FALSE(ac.getPower());
+}
+
+TEST(TestDaikin176Class, VaneSwing) {
+ IRDaikin176 ac(0);
+ ac.begin();
+
+ ac.setSwingHorizontal(kDaikin176SwingHAuto);
+ EXPECT_EQ(kDaikin176SwingHAuto, ac.getSwingHorizontal());
+
+ ac.setSwingHorizontal(0);
+ EXPECT_EQ(kDaikin176SwingHAuto, ac.getSwingHorizontal());
+
+ ac.setSwingHorizontal(kDaikin176SwingHOff);
+ EXPECT_EQ(kDaikin176SwingHOff, ac.getSwingHorizontal());
+
+ ac.setSwingHorizontal(255);
+ EXPECT_EQ(kDaikin176SwingHAuto, ac.getSwingHorizontal());
+
+ EXPECT_EQ(kDaikin176SwingHAuto,
+ IRDaikin176::convertSwingH(stdAc::swingh_t::kAuto));
+ EXPECT_EQ(kDaikin176SwingHOff,
+ IRDaikin176::convertSwingH(stdAc::swingh_t::kOff));
+ EXPECT_EQ(kDaikin176SwingHAuto,
+ IRDaikin176::convertSwingH(stdAc::swingh_t::kLeft));
+}
+
+TEST(TestDaikin176Class, ReconstructKnownStates) {
+ IRDaikin176 ac(0);
+ ac.begin();
+ // Data from:
+ // https://github.com/crankyoldgit/IRremoteESP8266/pull/826#issuecomment-513531138
+
+ // Power: On, Mode: 7 (COOL), Temp: 25C, Fan: 3 (MAX), Swing (H): 5 (Auto)
+ // 11DA171804001E11DA17180073002100002035002023
+ uint8_t on_cool_25_max_auto[22] = {
+ 0x11, 0xDA, 0x17, 0x18, 0x04, 0x00, 0x1E,
+ 0x11, 0xDA, 0x17, 0x18, 0x00, 0x73, 0x00, 0x21, 0x00, 0x00, 0x20, 0x35,
+ 0x00, 0x20, 0x23};
+ // Power: On, Mode: 6 (FAN), Temp: 17C, Fan: 3 (MAX), Swing (H): 5 (Auto)
+ // 11DA171804001E11DA171800630401000010350020E7
+ uint8_t on_fan_17_max_auto[22] = {
+ 0x11, 0xDA, 0x17, 0x18, 0x04, 0x00, 0x1E,
+ 0x11, 0xDA, 0x17, 0x18, 0x00, 0x63, 0x04, 0x01, 0x00, 0x00, 0x10, 0x35,
+ 0x00, 0x20, 0xE7};
+ // Power: On, Mode: 2 (DRY), Temp: 17C, Fan: 3 (MAX), Swing (H): 5 (Auto)
+ // 11DA171804001E11DA17180023047100001035002017
+ uint8_t on_dry_17_max_auto[22] = {
+ 0x11, 0xDA, 0x17, 0x18, 0x04, 0x00, 0x1E,
+ 0x11, 0xDA, 0x17, 0x18, 0x00, 0x23, 0x04, 0x71, 0x00, 0x00, 0x10, 0x35,
+ 0x00, 0x20, 0x17};
+ // Power: On, Mode: 7 (COOL), Temp: 25C, Fan: 3 (MAX), Swing (H): 5 (Auto)
+ // 11DA171804001E11DA17180073042100002035002027
+ uint8_t on_cool_25_max_auto_v2[22] = {
+ 0x11, 0xDA, 0x17, 0x18, 0x04, 0x00, 0x1E,
+ 0x11, 0xDA, 0x17, 0x18, 0x00, 0x73, 0x04, 0x21, 0x00, 0x00, 0x20, 0x35,
+ 0x00, 0x20, 0x27};
+ ac.setMode(kDaikin176Cool);
+ ac.setPower(true);
+ ac.setTemp(25);
+ ac.setFan(kDaikin176FanMax);
+ ac.setSwingHorizontal(true);
+ EXPECT_STATE_EQ(on_cool_25_max_auto, ac.getRaw(), kDaikin176Bits);
+ ac.setMode(kDaikinFan);
+ EXPECT_STATE_EQ(on_fan_17_max_auto, ac.getRaw(), kDaikin176Bits);
+ ac.setMode(kDaikinDry);
+ EXPECT_STATE_EQ(on_dry_17_max_auto, ac.getRaw(), kDaikin176Bits);
+ ac.setMode(kDaikin176Cool);
+ EXPECT_STATE_EQ(on_cool_25_max_auto_v2, ac.getRaw(), kDaikin176Bits);
+}
+
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/827
+// Data from:
+// https://docs.google.com/spreadsheets/d/1-YJnHyzy6bId5QmjTEZuw8_wSufESoIl-L_VEF-o8lM/edit?usp=sharing
+TEST(TestDecodeDaikin128, RealExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ uint16_t rawData[265] = {
+ 9846, 9794, 9848, 9796, 4638, 2512, 348, 382, 352, 954, 352, 956, 352,
+ 382, 352, 956, 352, 384, 352, 382, 352, 386, 352, 382, 352, 954, 352, 384,
+ 352, 382, 352, 954, 352, 384, 352, 382, 352, 386, 352, 382, 352, 382, 354,
+ 382, 354, 382, 352, 382, 352, 954, 352, 382, 352, 384, 352, 954, 352, 382,
+ 352, 382, 352, 954, 352, 954, 354, 382, 352, 382, 352, 386, 352, 954, 354,
+ 954, 352, 954, 352, 384, 352, 382, 352, 382, 352, 954, 352, 384, 354, 382,
+ 352, 954, 352, 382, 352, 382, 352, 382, 352, 956, 352, 382, 354, 384, 354,
+ 382, 354, 954, 352, 954, 352, 382, 352, 382, 352, 954, 352, 382, 352, 384,
+ 354, 954, 352, 382, 352, 954, 352, 954, 352, 382, 352, 954, 352, 382, 352,
+ 956, 352, 20306, 376, 954, 352, 384, 352, 382, 352, 382, 354, 382, 352,
+ 954, 352, 382, 352, 958, 352, 384, 352, 382, 352, 382, 352, 382, 352, 382,
+ 354, 382, 352, 382, 352, 386, 352, 382, 352, 382, 354, 382, 352, 384, 352,
+ 382, 352, 382, 352, 382, 354, 384, 354, 382, 354, 382, 354, 382, 352, 382,
+ 352, 382, 352, 382, 352, 382, 352, 386, 354, 382, 352, 382, 352, 382, 352,
+ 382, 352, 382, 352, 382, 354, 382, 352, 384, 352, 382, 354, 382, 354, 382,
+ 354, 382, 352, 382, 354, 382, 354, 382, 354, 384, 354, 382, 354, 382, 352,
+ 382, 352, 382, 354, 382, 352, 382, 352, 382, 352, 386, 354, 952, 354, 954,
+ 352, 382, 352, 954, 354, 382, 352, 382, 354, 382, 354, 382, 4618
+ }; // UNKNOWN DBA1F5E3
+ uint8_t expectedState[kDaikin128StateLength] = {
+ // 8 bytes
+ 0x16, 0x12, 0x20, 0x19, 0x47, 0x22, 0x26, 0xAD,
+ // 8 bytes
+ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendRaw(rawData, 265, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(DAIKIN128, irsend.capture.decode_type);
+ ASSERT_EQ(kDaikin128Bits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+ EXPECT_EQ(
+ "Power Toggle: On, Mode: 2 (COOL), Temp: 26C, Fan: 1 (Auto), "
+ "Powerful: Off, Quiet: Off, Swing (V): On, Sleep: Off, "
+ "Econo: Off, Clock: 19:20, "
+ "On Timer: Off, On Time: 07:30, Off Timer: Off, Off Time: 22:00, "
+ "Light Toggle: 0 (Off)",
+ IRAcUtils::resultAcToString(&irsend.capture));
+}
+
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/827
+// Data from:
+// https://docs.google.com/spreadsheets/d/1-YJnHyzy6bId5QmjTEZuw8_wSufESoIl-L_VEF-o8lM/edit?usp=sharing
+TEST(TestDecodeDaikin128, SyntheticSelfDecode) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ uint8_t expectedState[kDaikin128StateLength] = {
+ // 8 bytes
+ 0x16, 0x12, 0x20, 0x19, 0x47, 0x22, 0x26, 0xAD,
+ // 8 bytes
+ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendDaikin128(expectedState);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(DAIKIN128, irsend.capture.decode_type);
+ ASSERT_EQ(kDaikin128Bits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+}
+
+TEST(TestDaikin128Class, Checksums) {
+ IRDaikin128 ac(0);
+
+ uint8_t knownGood[kDaikin128StateLength] = {
+ 0x16, 0x12, 0x20, 0x19, 0x47, 0x22, 0x26, 0xAD,
+ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B};
+ uint8_t knownBad[kDaikin128StateLength] = {
+ 0x16, 0x12, 0x20, 0x19, 0x47, 0x22, 0x26, 0x0D,
+ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ EXPECT_EQ(0xA, ac.calcFirstChecksum(knownGood));
+ EXPECT_EQ(0x0B, ac.calcSecondChecksum(knownGood));
+ EXPECT_TRUE(ac.validChecksum(knownGood));
+ ac.setRaw(knownBad);
+ EXPECT_STATE_EQ(knownGood, ac.getRaw(), kDaikin128Bits);
+}
+
+TEST(TestDaikin128Class, PowerToggle) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ ac.setPowerToggle(true);
+ EXPECT_TRUE(ac.getPowerToggle());
+ ac.setPowerToggle(false);
+ EXPECT_FALSE(ac.getPowerToggle());
+ ac.setPowerToggle(true);
+ EXPECT_TRUE(ac.getPowerToggle());
+}
+
+TEST(TestDaikin128Class, SwingVertical) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ ac.setSwingVertical(true);
+ EXPECT_TRUE(ac.getSwingVertical());
+ ac.setSwingVertical(false);
+ EXPECT_FALSE(ac.getSwingVertical());
+ ac.setSwingVertical(true);
+ EXPECT_TRUE(ac.getSwingVertical());
+}
+
+TEST(TestDaikin128Class, Sleep) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ ac.setSleep(true);
+ EXPECT_TRUE(ac.getSleep());
+ ac.setSleep(false);
+ EXPECT_FALSE(ac.getSleep());
+ ac.setSleep(true);
+ EXPECT_TRUE(ac.getSleep());
+}
+
+TEST(TestDaikin128Class, Econo) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ // Econo works in some modes
+ ac.setMode(kDaikin128Heat);
+ ac.setEcono(true);
+ EXPECT_TRUE(ac.getEcono());
+ ac.setEcono(false);
+ EXPECT_FALSE(ac.getEcono());
+ ac.setEcono(true);
+ EXPECT_TRUE(ac.getEcono());
+ // But not some some modes
+ ac.setMode(kDaikin128Auto);
+ EXPECT_FALSE(ac.getEcono());
+ ac.setEcono(true);
+ EXPECT_FALSE(ac.getEcono());
+}
+
+TEST(TestDaikin128Class, FanSpeed) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ ac.setMode(kDaikin128Cool);
+ // Unexpected value should default to Auto.
+ ac.setFan(0);
+ EXPECT_EQ(kDaikin128FanAuto, ac.getFan());
+ ac.setFan(255);
+ EXPECT_EQ(kDaikin128FanAuto, ac.getFan());
+ ac.setFan(5);
+ EXPECT_EQ(kDaikin128FanAuto, ac.getFan());
+
+ ac.setFan(kDaikin128FanHigh);
+ EXPECT_EQ(kDaikin128FanHigh, ac.getFan());
+
+ // Beyond Quiet should default to Auto.
+ ac.setFan(kDaikin128FanQuiet + 1);
+ EXPECT_EQ(kDaikin128FanAuto, ac.getFan());
+
+ ac.setFan(kDaikin128FanMed);
+ EXPECT_EQ(kDaikin128FanMed, ac.getFan());
+
+ ac.setFan(kDaikin128FanLow);
+ EXPECT_EQ(kDaikin128FanLow, ac.getFan());
+
+ ac.setFan(kDaikin128FanPowerful);
+ EXPECT_EQ(kDaikin128FanPowerful, ac.getFan());
+
+ ac.setFan(kDaikin128FanAuto);
+ EXPECT_EQ(kDaikin128FanAuto, ac.getFan());
+
+ ac.setFan(kDaikin128FanQuiet);
+ EXPECT_EQ(kDaikin128FanQuiet, ac.getFan());
+}
+
+TEST(TestDaikin128Class, OperatingMode) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ ac.setMode(0);
+ EXPECT_EQ(kDaikin128Auto, ac.getMode());
+ ac.setMode(kDaikin128Cool);
+ EXPECT_EQ(kDaikin128Cool, ac.getMode());
+ ac.setMode(kDaikin128Auto);
+ EXPECT_EQ(kDaikin128Auto, ac.getMode());
+ ac.setMode(kDaikin128Heat);
+ EXPECT_EQ(kDaikin128Heat, ac.getMode());
+ ac.setMode(kDaikin128Dry);
+ EXPECT_EQ(kDaikin128Dry, ac.getMode());
+ ac.setMode(kDaikin128Fan);
+ EXPECT_EQ(kDaikin128Fan, ac.getMode());
+ ac.setMode(3);
+ EXPECT_EQ(kDaikin128Auto, ac.getMode());
+ ac.setMode(kDaikin128Auto + 1);
+ EXPECT_EQ(kDaikin128Auto, ac.getMode());
+ ac.setMode(255);
+ EXPECT_EQ(kDaikin128Auto, ac.getMode());
+}
+
+TEST(TestDaikin128Class, Quiet) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ // Quiet works in some modes
+ ac.setMode(kDaikin128Cool);
+ ac.setQuiet(true);
+ EXPECT_TRUE(ac.getQuiet());
+ ac.setQuiet(false);
+ EXPECT_FALSE(ac.getQuiet());
+ ac.setQuiet(true);
+ EXPECT_TRUE(ac.getQuiet());
+ // But not some some modes
+ ac.setMode(kDaikin128Auto);
+ EXPECT_FALSE(ac.getQuiet());
+ ac.setQuiet(true);
+ EXPECT_FALSE(ac.getQuiet());
+}
+
+TEST(TestDaikin128Class, Powerful) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ // Powerful works in some modes
+ ac.setMode(kDaikin128Cool);
+ ac.setPowerful(true);
+ EXPECT_TRUE(ac.getPowerful());
+ ac.setPowerful(false);
+ EXPECT_FALSE(ac.getPowerful());
+ ac.setPowerful(true);
+ EXPECT_TRUE(ac.getPowerful());
+ // But not some some modes
+ ac.setMode(kDaikin128Auto);
+ EXPECT_FALSE(ac.getPowerful());
+ ac.setPowerful(true);
+ EXPECT_FALSE(ac.getPowerful());
+}
+
+TEST(TestDaikin128Class, Temperature) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ ac.setTemp(0);
+ EXPECT_EQ(kDaikin128MinTemp, ac.getTemp());
+
+ ac.setTemp(255);
+ EXPECT_EQ(kDaikin128MaxTemp, ac.getTemp());
+
+ ac.setTemp(kDaikin128MinTemp);
+ EXPECT_EQ(kDaikin128MinTemp, ac.getTemp());
+
+ ac.setTemp(kDaikin128MaxTemp);
+ EXPECT_EQ(kDaikin128MaxTemp, ac.getTemp());
+
+ ac.setTemp(kDaikin128MinTemp - 1);
+ EXPECT_EQ(kDaikin128MinTemp, ac.getTemp());
+
+ ac.setTemp(kDaikin128MaxTemp + 1);
+ EXPECT_EQ(kDaikin128MaxTemp, ac.getTemp());
+
+ ac.setTemp(kDaikin128MinTemp + 1);
+ EXPECT_EQ(kDaikin128MinTemp + 1, ac.getTemp());
+
+ ac.setTemp(21);
+ EXPECT_EQ(21, ac.getTemp());
+
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+
+ ac.setTemp(29);
+ EXPECT_EQ(29, ac.getTemp());
+}
+
+// Test human readable output.
+TEST(TestDaikin128Class, HumanReadable) {
+ IRDaikin128 ac(0);
+
+ ac.setPowerToggle(false);
+ ac.setMode(kDaikin128Auto);
+ ac.setTemp(25);
+ ac.setFan(kDaikin128FanAuto);
+ ac.setQuiet(false);
+ ac.setPowerful(false);
+ ac.setSleep(false);
+ ac.setEcono(false);
+ ac.setSwingVertical(true);
+ EXPECT_EQ(
+ "Power Toggle: Off, Mode: 10 (AUTO), Temp: 25C, Fan: 1 (Auto), "
+ "Powerful: Off, Quiet: Off, Swing (V): On, "
+ "Sleep: Off, Econo: Off, Clock: 00:00, "
+ "On Timer: Off, On Time: 00:00, Off Timer: Off, Off Time: 00:00, "
+ "Light Toggle: 0 (Off)",
+ ac.toString());
+ ac.setMode(kDaikin128Cool);
+ ac.setTemp(16);
+ ac.setQuiet(true);
+ ac.setSwingVertical(false);
+ ac.setPowerToggle(true);
+ ac.setSleep(true);
+ ac.setEcono(true);
+ ac.setClock(18 * 60 + 33); // 18:33
+ ac.setOnTimer(10 * 60); // 10am
+ ac.setOnTimerEnabled(true);
+ ac.setOffTimer(21 * 60 + 30); // 9:30pm
+ ac.setOffTimerEnabled(true);
+ ac.setLightToggle(kDaikin128BitWall);
+ EXPECT_EQ(
+ "Power Toggle: On, Mode: 2 (COOL), Temp: 16C, Fan: 9 (Quiet), "
+ "Powerful: Off, Quiet: On, Swing (V): Off, "
+ "Sleep: On, Econo: On, Clock: 18:33, "
+ "On Timer: On, On Time: 10:00, Off Timer: On, Off Time: 21:30, "
+ "Light Toggle: 8 (Wall)",
+ ac.toString());
+}
+
+TEST(TestDaikin128Class, Clock) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ ac.setClock(0);
+ EXPECT_EQ(0, ac.getClock());
+ ac.setClock(23 * 60 + 59);
+ EXPECT_EQ(23 * 60 + 59, ac.getClock());
+ ac.setClock(23 * 60 + 59 + 1);
+ EXPECT_EQ(0, ac.getClock());
+ ac.setClock(24 * 60 + 99);
+ EXPECT_EQ(0, ac.getClock());
+}
+
+TEST(TestDaikin128Class, Timers) {
+ IRDaikin128 ac(0);
+ ac.begin();
+
+ ac.setOnTimerEnabled(false);
+ EXPECT_FALSE(ac.getOnTimerEnabled());
+ ac.setOnTimerEnabled(true);
+ EXPECT_TRUE(ac.getOnTimerEnabled());
+ ac.setOnTimer(13 * 60 + 30);
+ EXPECT_EQ("13:30", irutils::minsToString(ac.getOnTimer()));
+ ac.setOnTimer(13 * 60 + 31);
+ EXPECT_EQ("13:30", irutils::minsToString(ac.getOnTimer()));
+ ac.setOnTimer(13 * 60 + 29);
+ EXPECT_EQ("13:00", irutils::minsToString(ac.getOnTimer()));
+ EXPECT_TRUE(ac.getOnTimerEnabled());
+ ac.setOnTimerEnabled(false);
+ EXPECT_FALSE(ac.getOnTimerEnabled());
+
+ ac.setOffTimerEnabled(false);
+ EXPECT_FALSE(ac.getOffTimerEnabled());
+ ac.setOffTimerEnabled(true);
+ EXPECT_TRUE(ac.getOffTimerEnabled());
+ ac.setOffTimer(1 * 60 + 30);
+ EXPECT_EQ("01:30", irutils::minsToString(ac.getOffTimer()));
+ ac.setOffTimer(23 * 60 + 31);
+ EXPECT_EQ("23:30", irutils::minsToString(ac.getOffTimer()));
+ ac.setOffTimer(24 * 60 + 29);
+ EXPECT_EQ("00:00", irutils::minsToString(ac.getOffTimer()));
+ EXPECT_TRUE(ac.getOffTimerEnabled());
+ ac.setOffTimerEnabled(false);
+ EXPECT_FALSE(ac.getOffTimerEnabled());
+}
+
+TEST(TestDaikin128Class, ReconstructKnownState) {
+ IRDaikin128 ac(0);
+
+ uint8_t expectedState[kDaikin128StateLength] = {
+ 0x16, 0x12, 0x20, 0x19, 0x47, 0x22, 0x26, 0xAD,
+ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B};
+
+ ac.begin();
+ ac.setPowerToggle(true);
+ ac.setMode(kDaikin128Cool);
+ ac.setTemp(26);
+ ac.setFan(kDaikin128FanAuto);
+ ac.setPowerful(false);
+ ac.setQuiet(false);
+ ac.setSwingVertical(true);
+ ac.setSleep(false);
+ ac.setEcono(false);
+ ac.setClock(19 * 60 + 20);
+ ac.setOnTimerEnabled(false);
+ ac.setOnTimer(7 * 60 + 30);
+ ac.setOffTimerEnabled(false);
+ ac.setOffTimer(22 * 60 + 0);
+ ac.setLightToggle(0);
+
+ EXPECT_STATE_EQ(expectedState, ac.getRaw(), kDaikin128Bits);
+}
+
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/873
+// Data from:
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/873#issue-485088080
+TEST(TestDecodeDaikin152, RealExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ uint16_t rawData[319] = {
+ 450, 420, 448, 446, 422, 444, 422, 446, 422, 446, 422, 25182, 3492, 1718,
+ 450, 1288, 448, 422, 446, 448, 420, 446, 422, 1290, 448, 422, 446, 446,
+ 422, 446, 424, 420, 448, 1290, 448, 446, 422, 1288, 448, 1288, 450, 420,
+ 448, 1288, 448, 1288, 450, 1288, 448, 1288, 448, 1290, 448, 446, 422, 446,
+ 422, 1288, 450, 446, 422, 420, 446, 446, 422, 422, 446, 446, 422, 420,
+ 448, 422, 446, 446, 422, 446, 422, 446, 422, 420, 446, 446, 422, 446, 422,
+ 422, 446, 446, 422, 422, 446, 446, 422, 446, 422, 446, 422, 446, 422, 446,
+ 424, 444, 424, 446, 420, 446, 422, 446, 422, 424, 444, 444, 422, 424, 444,
+ 1288, 450, 444, 422, 1288, 450, 1288, 450, 444, 422, 422, 446, 446, 422,
+ 446, 422, 446, 422, 446, 422, 422, 446, 420, 448, 444, 422, 446, 422, 446,
+ 422, 420, 448, 446, 422, 446, 422, 446, 422, 422, 446, 1286, 450, 422,
+ 448, 446, 422, 446, 422, 422, 446, 420, 446, 422, 446, 446, 422, 422, 446,
+ 446, 422, 422, 446, 446, 424, 444, 422, 420, 448, 446, 422, 420, 446, 446,
+ 422, 446, 422, 420, 448, 444, 422, 422, 448, 444, 424, 420, 446, 446, 422,
+ 446, 422, 422, 446, 444, 422, 446, 422, 444, 422, 446, 422, 420, 448, 446,
+ 422, 420, 448, 446, 422, 446, 422, 446, 422, 446, 422, 446, 422, 444, 422,
+ 1288, 450, 420, 448, 446, 420, 446, 422, 446, 422, 446, 424, 420, 448,
+ 444, 422, 422, 446, 446, 424, 420, 448, 1312, 424, 420, 448, 1288, 448,
+ 446, 422, 446, 424, 420, 446, 1288, 450, 1288, 450, 444, 422, 446, 422,
+ 422, 448, 444, 422, 420, 448, 446, 422, 1288, 448, 446, 422, 446, 422,
+ 444, 424, 444, 422, 446, 422, 446, 422, 420, 448, 446, 422, 420, 446,
+ 1290, 448, 1288, 448, 420, 446, 1288, 448, 420, 446, 1288, 450, 444, 424,
+ 1286, 450}; // UNKNOWN 2B9504D3
+ uint8_t expectedState[kDaikin152StateLength] = {
+ 0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x34, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0xC5, 0x40, 0x00, 0xAB};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendRaw(rawData, 319, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(DAIKIN152, irsend.capture.decode_type);
+ ASSERT_EQ(kDaikin152Bits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+}
+
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/873
+TEST(TestDecodeDaikin152, SyntheticExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ uint8_t expectedState[kDaikin152StateLength] = {
+ 0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x34, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0xC5, 0x40, 0x00, 0xAB};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendDaikin152(expectedState);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(DAIKIN152, irsend.capture.decode_type);
+ ASSERT_EQ(kDaikin152Bits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Denon_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Denon_test.cpp
similarity index 91%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Denon_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Denon_test.cpp
index 6b80eae02..bfb554bb5 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Denon_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Denon_test.cpp
@@ -25,7 +25,7 @@ TEST(TestSendDenon, SendDataOnly) {
irsend.reset();
// Denon Eco Mode On. (Panasonic/Kaseikyo)
- irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS);
+ irsend.sendDenon(0x2A4C028D6CE3, kDenon48Bits);
EXPECT_EQ(
"f36700d50"
"m3456s1728"
@@ -45,7 +45,7 @@ TEST(TestSendDenon, SendNormalWithRepeats) {
irsend.begin();
irsend.reset();
- irsend.sendDenon(0x2278, DENON_BITS, 1); // 1 repeat.
+ irsend.sendDenon(0x2278, kDenonBits, 1); // 1 repeat.
EXPECT_EQ(
"f38000d33"
"m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780"
@@ -61,7 +61,7 @@ TEST(TestSendDenon, SendNormalWithRepeats) {
"m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820"
"m260s43602",
irsend.outputStr());
- irsend.sendDenon(0x2278, DENON_BITS, 2); // 2 repeats.
+ irsend.sendDenon(0x2278, kDenonBits, 2); // 2 repeats.
EXPECT_EQ(
"f38000d33"
"m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780"
@@ -90,7 +90,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) {
irsend.begin();
irsend.reset();
- irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS, 1); // 1 repeat.
+ irsend.sendDenon(0x2A4C028D6CE3, kDenon48Bits, 1); // 1 repeat.
EXPECT_EQ(
"f36700d50"
"m3456s1728"
@@ -110,7 +110,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) {
"m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296"
"m432s98928",
irsend.outputStr());
- irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS, 2); // 2 repeats.
+ irsend.sendDenon(0x2A4C028D6CE3, kDenon48Bits, 2); // 2 repeats.
EXPECT_EQ(
"f36700d50"
"m3456s1728"
@@ -185,9 +185,9 @@ TEST(TestDecodeDenon, NormalDecodeWithStrict) {
irsend.sendDenon(0x2278);
irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_BITS, true));
+ ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenonBits, true));
EXPECT_EQ(DENON, irsend.capture.decode_type);
- EXPECT_EQ(DENON_BITS, irsend.capture.bits);
+ EXPECT_EQ(kDenonBits, irsend.capture.bits);
EXPECT_EQ(0x2278, irsend.capture.value);
EXPECT_EQ(0x2, irsend.capture.address);
EXPECT_EQ(0x79, irsend.capture.command);
@@ -208,11 +208,11 @@ TEST(TestDecodeDenon, NormalDecodeWithStrict) {
// Normal Denon 48-bit message. (Panasonic/Kaseikyo)
irsend.reset();
- irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS);
+ irsend.sendDenon(0x2A4C028D6CE3, kDenon48Bits);
irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_48_BITS, true));
+ ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenon48Bits, true));
EXPECT_EQ(DENON, irsend.capture.decode_type);
- EXPECT_EQ(DENON_48_BITS, irsend.capture.bits);
+ EXPECT_EQ(kDenon48Bits, irsend.capture.bits);
EXPECT_EQ(0x2A4C028D6CE3, irsend.capture.value);
EXPECT_EQ(0x2A4C, irsend.capture.address);
EXPECT_EQ(0x028D6CE3, irsend.capture.command);
@@ -235,9 +235,9 @@ TEST(TestDecodeDenon, DecodeGlobalCacheExample) {
irsend.sendGC(gc_test_power, 67);
irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_BITS, true));
+ ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenonBits, true));
EXPECT_EQ(DENON, irsend.capture.decode_type);
- EXPECT_EQ(DENON_BITS, irsend.capture.bits);
+ EXPECT_EQ(kDenonBits, irsend.capture.bits);
EXPECT_EQ(0x2278, irsend.capture.value);
EXPECT_EQ(0x2, irsend.capture.address);
EXPECT_EQ(0x79, irsend.capture.command);
@@ -256,9 +256,9 @@ TEST(TestDecodeDenon, DecodeGlobalCacheExample) {
irsend.sendGC(gc_test_eco, 103);
irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_48_BITS, true));
+ ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenon48Bits, true));
EXPECT_EQ(DENON, irsend.capture.decode_type);
- EXPECT_EQ(DENON_48_BITS, irsend.capture.bits);
+ EXPECT_EQ(kDenon48Bits, irsend.capture.bits);
EXPECT_EQ(0x2A4C028D6CE3, irsend.capture.value);
EXPECT_EQ(0x2A4C, irsend.capture.address);
EXPECT_EQ(0x028D6CE3, irsend.capture.command);
@@ -281,6 +281,6 @@ TEST(TestDecodeDenon, FailToDecodeNonDenonExample) {
ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture));
ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kDenonLegacyBits, false));
- ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, DENON_BITS, false));
- ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, DENON_48_BITS, false));
+ ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kDenonBits, false));
+ ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kDenon48Bits, false));
}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Dish_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Dish_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Dish_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Dish_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Electra_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Electra_test.cpp
new file mode 100644
index 000000000..581d40561
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Electra_test.cpp
@@ -0,0 +1,250 @@
+// Copyright 2018, 2019 David Conran
+
+#include "ir_Electra.h"
+#include
+#include "IRac.h"
+#include "IRrecv.h"
+#include "IRrecv_test.h"
+#include "IRsend.h"
+#include "IRsend_test.h"
+#include "gtest/gtest.h"
+
+// Tests for sendElectraAC().
+
+// Test sending typical data only.
+TEST(TestSendElectraAC, SendDataOnly) {
+ IRsendTest irsend(0);
+ irsend.begin();
+ uint8_t data[kElectraAcStateLength] = {0xC3, 0x87, 0xF6, 0x28, 0x60,
+ 0x00, 0x20, 0x00, 0x00, 0x20,
+ 0x00, 0x05, 0x0D};
+
+ irsend.sendElectraAC(data);
+ EXPECT_EQ(
+ "f38000d50"
+ "m9166s4470"
+ "m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647m646s1647"
+ "m646s1647m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647"
+ "m646s547m646s1647m646s1647m646s547m646s1647m646s1647m646s1647m646s1647"
+ "m646s547m646s547m646s547m646s1647m646s547m646s1647m646s547m646s547"
+ "m646s547m646s547m646s547m646s547m646s547m646s1647m646s1647m646s547"
+ "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547"
+ "m646s547m646s547m646s547m646s547m646s547m646s1647m646s547m646s547"
+ "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547"
+ "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547"
+ "m646s547m646s547m646s547m646s547m646s547m646s1647m646s547m646s547"
+ "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547"
+ "m646s1647m646s547m646s1647m646s547m646s547m646s547m646s547m646s547"
+ "m646s1647m646s547m646s1647m646s1647m646s547m646s547m646s547m646s547"
+ "m646s100000",
+ irsend.outputStr());
+}
+
+// Tests for decodeElectraAC().
+// Decode normal ElectraAC messages.
+
+TEST(TestDecodeElectraAC, SyntheticDecode) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ // Synthesised Normal ElectraAC message.
+ irsend.reset();
+ uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0x87, 0xF6, 0x28, 0x60,
+ 0x00, 0x20, 0x00, 0x00, 0x20,
+ 0x00, 0x05, 0x0D};
+ irsend.sendElectraAC(expectedState);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(ELECTRA_AC, irsend.capture.decode_type);
+ EXPECT_EQ(kElectraAcBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+}
+
+// Decode a recorded example
+TEST(TestDecodeElectraAC, RealExampleDecode) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ // Real ElectraAC message.
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/527
+ uint16_t rawData[211] = {
+ 9166, 4470, 642, 1632, 642, 1632, 668, 534, 666, 534, 668, 534,
+ 614, 536, 640, 1636, 640, 1646, 694, 1662, 612, 1628, 642, 1666,
+ 664, 532, 668, 534, 666, 534, 666, 532, 666, 1644, 642, 532,
+ 640, 1634, 668, 1632, 642, 538, 666, 1660, 610, 1666, 664, 1632,
+ 642, 1672, 610, 536, 666, 534, 694, 532, 666, 1636, 614, 538,
+ 666, 1632, 642, 536, 666, 544, 692, 534, 640, 558, 640, 534,
+ 640, 540, 666, 534, 638, 1666, 638, 1636, 640, 550, 666, 534,
+ 640, 540, 666, 534, 640, 540, 666, 536, 638, 540, 666, 536,
+ 638, 550, 664, 536, 638, 540, 664, 536, 638, 540, 666, 534,
+ 638, 1640, 664, 536, 692, 546, 664, 536, 664, 536, 664, 536,
+ 664, 546, 612, 532, 636, 538, 664, 536, 664, 546, 612, 538,
+ 638, 538, 638, 538, 664, 536, 690, 538, 662, 538, 664, 538,
+ 662, 548, 664, 536, 662, 538, 662, 562, 638, 564, 636, 564,
+ 636, 1668, 582, 556, 652, 572, 612, 568, 636, 564, 610, 570,
+ 636, 556, 616, 550, 656, 566, 610, 570, 632, 578, 608, 1640,
+ 662, 562, 642, 1686, 582, 570, 634, 566, 604, 576, 636, 566,
+ 610, 578, 634, 1664, 584, 590, 660, 1636, 610, 1642, 664, 590,
+ 610, 590, 636, 566, 634, 568, 686}; // UNKNOWN 9AD8CDB5
+ uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0x87, 0xF6, 0x28, 0x60,
+ 0x00, 0x20, 0x00, 0x00, 0x20,
+ 0x00, 0x05, 0x0D};
+
+ irsend.reset();
+ irsend.sendRaw(rawData, 211, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(ELECTRA_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kElectraAcBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 3 (Low), "
+ "Swing(V): Off, Swing(H): Off",
+ IRAcUtils::resultAcToString(&irsend.capture));
+}
+
+TEST(TestIRElectraAcClass, Power) {
+ IRElectraAc ac(0);
+ ac.begin();
+
+ ac.on();
+ EXPECT_TRUE(ac.getPower());
+
+ ac.off();
+ EXPECT_FALSE(ac.getPower());
+
+ ac.setPower(true);
+ EXPECT_TRUE(ac.getPower());
+
+ ac.setPower(false);
+ EXPECT_FALSE(ac.getPower());
+}
+
+TEST(TestIRElectraAcClass, OperatingMode) {
+ IRElectraAc ac(0);
+ ac.begin();
+
+ ac.setMode(kElectraAcAuto);
+ EXPECT_EQ(kElectraAcAuto, ac.getMode());
+
+ ac.setMode(kElectraAcCool);
+ EXPECT_EQ(kElectraAcCool, ac.getMode());
+
+ ac.setMode(kElectraAcHeat);
+ EXPECT_EQ(kElectraAcHeat, ac.getMode());
+
+ ac.setMode(kElectraAcDry);
+ EXPECT_EQ(kElectraAcDry, ac.getMode());
+
+ ac.setMode(kElectraAcFan);
+ EXPECT_EQ(kElectraAcFan, ac.getMode());
+
+ ac.setMode(kElectraAcHeat + 1);
+ EXPECT_EQ(kElectraAcAuto, ac.getMode());
+
+ ac.setMode(255);
+ EXPECT_EQ(kElectraAcAuto, ac.getMode());
+}
+
+TEST(TestIRElectraAcClass, SetAndGetTemp) {
+ IRElectraAc ac(0);
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+ ac.setTemp(kElectraAcMinTemp);
+ EXPECT_EQ(kElectraAcMinTemp, ac.getTemp());
+ ac.setTemp(kElectraAcMinTemp - 1);
+ EXPECT_EQ(kElectraAcMinTemp, ac.getTemp());
+ ac.setTemp(kElectraAcMaxTemp);
+ EXPECT_EQ(kElectraAcMaxTemp, ac.getTemp());
+ ac.setTemp(kElectraAcMaxTemp + 1);
+ EXPECT_EQ(kElectraAcMaxTemp, ac.getTemp());
+}
+
+TEST(TestIRElectraAcClass, FanSpeed) {
+ IRElectraAc ac(0);
+ ac.begin();
+
+ ac.setFan(0);
+ EXPECT_EQ(kElectraAcFanAuto, ac.getFan());
+
+ ac.setFan(255);
+ EXPECT_EQ(kElectraAcFanAuto, ac.getFan());
+
+ ac.setFan(kElectraAcFanHigh);
+ EXPECT_EQ(kElectraAcFanHigh, ac.getFan());
+
+ ac.setFan(std::max(kElectraAcFanHigh, kElectraAcFanLow) + 1);
+ EXPECT_EQ(kElectraAcFanAuto, ac.getFan());
+
+ ac.setFan(kElectraAcFanHigh - 1);
+ EXPECT_EQ(kElectraAcFanAuto, ac.getFan());
+
+ ac.setFan(1);
+ EXPECT_EQ(1, ac.getFan());
+
+ ac.setFan(1);
+ EXPECT_EQ(1, ac.getFan());
+
+ ac.setFan(3);
+ EXPECT_EQ(3, ac.getFan());
+}
+
+TEST(TestIRElectraAcClass, toCommon) {
+ IRElectraAc ac(0);
+ ac.setPower(true);
+ ac.setMode(kElectraAcCool);
+ ac.setTemp(20);
+ ac.setFan(kElectraAcFanHigh);
+ ac.setSwingV(true);
+ ac.setSwingH(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::ELECTRA_AC, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestIRElectraAcClass, HumanReadable) {
+ IRElectraAc ac(0);
+ // Data from:
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/778#issue-460052080
+ uint8_t on_cool_32C_auto_voff[13] = {
+ 0xC3, 0xC7, 0xE0, 0x00, 0xA0, 0x00, 0x20,
+ 0x00, 0x00, 0x20, 0x00, 0x40, 0x8A};
+ ac.setRaw(on_cool_32C_auto_voff);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 32C, Fan: 5 (Auto), "
+ "Swing(V): Off, Swing(H): Off", ac.toString());
+ uint8_t on_cool_16C_auto_voff[13] = {
+ 0xC3, 0x47, 0xE0, 0x00, 0xA0, 0x00, 0x20,
+ 0x00, 0x00, 0x20, 0x00, 0x41, 0x0B};
+ ac.setRaw(on_cool_16C_auto_voff);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 5 (Auto), "
+ "Swing(V): Off, Swing(H): Off", ac.toString());
+ uint8_t on_cool_16C_low_voff[13] = {
+ 0xC3, 0x47, 0xE0, 0x00, 0x60, 0x00, 0x20,
+ 0x00, 0x00, 0x20, 0x00, 0x41, 0xCB};
+ ac.setRaw(on_cool_16C_low_voff);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 3 (Low), "
+ "Swing(V): Off, Swing(H): Off", ac.toString());
+}
diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Fujitsu_test.cpp
new file mode 100644
index 000000000..b6613906f
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Fujitsu_test.cpp
@@ -0,0 +1,798 @@
+// Copyright 2017 Jonny Graham, David Conran
+
+#include "IRrecv_test.h"
+#include "IRsend.h"
+#include "IRsend_test.h"
+#include "ir_Fujitsu.h"
+#include "gtest/gtest.h"
+
+// Tests for Fujitsu A/C methods.
+
+// Test sending typical data only.
+TEST(TestIRFujitsuACClass, GetRawDefault) {
+ IRFujitsuAC ac(0); // AR-RAH2E
+ ac.setSwing(kFujitsuAcSwingBoth);
+ ac.setMode(kFujitsuAcModeCool);
+ ac.setFanSpeed(kFujitsuAcFanHigh);
+ ac.setTemp(24);
+ ac.setCmd(kFujitsuAcCmdTurnOn);
+ uint8_t expected_arrah2e[16] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
+ 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD};
+ EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8);
+ EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
+ EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 1 (High), Swing: Vert + Horiz, Command: N/A",
+ ac.toString());
+
+ uint8_t expected_ardb1[15] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
+ 0x81, 0x01, 0x01, 0x00, 0x00, 0x00, 0x4D};
+ ac.setModel(ARDB1);
+ EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), 15 * 8);
+ EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
+ EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 1 (High), Command: N/A",
+ ac.toString());
+}
+
+TEST(TestIRFujitsuACClass, GetRawTurnOff) {
+ IRFujitsuAC ac(0);
+ ac.setModel(ARRAH2E);
+ ac.off();
+ uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD};
+ EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 7 * 8);
+ EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
+ EXPECT_EQ("Model: 1 (ARRAH2E), Power: Off, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 1 (High), Swing: Vert + Horiz, Command: N/A",
+ ac.toString());
+
+ ac.setModel(ARDB1);
+ uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02};
+ EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), 6 * 8);
+ EXPECT_EQ(kFujitsuAcStateLengthShort - 1, ac.getStateLength());
+ EXPECT_EQ("Model: 2 (ARDB1), Power: Off, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 1 (High), Command: N/A",
+ ac.toString());
+}
+
+TEST(TestIRFujitsuACClass, GetRawStepHoriz) {
+ IRFujitsuAC ac(0);
+ ac.stepHoriz();
+ uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x79, 0x86};
+ EXPECT_STATE_EQ(expected, ac.getRaw(), 7 * 8);
+ EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
+ EXPECT_EQ(
+ "Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 1 (High), Swing: Vert + Horiz, Command: Step vane horizontally",
+ ac.toString());
+}
+
+TEST(TestIRFujitsuACClass, GetRawStepVert) {
+ IRFujitsuAC ac(0);
+ ac.setModel(ARRAH2E);
+ ac.stepVert();
+ uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C, 0x93};
+ EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 7 * 8);
+ EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
+ EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 1 (High), Swing: Vert + Horiz, Command: Step vane vertically",
+ ac.toString());
+
+ ac.setModel(ARDB1);
+ ac.stepVert();
+ uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C};
+ EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), 6 * 8);
+ EXPECT_EQ(kFujitsuAcStateLengthShort - 1,
+ ac.getStateLength());
+ EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 1 (High), Command: Step vane vertically",
+ ac.toString());
+}
+
+TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) {
+ IRFujitsuAC ac(0);
+ ac.setCmd(kFujitsuAcCmdStayOn);
+ ac.setSwing(kFujitsuAcSwingHoriz);
+ ac.setMode(kFujitsuAcModeCool);
+ ac.setFanSpeed(kFujitsuAcFanQuiet);
+ ac.setTemp(25);
+ uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30,
+ 0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB};
+ EXPECT_STATE_EQ(expected, ac.getRaw(), 16 * 8);
+ EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 25C, "
+ "Fan: 4 (Quiet), Swing: Horiz, Command: N/A",
+ ac.toString());
+}
+
+TEST(TestIRFujitsuACClass, GetRawWithFan) {
+ IRFujitsuAC ac(0);
+ ac.setCmd(kFujitsuAcCmdStayOn);
+ ac.setSwing(kFujitsuAcSwingHoriz);
+ ac.setMode(kFujitsuAcModeFan);
+ ac.setFanSpeed(kFujitsuAcFanMed);
+ ac.setTemp(20); // temp doesn't matter for fan
+ // but it is sent by the RC anyway
+ ac.setModel(ARRAH2E);
+ uint8_t expected_arrah2e[16] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
+ 0x40, 0x03, 0x22, 0x00, 0x00, 0x00, 0x20, 0x4B};
+ EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8);
+ EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
+ EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 3 (FAN), Temp: 20C, "
+ "Fan: 2 (Medium), Swing: Horiz, Command: N/A", ac.toString());
+
+ ac.setModel(ARDB1);
+ uint8_t expected_ardb1[15] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
+ 0x40, 0x03, 0x02, 0x00, 0x00, 0x00, 0x8B};
+ EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
+ EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), ac.getStateLength() * 8);
+ EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 3 (FAN), Temp: 20C, "
+ "Fan: 2 (Medium), Command: N/A", ac.toString());
+}
+
+TEST(TestIRFujitsuACClass, SetRaw) {
+ IRFujitsuAC ac(0);
+ EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
+ uint8_t expected_default_arrah2e[kFujitsuAcStateLength] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
+ 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD};
+ EXPECT_STATE_EQ(expected_default_arrah2e, ac.getRaw(),
+ ac.getStateLength() * 8);
+ EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 1 (High), Swing: Vert + Horiz, Command: N/A",
+ ac.toString());
+ // Now set a new state via setRaw();
+ // This state is a real state from an AR-DB1 remote.
+ uint8_t new_state1[kFujitsuAcStateLength - 1] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
+ 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9F};
+ ac.setRaw(new_state1, kFujitsuAcStateLength - 1);
+ EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
+ EXPECT_STATE_EQ(new_state1, ac.getRaw(), ac.getStateLength() * 8);
+ EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 19C, "
+ "Fan: 0 (Auto), Command: N/A", ac.toString());
+}
+
+TEST(TestSendFujitsuAC, GenerateMessage) {
+ IRFujitsuAC ac(0);
+ IRsendTest irsend(0);
+ ac.begin();
+ irsend.begin();
+
+ ac.setCmd(kFujitsuAcCmdStayOn);
+ ac.setSwing(kFujitsuAcSwingBoth);
+ ac.setMode(kFujitsuAcModeCool);
+ ac.setFanSpeed(kFujitsuAcFanHigh);
+ ac.setTemp(24);
+
+ EXPECT_EQ(kFujitsuAcFanHigh, ac.getFanSpeed());
+ EXPECT_EQ(kFujitsuAcModeCool, ac.getMode());
+ EXPECT_EQ(24, ac.getTemp());
+ EXPECT_EQ(kFujitsuAcSwingBoth, ac.getSwing());
+ EXPECT_EQ(kFujitsuAcCmdStayOn, ac.getCmd());
+
+ irsend.reset();
+ irsend.sendFujitsuAC(ac.getRaw(), kFujitsuAcStateLength);
+ EXPECT_EQ(
+ "f38000d50"
+ "m3324s1574"
+ "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390"
+ "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
+ "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182"
+ "m448s1182m448s390m448s390m448s1182m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s1182"
+ "m448s1182m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s390"
+ "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182"
+ "m448s8100",
+ irsend.outputStr());
+}
+
+TEST(TestSendFujitsuAC, GenerateShortMessage) {
+ IRFujitsuAC ac(0);
+ IRsendTest irsend(0);
+ ac.begin();
+ irsend.begin();
+
+ ac.off();
+
+ EXPECT_EQ(kFujitsuAcCmdTurnOff, ac.getCmd());
+
+ irsend.reset();
+ irsend.sendFujitsuAC(ac.getRaw(), kFujitsuAcStateLengthShort);
+ EXPECT_EQ(
+ "f38000d50"
+ "m3324s1574m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448"
+ "s390m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s1182m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s1182m448"
+ "s1182m448s1182m448s1182m448s1182m448s1182m448s8100",
+ irsend.outputStr());
+}
+
+// Issue #275
+TEST(TestSendFujitsuAC, Issue275) {
+ IRFujitsuAC ac(0);
+ IRsendTest irsend(0);
+ ac.begin();
+ irsend.begin();
+ irsend.reset();
+
+ ac.setCmd(kFujitsuAcCmdTurnOff);
+ irsend.sendFujitsuAC(ac.getRaw(), kFujitsuAcStateLengthShort);
+ EXPECT_EQ(
+ "f38000d50"
+ // Header
+ "m3324s1574"
+ // 0 0 1 0 1 0 0 0 (0x28)
+ "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390"
+ // 1 1 0 0 0 1 1 0 (0xC6)
+ "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390"
+ // 0 0 0 0 0 0 0 0 (0x00)
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ // 0 0 0 0 1 0 0 0 (0x08)
+ "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
+ // 0 0 0 0 1 0 0 0 (0x08)
+ "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
+ // 0 1 0 0 0 0 0 0 (0x40)
+ "m448s390m448s1182m448s390m448s390m448s390m448s390m448s390m448s390"
+ // 1 0 1 1 1 1 1 1 (0xBF)
+ "m448s1182m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182"
+ // Footer
+ "m448s8100", irsend.outputStr());
+
+ irsend.reset();
+ // Per report in Issue #275
+ uint16_t off[115] = {
+ 3350, 1650,
+ 450, 400, 450, 450, 450, 1250, 450, 400, 450, 1250, 450, 400, 450, 400,
+ 450, 400, 450, 1250, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 1250,
+ 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400,
+ 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400,
+ 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400,
+ 450, 400, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250,
+ 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250,
+ 450, 400, 450, 1250, 450, 1250, 450, 1250, 450, 1250, 450, 1250,
+ 450, 1250, 450};
+ irsend.sendRaw(off, 115, 38);
+ EXPECT_EQ(
+ "f38000d50"
+ // Header
+ "m3350s1650"
+ // 0 0 1 0 1 0 0 0 (0x28)
+ "m450s400m450s450m450s1250m450s400m450s1250m450s400m450s400m450s400"
+ // 1 1 0 0 0 1 1 0 (0xC6)
+ "m450s1250m450s1250m450s400m450s400m450s400m450s1250m450s1250m450s400"
+ // 0 0 0 0 0 0 0 0 (0x00)
+ "m450s400m450s400m450s400m450s400m450s400m450s400m450s400m450s400"
+ // 0 0 0 0 1 0 0 0 (0x08)
+ "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400"
+ // 0 0 0 0 1 0 0 0 (0x08)
+ "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400"
+ // 0 1 0 0 0 0 0 0 (0x40)
+ "m450s400m450s1250m450s400m450s400m450s400m450s400m450s400m450s400"
+ // 1 0 1 1 1 1 1 1 (0xBF)
+ "m450s1250m450s400m450s1250m450s1250m450s1250m450s1250m450s1250m450s1250"
+ // Footer
+ "m450",
+ irsend.outputStr());
+}
+
+TEST(TestDecodeFujitsuAC, SyntheticShortMessages) {
+ IRsendTest irsend(0);
+ IRFujitsuAC ac(0);
+ IRrecv irrecv(0);
+
+ irsend.begin();
+ irsend.reset();
+
+ ac.setModel(ARRAH2E);
+ ac.setCmd(kFujitsuAcCmdTurnOff);
+ irsend.sendFujitsuAC(ac.getRaw(), ac.getStateLength());
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcMinBits + 8, irsend.capture.bits);
+ uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD};
+ EXPECT_STATE_EQ(expected_arrah2e, irsend.capture.state, irsend.capture.bits);
+
+ irsend.reset();
+
+ ac.setModel(ARDB1);
+ ac.setCmd(kFujitsuAcCmdTurnOff);
+ irsend.sendFujitsuAC(ac.getRaw(), ac.getStateLength());
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcMinBits, irsend.capture.bits);
+ uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02};
+ EXPECT_STATE_EQ(expected_ardb1, irsend.capture.state, irsend.capture.bits);
+}
+
+TEST(TestDecodeFujitsuAC, SyntheticLongMessages) {
+ IRsendTest irsend(0);
+ IRFujitsuAC ac(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ irsend.reset();
+
+ ac.setModel(ARRAH2E);
+ ac.setCmd(kFujitsuAcCmdStayOn);
+ ac.setSwing(kFujitsuAcSwingVert);
+ ac.setMode(kFujitsuAcModeCool);
+ ac.setFanSpeed(kFujitsuAcFanQuiet);
+ ac.setTemp(18);
+ irsend.sendFujitsuAC(ac.getRaw(), ac.getStateLength());
+ ASSERT_EQ(kFujitsuAcStateLength, ac.getStateLength());
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decodeFujitsuAC(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits);
+ uint8_t expected_arrah2e[kFujitsuAcStateLength] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
+ 0x20, 0x01, 0x14, 0x00, 0x00, 0x00, 0x20, 0x7B};
+ EXPECT_STATE_EQ(expected_arrah2e, irsend.capture.state, irsend.capture.bits);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
+ EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 18C, "
+ "Fan: 4 (Quiet), Swing: Vert, Command: N/A", ac.toString());
+
+ irsend.reset();
+
+ ac.setModel(ARDB1);
+ irsend.sendFujitsuAC(ac.getRaw(), ac.getStateLength());
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits);
+ uint8_t expected_ardb1[kFujitsuAcStateLength - 1] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
+ 0x20, 0x01, 0x04, 0x00, 0x00, 0x00, 0xAB};
+ EXPECT_STATE_EQ(expected_ardb1, irsend.capture.state, irsend.capture.bits);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
+ EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 18C, "
+ "Fan: 4 (Quiet), Command: N/A", ac.toString());
+}
+
+TEST(TestDecodeFujitsuAC, RealShortARDB1OffExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ IRFujitsuAC ac(0);
+
+ irsend.begin();
+
+ irsend.reset();
+ // "Off" Message recorded from an AR-DB1 remote.
+ uint16_t rawData[99] = {
+ 3310, 1636, 440, 386, 440, 394, 442, 1210, 442, 390, 414, 1220,
+ 444, 390, 446, 380, 446, 380, 436, 1216, 438, 1214, 438, 388,
+ 438, 386, 438, 396, 410, 1222, 440, 1220, 442, 384, 442, 384,
+ 442, 384, 442, 382, 444, 382, 442, 382, 444, 380, 446, 380,
+ 446, 380, 444, 380, 436, 390, 436, 388, 436, 388, 438, 1214,
+ 438, 386, 438, 388, 438, 386, 440, 386, 440, 384, 442, 384,
+ 442, 384, 442, 1210, 444, 382, 444, 382, 444, 382, 444, 380,
+ 446, 1206, 436, 390, 436, 388, 436, 388, 438, 388, 438, 396,
+ 420, 388, 436};
+ irsend.sendRaw(rawData, 99, 38000);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcMinBits, irsend.capture.bits);
+ uint8_t expected[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02};
+ EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(kFujitsuAcStateLengthShort - 1, ac.getStateLength());
+ EXPECT_EQ("Model: 2 (ARDB1), Power: Off, Mode: 0 (AUTO), Temp: 16C, "
+ "Fan: 0 (Auto), Command: N/A", ac.toString());
+}
+
+TEST(TestDecodeFujitsuAC, RealLongARDB1Example) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ IRFujitsuAC ac(0);
+
+ irsend.begin();
+ irsend.reset();
+ uint16_t rawData1[243] = {
+ 3316, 1632, 444, 390, 438, 388, 436, 1216, 438, 388, 438, 1214,
+ 438, 388, 438, 386, 440, 386, 440, 1212, 440, 1210, 442, 392,
+ 412, 396, 442, 392, 444, 1208, 444, 1208, 444, 380, 444, 380,
+ 446, 380, 436, 390, 436, 390, 436, 390, 436, 388, 438, 388,
+ 438, 388, 438, 388, 438, 386, 438, 386, 440, 384, 440, 1210,
+ 442, 384, 442, 382, 442, 384, 442, 384, 442, 382, 442, 382,
+ 444, 382, 444, 1208, 444, 382, 444, 380, 446, 380, 436, 390,
+ 436, 390, 436, 1214, 438, 1214, 438, 1212, 440, 1212, 440, 1220,
+ 412, 1222, 440, 394, 442, 382, 442, 382, 444, 1208, 444, 382,
+ 444, 380, 446, 380, 446, 380, 434, 390, 436, 388, 438, 388,
+ 438, 388, 438, 1214, 438, 1212, 440, 386, 440, 394, 412, 1222,
+ 440, 394, 442, 384, 442, 384, 442, 382, 442, 1208, 444, 390,
+ 414, 394, 442, 1216, 446, 380, 436, 390, 436, 390, 436, 388,
+ 436, 390, 436, 388, 438, 386, 440, 386, 440, 386, 438, 1212,
+ 440, 386, 440, 384, 440, 384, 442, 392, 412, 396, 440, 394,
+ 442, 382, 444, 382, 444, 382, 444, 380, 444, 380, 444, 382,
+ 444, 380, 446, 380, 436, 388, 436, 390, 436, 388, 438, 388,
+ 438, 388, 438, 388, 438, 386, 440, 386, 440, 386, 442, 384,
+ 440, 386, 442, 384, 440, 384, 442, 384, 442, 382, 442, 382,
+ 444, 1208, 444, 382, 444, 1208, 444, 380, 446, 1206, 436, 390,
+ 436, 1216, 436};
+ irsend.sendRaw(rawData1, 243, 38000);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits);
+ uint8_t expected1[kFujitsuAcStateLength - 1] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
+ 0x21, 0x01, 0x04, 0x00, 0x00, 0x00, 0xAA};
+ EXPECT_STATE_EQ(expected1, irsend.capture.state, irsend.capture.bits);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
+ EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 18C, "
+ "Fan: 4 (Quiet), Command: N/A", ac.toString());
+
+ irsend.reset();
+ uint16_t rawData2[243] = {
+ 3316, 1630, 436, 398, 438, 386, 438, 1212, 440, 384, 440, 1212,
+ 442, 384, 442, 392, 414, 394, 442, 1218, 446, 1206, 436, 390,
+ 436, 388, 438, 388, 438, 1214, 440, 1212, 440, 384, 442, 384,
+ 442, 384, 442, 382, 444, 382, 444, 382, 444, 380, 446, 380,
+ 444, 380, 436, 390, 436, 388, 438, 396, 418, 388, 438, 1232,
+ 410, 396, 440, 394, 442, 384, 442, 384, 442, 382, 442, 392,
+ 414, 392, 444, 1216, 446, 380, 436, 390, 436, 396, 418, 390,
+ 436, 398, 438, 1214, 440, 1212, 440, 1210, 442, 1208, 444, 1216,
+ 416, 1218, 444, 388, 436, 390, 436, 388, 438, 1214, 440, 386,
+ 438, 386, 440, 386, 440, 384, 442, 384, 442, 384, 442, 382,
+ 444, 382, 444, 1206, 446, 1206, 436, 390, 436, 388, 438, 388,
+ 438, 386, 440, 394, 410, 396, 440, 1220, 442, 1210, 442, 392,
+ 414, 394, 442, 1218, 446, 406, 410, 388, 436, 390, 436, 390,
+ 436, 388, 438, 386, 440, 386, 440, 386, 440, 386, 440, 384,
+ 442, 384, 442, 384, 442, 382, 444, 382, 444, 380, 446, 380,
+ 446, 380, 436, 390, 436, 390, 436, 388, 438, 386, 438, 388,
+ 438, 386, 440, 386, 440, 384, 442, 384, 442, 384, 442, 384,
+ 442, 382, 444, 382, 444, 380, 446, 380, 446, 380, 436, 390,
+ 436, 388, 436, 388, 438, 386, 438, 386, 440, 386, 440, 1212,
+ 440, 1210, 442, 1210, 442, 1208, 444, 1208, 436, 390, 436, 388,
+ 436, 1214, 440};
+ irsend.sendRaw(rawData2, 243, 38000);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits);
+ uint8_t expected2[kFujitsuAcStateLength - 1] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30,
+ 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9F};
+ EXPECT_STATE_EQ(expected2, irsend.capture.state, irsend.capture.bits);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
+ EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 19C, "
+ "Fan: 0 (Auto), Command: N/A", ac.toString());
+}
+
+TEST(TestDecodeFujitsuAC, Issue414) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ IRFujitsuAC ac(0);
+
+ // Capture as supplied by arpmota
+ uint16_t rawData[259] = {3352, 1574, 480, 350, 480, 346, 480, 1190, 458, 346,
+ 508, 1140, 480, 346, 506, 346, 458, 346, 480, 1168, 480, 1192, 452, 374,
+ 458, 346, 480, 346, 508, 1168, 480, 1140, 480, 346, 506, 346, 458, 346,
+ 480, 346, 480, 346, 480, 346, 484, 372, 454, 374, 456, 346, 508, 318,
+ 480, 374, 458, 374, 480, 318, 480, 1196, 452, 346, 480, 346, 484, 342,
+ 484, 346, 480, 374, 458, 346, 506, 318, 508, 1170, 452, 346, 480, 374,
+ 458, 346, 506, 318, 480, 1196, 452, 1190, 458, 1162, 480, 1196, 452,
+ 1170, 480, 1190, 458, 1164, 480, 1196, 480, 318, 508, 346, 456, 1192,
+ 480, 346, 456, 374, 452, 346, 480, 374, 458, 342, 484, 346, 508, 346,
+ 456, 342, 512, 1164, 458, 1164, 508, 346, 456, 346, 480, 1190, 456, 342,
+ 484, 346, 506, 346, 456, 374, 452, 346, 508, 346, 458, 1164, 508, 346,
+ 458, 374, 452, 1168, 480, 374, 480, 318, 480, 374, 456, 346, 508, 318,
+ 480, 346, 484, 374, 480, 318, 484, 342, 484, 374, 480, 318, 484, 342,
+ 484, 346, 508, 318, 508, 346, 458, 346, 506, 318, 480, 374, 458, 346,
+ 506, 318, 480, 346, 484, 374, 480, 318, 482, 372, 456, 346, 508, 318,
+ 506, 348, 456, 342, 484, 346, 508, 318, 484, 374, 480, 318, 508, 318,
+ 484, 346, 508, 318, 480, 374, 456, 346, 508, 346, 480, 318, 480, 346,
+ 484, 374, 480, 320, 484, 1164, 508, 346, 458, 342, 512, 1164, 458, 1190,
+ 454, 346, 484, 1164, 508, 346, 458, 1164, 480, 350, 480, 374, 480};
+ uint8_t state[16] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, 0x81, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x2B};
+ irsend.begin();
+ irsend.reset();
+ irsend.sendRaw(rawData, 259, 38000);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(state, irsend.capture.state, irsend.capture.bits);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
+ EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 4 (HEAT), Temp: 24C, "
+ "Fan: 0 (Auto), Swing: Off, Command: N/A", ac.toString());
+
+ // Resend it using the state this time.
+ irsend.reset();
+ irsend.sendFujitsuAC(state, 16);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(state, irsend.capture.state, irsend.capture.bits);
+ EXPECT_EQ(
+ "f38000d50"
+ "m3324s1574"
+ "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390"
+ "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390"
+ "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182"
+ "m448s1182m448s390m448s390m448s1182m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390"
+ "m448s1182m448s390m448s390m448s390m448s390m448s390m448s390m448s1182"
+ "m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390"
+ "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s390"
+ "m448s1182m448s1182m448s390m448s1182m448s390m448s1182m448s390m448s390"
+ "m448s8100", irsend.outputStr());
+}
+
+TEST(TestIRFujitsuACClass, toCommon) {
+ IRFujitsuAC ac(0);
+ ac.setMode(kFujitsuAcModeCool);
+ ac.setTemp(20);
+ ac.setFanSpeed(kFujitsuAcFanQuiet);
+ ac.setSwing(kFujitsuAcSwingBoth);
+
+ // Now test it.
+ ASSERT_EQ(decode_type_t::FUJITSU_AC, ac.toCommon().protocol);
+ ASSERT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_TRUE(ac.toCommon().quiet);
+
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMin, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+
+ // Check off mode which is special.
+ ac.off();
+ ASSERT_FALSE(ac.toCommon().power);
+ ac.send();
+ ac.stateReset();
+ IRrecv irrecv(0);
+ ac._irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&ac._irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type);
+ ac.setRaw(ac._irsend.capture.state, ac._irsend.capture.bits / 8);
+
+ // Now test it.
+ EXPECT_EQ( // Off mode technically has no temp, mode, fan, etc.
+ "Model: 1 (ARRAH2E), Power: Off, Mode: 0 (AUTO), Temp: 16C, "
+ "Fan: 0 (Auto), Swing: Off, Command: N/A", ac.toString());
+ ASSERT_EQ(decode_type_t::FUJITSU_AC, ac.toCommon().protocol);
+ ASSERT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.toCommon().model);
+ ASSERT_FALSE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(16, ac.toCommon().degrees);
+ ASSERT_FALSE(ac.toCommon().quiet);
+
+ ASSERT_EQ(stdAc::opmode_t::kAuto, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kAuto, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestDecodeFujitsuAC, Issue716) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ IRFujitsuAC ac(0);
+
+ // Powerful command from a raw data capture.
+ // Capture as supplied by u4mzu4
+ uint16_t rawData[115] = {
+ 3320, 1610, 432, 406, 432, 406, 432, 1220, 432, 406, 432, 1192, 458, 406,
+ 432, 406, 432, 406, 432, 1218, 432, 1220, 432, 406, 432, 406, 432, 406,
+ 432, 1192, 458, 1192, 460, 406, 432, 406, 432, 406, 432, 406, 432, 406,
+ 432, 406, 432, 406, 432, 408, 432, 406, 432, 406, 430, 406, 432, 406, 432,
+ 406, 432, 1190, 460, 406, 432, 408, 430, 406, 432, 406, 432, 406, 432,
+ 406, 432, 406, 434, 1192, 458, 406, 432, 406, 432, 406, 432, 1194, 458,
+ 406, 432, 406, 432, 1194, 456, 1196, 454, 1220, 432, 406, 432, 406, 432,
+ 408, 430, 1194, 458, 1194, 456, 406, 432, 406, 430, 406, 432, 1194, 458,
+ 1194, 458}; // FUJITSU_AC
+ uint8_t powerful[kFujitsuAcStateLengthShort] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0x39, 0xC6};
+ irsend.begin();
+ irsend.reset();
+ irsend.sendRaw(rawData, 115, 38000);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcStateLengthShort * 8, irsend.capture.bits);
+ EXPECT_STATE_EQ(powerful, irsend.capture.state, irsend.capture.bits);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(fujitsu_ac_remote_model_t::ARREB1E, ac.getModel());
+ EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
+ EXPECT_EQ("Model: 3 (ARREB1E), Power: On, Mode: 0 (AUTO), Temp: 16C, "
+ "Fan: 0 (Auto), Swing: Off, Command: Powerful, Outside Quiet: Off",
+ ac.toString());
+
+ // Economy (just from the state)
+ uint8_t econo[kFujitsuAcStateLengthShort] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0x09, 0xF6};
+ // Make sure we can't accidentally inherit the correct model.
+ ASSERT_NE(fujitsu_ac_remote_model_t::ARDB1,
+ fujitsu_ac_remote_model_t::ARREB1E);
+ ac.setModel(fujitsu_ac_remote_model_t::ARDB1);
+ ac.setRaw(econo, kFujitsuAcStateLengthShort);
+ EXPECT_EQ(fujitsu_ac_remote_model_t::ARREB1E, ac.getModel());
+ EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
+ EXPECT_EQ("Model: 3 (ARREB1E), Power: On, Mode: 0 (AUTO), Temp: 16C, "
+ "Fan: 0 (Auto), Swing: Off, Command: Economy, Outside Quiet: Off",
+ ac.toString());
+}
+
+TEST(TestIRFujitsuACClass, OutsideQuiet) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ IRFujitsuAC ac(0);
+
+ ASSERT_NE(fujitsu_ac_remote_model_t::ARDB1,
+ fujitsu_ac_remote_model_t::ARREB1E);
+ ASSERT_NE(fujitsu_ac_remote_model_t::ARRAH2E,
+ fujitsu_ac_remote_model_t::ARREB1E);
+ // States as supplied by u4mzu4
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/716#issuecomment-495852309
+ uint8_t off[kFujitsuAcStateLength] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2F};
+ uint8_t on[kFujitsuAcStateLength] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xAF};
+ // Make sure we can't accidentally inherit the correct model.
+ ac.setModel(fujitsu_ac_remote_model_t::ARDB1);
+ ac.setRaw(off, kFujitsuAcStateLength);
+ EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.getModel());
+ EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
+ EXPECT_FALSE(ac.getOutsideQuiet());
+ // We can really only tell the difference between ARRAH2E & ARREB1E if
+ // the option is set. Otheriwse they appear the same.
+ EXPECT_EQ(
+ "Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 0 (Auto), Swing: Off, Command: N/A", ac.toString());
+ ac.setModel(fujitsu_ac_remote_model_t::ARREB1E);
+ EXPECT_EQ(
+ "Model: 3 (ARREB1E), Power: On, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 0 (Auto), Swing: Off, Command: N/A, Outside Quiet: Off",
+ ac.toString());
+
+ // Make sure we can't accidentally inherit the correct model.
+ ac.setModel(fujitsu_ac_remote_model_t::ARDB1);
+ ac.setRaw(on, kFujitsuAcStateLength);
+ EXPECT_EQ(fujitsu_ac_remote_model_t::ARREB1E, ac.getModel());
+ EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
+ EXPECT_TRUE(ac.getOutsideQuiet());
+ EXPECT_EQ(
+ "Model: 3 (ARREB1E), Power: On, Mode: 1 (COOL), Temp: 24C, "
+ "Fan: 0 (Auto), Swing: Off, Command: N/A, Outside Quiet: On",
+ ac.toString());
+
+ ac.setOutsideQuiet(false);
+ EXPECT_FALSE(ac.getOutsideQuiet());
+ ac.setOutsideQuiet(true);
+ EXPECT_TRUE(ac.getOutsideQuiet());
+ ac.setOutsideQuiet(false);
+ EXPECT_FALSE(ac.getOutsideQuiet());
+}
+
+TEST(TestIRFujitsuACClass, toggleSwing) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ IRFujitsuAC ac(0);
+
+ ac.begin();
+ ac.setModel(ARJW2);
+ ac.setSwing(kFujitsuAcSwingOff);
+ ac.setCmd(kFujitsuAcCmdStayOn);
+ ASSERT_EQ(kFujitsuAcSwingOff, ac.getSwing());
+ ac.toggleSwingHoriz();
+ EXPECT_EQ(kFujitsuAcCmdToggleSwingHoriz, ac.getCmd());
+ EXPECT_EQ(kFujitsuAcSwingHoriz, ac.getSwing());
+ ac.toggleSwingHoriz();
+ EXPECT_EQ(kFujitsuAcCmdToggleSwingHoriz, ac.getCmd());
+ EXPECT_EQ(kFujitsuAcSwingOff, ac.getSwing());
+ ac.toggleSwingVert();
+ EXPECT_EQ(kFujitsuAcCmdToggleSwingVert, ac.getCmd());
+ EXPECT_EQ(kFujitsuAcSwingVert, ac.getSwing());
+ ac.toggleSwingVert();
+ EXPECT_EQ(kFujitsuAcCmdToggleSwingVert, ac.getCmd());
+ EXPECT_EQ(kFujitsuAcSwingOff, ac.getSwing());
+
+ // Both
+ ac.toggleSwingHoriz();
+ EXPECT_EQ(kFujitsuAcCmdToggleSwingHoriz, ac.getCmd());
+ ac.toggleSwingVert();
+ EXPECT_EQ(kFujitsuAcCmdToggleSwingVert, ac.getCmd());
+ EXPECT_EQ(kFujitsuAcSwingBoth, ac.getSwing());
+ ac.toggleSwingHoriz();
+ EXPECT_EQ(kFujitsuAcCmdToggleSwingHoriz, ac.getCmd());
+ EXPECT_EQ(kFujitsuAcSwingVert, ac.getSwing());
+ ac.toggleSwingHoriz();
+ EXPECT_EQ(kFujitsuAcSwingBoth, ac.getSwing());
+
+ EXPECT_EQ(
+ "Model: 4 (ARJW2), Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (High), "
+ "Command: Toggle horizontal swing",
+ ac.toString());
+
+ // Test without the update set.
+ ac.toggleSwingHoriz(false);
+ EXPECT_EQ(kFujitsuAcSwingBoth, ac.getSwing());
+ EXPECT_EQ(kFujitsuAcCmdToggleSwingHoriz, ac.getCmd());
+ ac.toggleSwingVert(false);
+ EXPECT_EQ(kFujitsuAcSwingBoth, ac.getSwing());
+ EXPECT_EQ(kFujitsuAcCmdToggleSwingVert, ac.getCmd());
+}
+
+TEST(TestDecodeFujitsuAC, Issue726) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ IRFujitsuAC ac(0);
+
+ // fan:auto mode:auto temp:24 powerļ¼on
+ // Capture as supplied by huexpub
+ // Rawdata was very messy. Had to use `./auto_analyse_raw_data.py -r 250` to
+ // get it to parse due to timings being above tolerances.
+ uint8_t auto_auto_on_24[kFujitsuAcStateLength] = {
+ 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
+ 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2F};
+ irsend.begin();
+ irsend.reset();
+ irsend.sendFujitsuAC(auto_auto_on_24, 16);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kFujitsuAcStateLength * 8, irsend.capture.bits);
+ EXPECT_STATE_EQ(auto_auto_on_24, irsend.capture.state, irsend.capture.bits);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.getModel());
+ EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
+ EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 0 (AUTO), Temp: 24C, "
+ "Fan: 0 (Auto), Swing: Off, Command: N/A",
+ ac.toString());
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_GICable_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_GICable_test.cpp
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/test/ir_GICable_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_GICable_test.cpp
index bad9bbded..234a748b5 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_GICable_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_GICable_test.cpp
@@ -102,7 +102,7 @@ TEST(TestDecodeGICable, RealExampleDecodeOK) {
irsend.begin();
// Real GICable "OK/Select" message.
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/447
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/447
uint16_t rawData[39] = {9064, 4408, 580, 4408, 580, 2152, 578, 2150,
580, 2150, 580, 4408, 580, 2150, 580, 2150,
580, 2150, 580, 2150, 580, 2150, 580, 2150,
@@ -125,7 +125,7 @@ TEST(TestDecodeGICable, RealExampleDecodeLEFT) {
irsend.begin();
// Real GICable "LEFT" message.
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/447
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/447
uint16_t rawData[39] = {9040, 4434, 554, 2176, 580, 4408, 554, 4434,
582, 2148, 554, 4434, 580, 4408, 556, 2174,
580, 2150, 580, 2150, 582, 2148, 556, 2176,
@@ -149,7 +149,7 @@ TEST(TestDecodeGICable, RealExampleDecodeZEROKey) {
// Real GICable "Zero Key" message.
// Note: Zero key looks similar to a JVC message, hence this test.
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/447
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/447
uint16_t rawData[39] = {9036, 4434, 552, 2178, 552, 2178, 552, 2180,
550, 2178, 552, 2178, 550, 2180, 552, 2178,
552, 2178, 550, 2180, 552, 2178, 526, 2204,
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_GlobalCache_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_GlobalCache_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_GlobalCache_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_GlobalCache_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Goodweather_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Goodweather_test.cpp
new file mode 100644
index 000000000..58f42f0fe
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Goodweather_test.cpp
@@ -0,0 +1,511 @@
+// Copyright 2019 David Conran
+
+#include "ir_Goodweather.h"
+#include "IRrecv.h"
+#include "IRrecv_test.h"
+#include "IRsend.h"
+#include "IRsend_test.h"
+#include "gtest/gtest.h"
+
+TEST(TestIRUtils, Goodweather) {
+ ASSERT_EQ("GOODWEATHER", typeToString(decode_type_t::GOODWEATHER));
+ ASSERT_EQ(decode_type_t::GOODWEATHER, strToDecodeType("GOODWEATHER"));
+ ASSERT_FALSE(hasACState(decode_type_t::GOODWEATHER));
+}
+
+// Tests for sendGoodweather().
+
+// Test sending typical data only.
+TEST(TestSendGoodweather, SendDataOnly) {
+ IRsendTest irsend(0);
+ irsend.begin();
+
+ irsend.reset();
+ irsend.sendGoodweather(0x0);
+ EXPECT_EQ(
+ "f38000d50"
+ "m6800s6800"
+ "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600"
+ "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580"
+ "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600"
+ "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580"
+ "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600"
+ "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580"
+ "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600"
+ "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580"
+ "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600"
+ "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580"
+ "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600"
+ "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580"
+ "m640s6800m640s100000",
+ irsend.outputStr());
+
+ irsend.reset();
+}
+
+// Tests for decodeGoodweather().
+
+// Decode normal Goodweather messages.
+TEST(TestDecodeGoodweather, SyntheticDecode) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ // Normal (made-up value) Goodweather 48-bit message.
+ irsend.reset();
+ irsend.sendGoodweather(0x1234567890AB);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::GOODWEATHER, irsend.capture.decode_type);
+ EXPECT_EQ(kGoodweatherBits, irsend.capture.bits);
+ EXPECT_EQ(0x1234567890AB, irsend.capture.value);
+ EXPECT_EQ(0x0, irsend.capture.address);
+ EXPECT_EQ(0x0, irsend.capture.command);
+ EXPECT_FALSE(irsend.capture.repeat);
+ // Normal (Real) Goodweather 48-bit message.
+ irsend.reset();
+ irsend.sendGoodweather(0xD5276A030000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::GOODWEATHER, irsend.capture.decode_type);
+ EXPECT_EQ(kGoodweatherBits, irsend.capture.bits);
+ EXPECT_EQ(0xD5276A030000, irsend.capture.value);
+ EXPECT_EQ(0x0, irsend.capture.address);
+ EXPECT_EQ(0x0, irsend.capture.command);
+ EXPECT_FALSE(irsend.capture.repeat);
+}
+
+// Decode a real example of a Goodweather message.
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/697#issuecomment-490209819
+TEST(TestDecodeGoodweather, RealExampleDecode) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ IRGoodweatherAc ac(0);
+ irsend.begin();
+ ac.begin();
+
+ irsend.reset();
+ // Raw Goodweather 48-bit message.
+ uint16_t rawData_4624AB[197] = {
+ 6828, 6828, 732, 1780, 652, 1830, 652, 1806, 678, 1830, 652, 1806, 678,
+ 1830, 652, 1830, 652, 1834, 706, 518, 734, 508, 734, 514, 734, 510, 732,
+ 510, 732, 510, 732, 510, 732, 514, 732, 1776, 706, 1780, 628, 1854, 628,
+ 1832, 654, 1832, 654, 1856, 628, 1832, 634, 1876, 680, 536, 708, 536, 708,
+ 536, 706, 538, 706, 538, 706, 538, 706, 536, 680, 564, 680, 1828, 708,
+ 1758, 680, 1804, 680, 1828, 708, 1778, 732, 1754, 732, 1754, 732, 1756,
+ 732, 490, 658, 586, 658, 586, 658, 586, 658, 586, 658, 584, 658, 586, 658,
+ 586, 660, 1850, 704, 520, 658, 1828, 658, 1826, 658, 1826, 658, 586, 660,
+ 584, 684, 1826, 730, 490, 686, 1824, 660, 560, 710, 532, 710, 534, 712,
+ 1776, 712, 1774, 686, 560, 712, 1774, 712, 1798, 730, 492, 712, 1798, 684,
+ 1798, 678, 568, 730, 1756, 686, 1796, 686, 532, 712, 532, 712, 1796, 728,
+ 494, 712, 532, 738, 1772, 730, 492, 712, 532, 738, 506, 738, 1772, 660,
+ 582, 728, 1736, 712, 558, 710, 1750, 710, 558, 710, 510, 738, 1748, 738,
+ 508, 736, 1772, 684, 534, 736, 1772, 704, 518, 738, 1772, 660, 1824, 678,
+ 6770, 684}; // COOLIX 4624AB
+ irsend.sendRaw(rawData_4624AB, 197, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::GOODWEATHER, irsend.capture.decode_type);
+ EXPECT_EQ(kGoodweatherBits, irsend.capture.bits);
+ EXPECT_EQ(0xD52462000000, irsend.capture.value);
+ EXPECT_EQ(0x0, irsend.capture.address);
+ EXPECT_EQ(0x0, irsend.capture.command);
+ EXPECT_FALSE(irsend.capture.repeat);
+ ac.setRaw(irsend.capture.value);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 3 (Low), "
+ "Turbo: -, Light: -, Sleep: -, Swing: 0 (Fast), Command: 0 (Power)",
+ ac.toString());
+
+uint16_t rawData_FAD2BE31[197] = {
+ 6142, 7348, 570, 1612, 638, 1562, 620, 1584, 670, 1538, 566, 1638, 564,
+ 1610, 618, 1582, 642, 1542, 638, 498, 622, 518, 618, 496, 622, 518, 596,
+ 522, 596, 542, 618, 498, 618, 520, 594, 1590, 614, 1586, 618, 1588, 640,
+ 1592, 538, 1614, 612, 1584, 620, 1584, 616, 1592, 564, 546, 596, 540, 596,
+ 520, 620, 520, 594, 524, 618, 522, 650, 466, 616, 522, 670, 1532, 618, 1568,
+ 590, 1610, 618, 1612, 640, 1530, 594, 1586, 618, 1616, 590, 1586, 640, 472,
+ 618, 520, 672, 446, 618, 520, 646, 474, 616, 520, 622, 500, 614, 518, 624,
+ 1612, 560, 1616, 590, 1584, 620, 520, 646, 1540, 612, 518, 622, 516, 596,
+ 1586, 618, 518, 622, 498, 616, 520, 622, 1582, 616, 498, 620, 1582, 622,
+ 1586, 586, 528, 616, 1582, 622, 498, 616, 518, 624, 1582, 614, 1592, 568,
+ 544, 620, 1580, 648, 1542, 610, 520, 622, 1586, 666, 1536, 592, 518, 600,
+ 542, 594, 1592, 590, 544, 620, 498, 616, 518, 622, 1580, 620, 496, 620,
+ 1586, 618, 502, 610, 1584, 620, 518, 672, 446, 620, 1612, 592, 504, 608,
+ 1586, 618, 518, 646, 1540, 612, 520, 600, 1604, 622, 1582, 596, 7382, 566};
+ // UNKNOWN FAD2BE31
+
+ irsend.reset();
+ irsend.sendRaw(rawData_FAD2BE31, 197, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::GOODWEATHER, irsend.capture.decode_type);
+ EXPECT_EQ(kGoodweatherBits, irsend.capture.bits);
+ EXPECT_EQ(0xD52668000000, irsend.capture.value);
+ EXPECT_EQ(0x0, irsend.capture.address);
+ EXPECT_EQ(0x0, irsend.capture.command);
+ EXPECT_FALSE(irsend.capture.repeat);
+ ac.setRaw(irsend.capture.value);
+ EXPECT_EQ(
+ "Power: Off, Mode: 1 (COOL), Temp: 22C, Fan: 3 (Low), Turbo: -, "
+ "Light: -, Sleep: -, Swing: 2 (Off), Command: 0 (Power)",
+ ac.toString());
+
+ uint16_t rawData_5453D3AD[197] = {
+ 6190, 7298, 668, 1542, 614, 1590, 590, 1582, 620, 1584, 566, 1624, 632,
+ 1592, 616, 1588, 638, 1538, 594, 520, 620, 520, 594, 522, 620, 520, 586,
+ 530, 618, 520, 640, 480, 616, 520, 642, 1544, 612, 1588, 622, 1576, 668,
+ 1540, 564, 1640, 592, 1582, 646, 1558, 670, 1536, 594, 518, 622, 520, 594,
+ 522, 620, 520, 566, 552, 618, 520, 614, 504, 618, 518, 666, 1520, 610,
+ 1586, 618, 1612, 636, 1568, 564, 1590, 614, 1584, 620, 1582, 666, 1542,
+ 614, 526, 590, 520, 596, 520, 622, 520, 566, 550, 620, 520, 588, 530, 618,
+ 520, 668, 1536, 594, 520, 646, 1558, 668, 452, 616, 1584, 642, 498, 566,
+ 550, 618, 1582, 668, 454, 612, 1582, 646, 496, 594, 1614, 666, 450, 662,
+ 1536, 584, 1600, 612, 520, 642, 1590, 588, 502, 616, 520, 588, 1600, 612,
+ 1586, 616, 520, 612, 1574, 610, 1584, 644, 496, 564, 1620, 636, 1562, 640,
+ 524, 560, 530, 616, 1582, 644, 498, 620, 494, 670, 472, 622, 1558, 616,
+ 520, 642, 1564, 594, 518, 646, 1558, 668, 454, 638, 494, 668, 1538, 616,
+ 498, 642, 1558, 670, 454, 636, 1560, 642, 496, 614, 1592, 616, 1584, 620,
+ 7350, 668}; // UNKNOWN 5453D3AD
+
+ irsend.reset();
+ irsend.sendRaw(rawData_5453D3AD, 197, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::GOODWEATHER, irsend.capture.decode_type);
+ EXPECT_EQ(kGoodweatherBits, irsend.capture.bits);
+ EXPECT_EQ(0xD5266A000000, irsend.capture.value);
+ EXPECT_EQ(0x0, irsend.capture.address);
+ EXPECT_EQ(0x0, irsend.capture.command);
+ EXPECT_FALSE(irsend.capture.repeat);
+ ac.setRaw(irsend.capture.value);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 22C, Fan: 3 (Low), Turbo: -, "
+ "Light: -, Sleep: -, Swing: 2 (Off), Command: 0 (Power)",
+ ac.toString());
+
+ uint16_t rawData_B2354FBB[197] = {
+ 6192, 7298, 592, 1616, 618, 1584, 620, 1558, 668, 1520, 636, 1562, 642,
+ 1584, 590, 1614, 542, 1634, 622, 494, 668, 454, 638, 494, 670, 454, 638,
+ 492, 646, 480, 636, 494, 672, 470, 622, 1560, 642, 1556, 672, 1534, 614,
+ 1572, 636, 1584, 622, 1582, 644, 1534, 596, 1586, 642, 494, 666, 454, 640,
+ 494, 668, 452, 640, 494, 668, 454, 638, 494, 670, 470, 620, 1562, 666,
+ 470, 644, 1546, 634, 1584, 618, 1584, 644, 1534, 640, 1548, 636, 1560,
+ 644, 520, 542, 1618, 638, 494, 670, 454, 636, 496, 670, 454, 634, 494,
+ 672, 470, 620, 1564, 640, 496, 642, 1562, 616, 520, 622, 1558, 668, 450,
+ 640, 494, 694, 1536, 566, 524, 644, 1558, 666, 456, 638, 1558, 644, 520,
+ 572, 1588, 638, 1558, 644, 494, 590, 1596, 638, 1584, 620, 1584, 644, 454,
+ 638, 1556, 672, 472, 620, 1562, 640, 1558, 646, 494, 644, 470, 646, 496,
+ 566, 1618, 638, 494, 668, 1534, 646, 468, 674, 468, 568, 550, 670, 1530,
+ 670, 454, 638, 1560, 644, 494, 622, 1582, 620, 494, 646, 496, 620, 1560,
+ 644, 494, 668, 1522, 610, 518, 674, 1532, 614, 504, 640, 1584, 642, 1562,
+ 616, 7332, 594}; // UNKNOWN B2354FBB
+
+ irsend.reset();
+ irsend.sendRaw(rawData_B2354FBB, 197, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::GOODWEATHER, irsend.capture.decode_type);
+ EXPECT_EQ(kGoodweatherBits, irsend.capture.bits);
+ EXPECT_EQ(0xD5286A020000, irsend.capture.value);
+ EXPECT_EQ(0x0, irsend.capture.address);
+ EXPECT_EQ(0x0, irsend.capture.command);
+ EXPECT_FALSE(irsend.capture.repeat);
+ ac.setRaw(irsend.capture.value);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 3 (Low), Turbo: -, "
+ "Light: -, Sleep: -, Swing: 2 (Off), Command: 2 (Temp Up)",
+ ac.toString());
+
+ uint16_t rawData_71DD9105[197] = {
+ 6190, 7296, 696, 1496, 634, 1562, 642, 1582, 640, 1564, 564, 1598, 638,
+ 1558, 646, 1560, 588, 1616, 618, 520, 620, 494, 622, 494, 646, 494, 620,
+ 496, 644, 494, 590, 528, 642, 494, 642, 1544, 638, 1584, 618, 1564, 804,
+ 1394, 620, 1564, 640, 1558, 644, 1586, 562, 1616, 620, 492, 672, 470, 622,
+ 494, 646, 494, 622, 494, 646, 494, 620, 498, 644, 492, 596, 520, 644, 494,
+ 592, 1596, 612, 1584, 642, 1560, 614, 1612, 594, 1584, 620, 1558, 646,
+ 1556, 644, 1562, 618, 520, 620, 494, 620, 494, 646, 494, 568, 548, 644,
+ 494, 616, 1570, 638, 494, 670, 1534, 568, 550, 646, 1556, 616, 526, 618,
+ 492, 672, 1532, 568, 550, 646, 1558, 640, 500, 618, 1560, 668, 470, 642,
+ 1548, 658, 1536, 642, 520, 588, 504, 644, 492, 644, 478, 642, 1582, 618,
+ 1586, 590, 506, 640, 1556, 646, 1584, 562, 1616, 620, 1558, 646, 1556,
+ 670, 454, 638, 492, 648, 1558, 642, 478, 644, 492, 590, 530, 858, 1342,
+ 642, 496, 618, 1564, 642, 492, 642, 1548, 636, 492, 648, 494, 622, 1562,
+ 642, 492, 644, 1562, 618, 520, 620, 1558, 644, 476, 640, 1558, 646, 1558,
+ 612, 7382, 594}; // UNKNOWN 71DD9105
+
+ irsend.reset();
+ irsend.sendRaw(rawData_71DD9105, 197, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::GOODWEATHER, irsend.capture.decode_type);
+ EXPECT_EQ(kGoodweatherBits, irsend.capture.bits);
+ EXPECT_EQ(0xD5276A030000, irsend.capture.value);
+ EXPECT_EQ(0x0, irsend.capture.address);
+ EXPECT_EQ(0x0, irsend.capture.command);
+ EXPECT_FALSE(irsend.capture.repeat);
+ ac.setRaw(irsend.capture.value);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 23C, Fan: 3 (Low), "
+ "Turbo: -, Light: -, Sleep: -, Swing: 2 (Off), Command: 3 (Temp Down)",
+ ac.toString());
+
+ uint16_t rawData_C4F9E573[199] = {
+ 6186, 7296, 648, 1558, 670, 1542, 612, 1584, 618, 1560, 668, 1534, 622,
+ 1566, 638, 1558, 646, 1584, 590, 506, 640, 492, 642, 480, 640, 494, 644,
+ 478, 640, 494, 668, 454, 614, 516, 648, 1560, 566, 1638, 618, 1584, 620,
+ 1556, 672, 1534, 620, 1564, 640, 1584, 618, 1586, 564, 528, 670, 468, 640,
+ 478, 642, 494, 644, 478, 640, 492, 670, 454, 638, 494, 670, 1560, 542,
+ 1636, 644, 468, 670, 1534, 620, 1586, 618, 1558, 646, 1556, 670, 1534,
+ 622, 492, 648, 494, 620, 1562, 642, 496, 642, 476, 642, 494, 696, 426,
+ 642, 492, 646, 1558, 568, 548, 644, 494, 642, 1564, 618, 1584, 620, 494,
+ 568, 548, 644, 1558, 644, 480, 636, 1584, 620, 1584, 644, 456, 634, 494,
+ 672, 1560, 540, 1638, 618, 494, 728, 1476, 592, 524, 646, 492, 616, 1572,
+ 638, 1560, 644, 492, 668, 1520, 638, 1562, 642, 494, 588, 1598, 638, 1560,
+ 642, 494, 622, 498, 642, 1556, 646, 478, 638, 492, 646, 494, 620, 1584,
+ 618, 522, 616, 1546, 612, 516, 648, 1556, 644, 476, 668, 468, 670, 1534,
+ 620, 494, 648, 1556, 670, 452, 640, 1558, 644, 496, 646, 1536, 616, 1582,
+ 646, 7326, 616, 41598, 230}; // UNKNOWN C4F9E573
+
+ irsend.reset();
+ irsend.sendRaw(rawData_C4F9E573, 199, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::GOODWEATHER, irsend.capture.decode_type);
+ EXPECT_EQ(kGoodweatherBits, irsend.capture.bits);
+ EXPECT_EQ(0xD52666040000, irsend.capture.value);
+ EXPECT_EQ(0x0, irsend.capture.address);
+ EXPECT_EQ(0x0, irsend.capture.command);
+ EXPECT_FALSE(irsend.capture.repeat);
+ ac.setRaw(irsend.capture.value);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 22C, Fan: 3 (Low), Turbo: -, Light: -, "
+ "Sleep: -, Swing: 1 (Slow), Command: 4 (Swing)",
+ ac.toString());
+}
+
+
+TEST(TestGoodweatherAcClass, toCommon) {
+ IRGoodweatherAc ac(0);
+ ac.setPower(true);
+ ac.setMode(kGoodweatherCool);
+ ac.setTemp(20);
+ ac.setFan(kGoodweatherFanHigh);
+ ac.setSwing(kGoodweatherSwingFast);
+ ac.setTurbo(true);
+ ac.setLight(true);
+ ac.setSleep(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::GOODWEATHER, ac.toCommon().protocol);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().light);
+ ASSERT_EQ(0, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+
+TEST(TestGoodweatherAcClass, Temperature) {
+ IRGoodweatherAc ac(0);
+
+ ac.setTemp(kGoodweatherTempMin);
+ EXPECT_EQ(kGoodweatherTempMin, ac.getTemp());
+
+ ac.setTemp(kGoodweatherTempMin + 1);
+ EXPECT_EQ(kGoodweatherTempMin + 1, ac.getTemp());
+
+ ac.setTemp(kGoodweatherTempMax);
+ EXPECT_EQ(kGoodweatherTempMax, ac.getTemp());
+
+ ac.setTemp(kGoodweatherTempMin - 1);
+ EXPECT_EQ(kGoodweatherTempMin, ac.getTemp());
+
+ ac.setTemp(kGoodweatherTempMax + 1);
+ EXPECT_EQ(kGoodweatherTempMax, ac.getTemp());
+
+ ac.setTemp(23);
+ EXPECT_EQ(23, ac.getTemp());
+
+ ac.setTemp(27);
+ EXPECT_EQ(27, ac.getTemp());
+
+ ac.setTemp(22);
+ EXPECT_EQ(22, ac.getTemp());
+
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+
+ ac.setTemp(0);
+ EXPECT_EQ(kGoodweatherTempMin, ac.getTemp());
+
+ ac.setTemp(255);
+ EXPECT_EQ(kGoodweatherTempMax, ac.getTemp());
+}
+
+TEST(TestGoodweatherAcClass, OperatingMode) {
+ IRGoodweatherAc ac(0);
+ ac.begin();
+
+ ac.setMode(kGoodweatherAuto);
+ EXPECT_EQ(kGoodweatherAuto, ac.getMode());
+
+ ac.setMode(kGoodweatherCool);
+ EXPECT_EQ(kGoodweatherCool, ac.getMode());
+
+ ac.setMode(kGoodweatherHeat);
+ EXPECT_EQ(kGoodweatherHeat, ac.getMode());
+
+ ac.setMode(kGoodweatherFan); // Should set fan speed to High.
+ EXPECT_EQ(kGoodweatherFan, ac.getMode());
+
+ ac.setMode(kGoodweatherDry);
+ EXPECT_EQ(kGoodweatherDry, ac.getMode());
+
+ ac.setMode(kGoodweatherHeat + 1);
+ EXPECT_EQ(kGoodweatherAuto, ac.getMode());
+
+ ac.setMode(kGoodweatherCool);
+ EXPECT_EQ(kGoodweatherCool, ac.getMode());
+
+ ac.setMode(kGoodweatherAuto - 1);
+ EXPECT_EQ(kGoodweatherAuto, ac.getMode());
+
+ ac.setMode(kGoodweatherCool);
+ ac.setMode(255);
+ EXPECT_EQ(kGoodweatherAuto, ac.getMode());
+
+ ac.setMode(kGoodweatherCool);
+ ac.setMode(0);
+ EXPECT_EQ(kGoodweatherAuto, ac.getMode());
+}
+
+TEST(TestGoodweatherAcClass, Power) {
+ IRGoodweatherAc ac(0);
+ ac.begin();
+
+ ac.setPower(true);
+ EXPECT_TRUE(ac.getPower());
+
+ ac.setPower(false);
+ EXPECT_EQ(false, ac.getPower());
+
+ ac.setPower(true);
+ EXPECT_TRUE(ac.getPower());
+
+ ac.off();
+ EXPECT_EQ(false, ac.getPower());
+
+ ac.on();
+ EXPECT_TRUE(ac.getPower());
+}
+
+TEST(TestGoodweatherAcClass, Light) {
+ IRGoodweatherAc ac(0);
+ ac.begin();
+
+ ac.setLight(true);
+ EXPECT_TRUE(ac.getLight());
+ ac.setLight(false);
+ EXPECT_EQ(false, ac.getLight());
+ ac.setLight(true);
+ EXPECT_TRUE(ac.getLight());
+}
+
+TEST(TestGoodweatherAcClass, Turbo) {
+ IRGoodweatherAc ac(0);
+ ac.begin();
+
+ ac.setTurbo(true);
+ EXPECT_TRUE(ac.getTurbo());
+ ac.setTurbo(false);
+ EXPECT_EQ(false, ac.getTurbo());
+ ac.setTurbo(true);
+ EXPECT_TRUE(ac.getTurbo());
+}
+
+TEST(TestGoodweatherAcClass, Sleep) {
+ IRGoodweatherAc ac(0);
+ ac.begin();
+
+ ac.setSleep(true);
+ EXPECT_TRUE(ac.getSleep());
+ ac.setSleep(false);
+ EXPECT_EQ(false, ac.getSleep());
+ ac.setSleep(true);
+ EXPECT_TRUE(ac.getSleep());
+}
+
+TEST(TestGoodweatherAcClass, FanSpeed) {
+ IRGoodweatherAc ac(0);
+ ac.begin();
+
+ // Unexpected value should default to Auto.
+ ac.setFan(255);
+ EXPECT_EQ(kGoodweatherFanAuto, ac.getFan());
+
+ ac.setFan(kGoodweatherFanLow);
+ EXPECT_EQ(kGoodweatherFanLow, ac.getFan());
+ ac.setFan(kGoodweatherFanMed);
+ EXPECT_EQ(kGoodweatherFanMed, ac.getFan());
+ ac.setFan(kGoodweatherFanHigh);
+ EXPECT_EQ(kGoodweatherFanHigh, ac.getFan());
+ ac.setFan(kGoodweatherFanAuto);
+ EXPECT_EQ(kGoodweatherFanAuto, ac.getFan());
+
+ // Beyond Low should default to Auto.
+ ac.setFan(kGoodweatherFanLow + 1);
+ EXPECT_EQ(kGoodweatherFanAuto, ac.getFan());
+}
+
+
+TEST(TestGoodweatherAcClass, SwingSpeed) {
+ IRGoodweatherAc ac(0);
+ ac.begin();
+
+ // Unexpected value should default to Off.
+ ac.setSwing(255);
+ EXPECT_EQ(kGoodweatherSwingOff, ac.getSwing());
+
+ ac.setSwing(kGoodweatherSwingSlow);
+ EXPECT_EQ(kGoodweatherSwingSlow, ac.getSwing());
+ ac.setSwing(kGoodweatherSwingOff);
+ EXPECT_EQ(kGoodweatherSwingOff, ac.getSwing());
+ ac.setSwing(kGoodweatherSwingFast);
+ EXPECT_EQ(kGoodweatherSwingFast, ac.getSwing());
+
+ // Beyond Off should default to Off.
+ ac.setSwing(kGoodweatherSwingOff + 1);
+ EXPECT_EQ(kGoodweatherSwingOff, ac.getSwing());
+}
+
+TEST(TestGoodweatherAcClass, Command) {
+ IRGoodweatherAc ac(0);
+ ac.begin();
+
+ ac.setCommand(kGoodweatherCmdMode);
+ EXPECT_EQ(kGoodweatherCmdMode, ac.getCommand());
+ // Unexpected value should not change anything.
+ ac.setCommand(255);
+ EXPECT_EQ(kGoodweatherCmdMode, ac.getCommand());
+
+ ac.setCommand(kGoodweatherCmdPower);
+ EXPECT_EQ(kGoodweatherCmdPower, ac.getCommand());
+ ac.setCommand(kGoodweatherCmdLight);
+ EXPECT_EQ(kGoodweatherCmdLight, ac.getCommand());
+
+ // Beyond Light should be ignored.
+ ac.setCommand(kGoodweatherCmdLight + 1);
+ EXPECT_EQ(kGoodweatherCmdLight, ac.getCommand());
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Gree_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Gree_test.cpp
similarity index 76%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Gree_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Gree_test.cpp
index a05b06391..d85df72b8 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Gree_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Gree_test.cpp
@@ -338,6 +338,50 @@ TEST(TestGreeClass, Turbo) {
EXPECT_TRUE(irgree.getTurbo());
}
+TEST(TestGreeClass, IFeel) {
+ IRGreeAC ac(0);
+ ac.begin();
+
+ ac.setIFeel(true);
+ EXPECT_TRUE(ac.getIFeel());
+
+ ac.setIFeel(false);
+ EXPECT_FALSE(ac.getIFeel());
+
+ ac.setIFeel(true);
+ EXPECT_TRUE(ac.getIFeel());
+
+ // https://github.com/crankyoldgit/IRremoteESP8266/pull/770#issuecomment-504992209
+ uint8_t on[8] = {0x08, 0x09, 0x60, 0x50, 0x00, 0x44, 0x00, 0xF0};
+ uint8_t off[8] = {0x08, 0x09, 0x60, 0x50, 0x00, 0x40, 0x00, 0xF0};
+ ac.setRaw(off);
+ EXPECT_FALSE(ac.getIFeel());
+ ac.setRaw(on);
+ EXPECT_TRUE(ac.getIFeel());
+}
+
+TEST(TestGreeClass, WiFi) {
+ IRGreeAC ac(0);
+ ac.begin();
+
+ ac.setWiFi(true);
+ EXPECT_TRUE(ac.getWiFi());
+
+ ac.setWiFi(false);
+ EXPECT_FALSE(ac.getWiFi());
+
+ ac.setWiFi(true);
+ EXPECT_TRUE(ac.getWiFi());
+
+ // https://github.com/crankyoldgit/IRremoteESP8266/pull/770#issuecomment-504992209
+ uint8_t on[8] = {0x09, 0x09, 0x60, 0x50, 0x00, 0x40, 0x00, 0x00};
+ uint8_t off[8] = {0x09, 0x09, 0x60, 0x50, 0x00, 0x00, 0x00, 0xC0};
+ ac.setRaw(off);
+ EXPECT_FALSE(ac.getWiFi());
+ ac.setRaw(on);
+ EXPECT_TRUE(ac.getWiFi());
+}
+
TEST(TestGreeClass, Sleep) {
IRGreeAC irgree(0);
irgree.begin();
@@ -451,9 +495,10 @@ TEST(TestGreeClass, HumanReadable) {
IRGreeAC irgree(0);
EXPECT_EQ(
- "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), Turbo: Off, "
- "XFan: Off, Light: On, Sleep: Off, Swing Vertical Mode: Manual, "
- "Swing Vertical Pos: 0 (Last Pos)",
+ "Model: 1 (YAW1F), Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 0 (Auto), "
+ "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, "
+ "Swing Vertical Mode: Manual, Swing Vertical Pos: 0 (Last Pos), "
+ "Timer: Off",
irgree.toString());
irgree.on();
irgree.setMode(kGreeCool);
@@ -463,11 +508,14 @@ TEST(TestGreeClass, HumanReadable) {
irgree.setSleep(true);
irgree.setLight(false);
irgree.setTurbo(true);
+ irgree.setIFeel(true);
+ irgree.setWiFi(true);
irgree.setSwingVertical(true, kGreeSwingAuto);
+ irgree.setTimer(12 * 60 + 30);
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 3 (MAX), Turbo: On, "
- "XFan: On, Light: Off, Sleep: On, Swing Vertical Mode: Auto, "
- "Swing Vertical Pos: 1 (Auto)",
+ "Model: 1 (YAW1F), Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 3 (High), "
+ "Turbo: On, IFeel: On, WiFi: On, XFan: On, Light: Off, Sleep: On, "
+ "Swing Vertical Mode: Auto, Swing Vertical Pos: 1 (Auto), Timer: 12:30",
irgree.toString());
}
@@ -501,7 +549,7 @@ TEST(TestDecodeGree, NormalRealExample) {
uint8_t gree_code[kGreeStateLength] = {0x19, 0x0A, 0x60, 0x50,
0x02, 0x23, 0x00, 0xF0};
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/386
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/386
uint16_t rawData[139] = {
9008, 4496, 644, 1660, 676, 530, 648, 558, 672, 1636, 646, 1660,
644, 556, 650, 584, 626, 560, 644, 580, 628, 1680, 624, 560,
@@ -525,8 +573,116 @@ TEST(TestDecodeGree, NormalRealExample) {
EXPECT_STATE_EQ(gree_code, irsend.capture.state, kGreeBits);
irgree.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 26C, Fan: 1, Turbo: Off, "
- "XFan: Off, Light: On, Sleep: Off, Swing Vertical Mode: Manual, "
- "Swing Vertical Pos: 2",
+ "Model: 1 (YAW1F), Power: On, Mode: 1 (COOL), Temp: 26C, Fan: 1 (Low), "
+ "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, "
+ "Swing Vertical Mode: Manual, Swing Vertical Pos: 2, Timer: Off",
irgree.toString());
}
+
+TEST(TestGreeClass, toCommon) {
+ IRGreeAC ac(0);
+ ac.setPower(true);
+ ac.setMode(kGreeCool);
+ ac.setTemp(20);
+ ac.setFan(kGreeFanMax);
+ ac.setSwingVertical(false, kGreeSwingUp);
+ ac.setTurbo(true);
+ ac.setXFan(true);
+ ac.setLight(true);
+ ac.setSleep(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::GREE, ac.toCommon().protocol);
+ ASSERT_EQ(gree_ac_remote_model_t::YAW1F, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().clean);
+ ASSERT_TRUE(ac.toCommon().light);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kHighest, ac.toCommon().swingv);
+ ASSERT_EQ(0, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestGreeClass, Issue814Power) {
+ IRGreeAC ac(0);
+ ac.begin();
+
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/814#issuecomment-511263921
+ uint8_t YBOFB_on[8] = {0x59, 0x07, 0x20, 0x50, 0x01, 0x20, 0x00, 0xC0};
+ uint8_t off[8] = {0x51, 0x07, 0x20, 0x50, 0x01, 0x20, 0x00, 0x40};
+
+ ac.on();
+ EXPECT_EQ(gree_ac_remote_model_t::YAW1F, ac.getModel());
+ ac.setRaw(off);
+ EXPECT_FALSE(ac.getPower());
+ ac.setRaw(YBOFB_on);
+ EXPECT_TRUE(ac.getPower());
+ EXPECT_EQ(gree_ac_remote_model_t::YBOFB, ac.getModel());
+ EXPECT_EQ(
+ "Model: 2 (YBOFB), Power: On, Mode: 1 (COOL), Temp: 23C, Fan: 1 (Low), "
+ "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, "
+ "Swing Vertical Mode: Auto, Swing Vertical Pos: 1 (Auto), Timer: Off",
+ ac.toString());
+ ac.off();
+ EXPECT_STATE_EQ(off, ac.getRaw(), kGreeBits);
+ ac.on();
+ EXPECT_STATE_EQ(YBOFB_on, ac.getRaw(), kGreeBits);
+ uint8_t YAW1F_on[8] = {0x59, 0x07, 0x60, 0x50, 0x01, 0x20, 0x00, 0xC0};
+ ac.setModel(gree_ac_remote_model_t::YAW1F);
+ EXPECT_STATE_EQ(YAW1F_on, ac.getRaw(), kGreeBits);
+ ac.off();
+ EXPECT_STATE_EQ(off, ac.getRaw(), kGreeBits);
+ ac.setModel(gree_ac_remote_model_t::YBOFB);
+ ac.on();
+ EXPECT_STATE_EQ(YBOFB_on, ac.getRaw(), kGreeBits);
+}
+
+TEST(TestGreeClass, Timer) {
+ IRGreeAC ac(0);
+ ac.begin();
+
+ ac.setTimer(0);
+ EXPECT_FALSE(ac.getTimerEnabled());
+ EXPECT_EQ(0, ac.getTimer());
+
+ ac.setTimer(29);
+ EXPECT_FALSE(ac.getTimerEnabled());
+ EXPECT_EQ(0, ac.getTimer());
+
+ ac.setTimer(30);
+ EXPECT_TRUE(ac.getTimerEnabled());
+ EXPECT_EQ(30, ac.getTimer());
+
+ ac.setTimer(60);
+ EXPECT_TRUE(ac.getTimerEnabled());
+ EXPECT_EQ(60, ac.getTimer());
+
+ ac.setTimer(90);
+ EXPECT_TRUE(ac.getTimerEnabled());
+ EXPECT_EQ(90, ac.getTimer());
+
+ ac.setTimer(10 * 60);
+ EXPECT_TRUE(ac.getTimerEnabled());
+ EXPECT_EQ(10 * 60, ac.getTimer());
+
+ ac.setTimer(23 * 60 + 59);
+ EXPECT_TRUE(ac.getTimerEnabled());
+ EXPECT_EQ(23 * 60 + 30, ac.getTimer());
+
+ ac.setTimer(24 * 60 + 1);
+ EXPECT_TRUE(ac.getTimerEnabled());
+ EXPECT_EQ(24 * 60, ac.getTimer());
+
+ ac.setTimer(24 * 60 + 30);
+ EXPECT_TRUE(ac.getTimerEnabled());
+ EXPECT_EQ(24 * 60, ac.getTimer());
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Haier_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Haier_test.cpp
similarity index 90%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Haier_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Haier_test.cpp
index 8d306cb0b..03cc63f93 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Haier_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Haier_test.cpp
@@ -343,24 +343,11 @@ TEST(TestHaierACClass, Timers) {
EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand());
}
-TEST(TestHaierACClass, TimeToString) {
- EXPECT_EQ("00:00", IRHaierAC::timeToString(0));
- EXPECT_EQ("00:01", IRHaierAC::timeToString(1));
- EXPECT_EQ("00:10", IRHaierAC::timeToString(10));
- EXPECT_EQ("00:59", IRHaierAC::timeToString(59));
-
- EXPECT_EQ("01:00", IRHaierAC::timeToString(60));
- EXPECT_EQ("01:01", IRHaierAC::timeToString(61));
- EXPECT_EQ("01:59", IRHaierAC::timeToString(60 + 59));
- EXPECT_EQ("18:59", IRHaierAC::timeToString(18 * 60 + 59));
- EXPECT_EQ("23:59", IRHaierAC::timeToString(23 * 60 + 59));
-}
-
TEST(TestHaierACClass, MessageConstuction) {
IRHaierAC haier(0);
EXPECT_EQ(
- "Command: 1 (On), Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), "
+ "Command: 1 (On), Mode: 0 (AUTO), Temp: 25C, Fan: 0 (Auto), "
"Swing: 0 (Off), Sleep: Off, Health: Off, "
"Current Time: 00:00, On Timer: Off, Off Timer: Off",
haier.toString());
@@ -368,7 +355,7 @@ TEST(TestHaierACClass, MessageConstuction) {
haier.setTemp(21);
haier.setFan(kHaierAcFanHigh);
EXPECT_EQ(
- "Command: 3 (Fan), Mode: 1 (COOL), Temp: 21C, Fan: 3 (MAX), "
+ "Command: 3 (Fan), Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), "
"Swing: 0 (Off), Sleep: Off, Health: Off, "
"Current Time: 00:00, On Timer: Off, Off Timer: Off",
haier.toString());
@@ -377,7 +364,7 @@ TEST(TestHaierACClass, MessageConstuction) {
haier.setSleep(true);
haier.setCurrTime(615); // 10:15am
EXPECT_EQ(
- "Command: 8 (Sleep), Mode: 3 (HEAT), Temp: 21C, Fan: 3 (MAX), "
+ "Command: 8 (Sleep), Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), "
"Swing: 3 (Chg), Sleep: On, Health: On, "
"Current Time: 10:15, On Timer: Off, Off Timer: Off",
haier.toString());
@@ -386,7 +373,7 @@ TEST(TestHaierACClass, MessageConstuction) {
haier.setCommand(kHaierAcCmdOn);
EXPECT_EQ(
- "Command: 1 (On), Mode: 2 (DRY), Temp: 21C, Fan: 2, "
+ "Command: 1 (On), Mode: 1 (COOL), Temp: 21C, Fan: 2 (Medium), "
"Swing: 3 (Chg), Sleep: On, Health: On, "
"Current Time: 10:15, On Timer: 13:20, Off Timer: 18:45",
haier.toString());
@@ -394,20 +381,20 @@ TEST(TestHaierACClass, MessageConstuction) {
// Now change a few already set things.
haier.setMode(kHaierAcHeat);
EXPECT_EQ(
- "Command: 2 (Mode), Mode: 3 (HEAT), Temp: 21C, Fan: 2, "
+ "Command: 2 (Mode), Mode: 3 (HEAT), Temp: 21C, Fan: 2 (Medium), "
"Swing: 3 (Chg), Sleep: On, Health: On, "
- "Current Time: 10:15, On Timer: 13:52, Off Timer: 18:45",
+ "Current Time: 10:15, On Timer: 13:20, Off Timer: 18:45",
haier.toString());
haier.setTemp(25);
EXPECT_EQ(
- "Command: 6 (Temp Up), Mode: 3 (HEAT), Temp: 25C, Fan: 2, "
+ "Command: 6 (Temp Up), Mode: 3 (HEAT), Temp: 25C, Fan: 2 (Medium), "
"Swing: 3 (Chg), Sleep: On, Health: On, "
- "Current Time: 10:15, On Timer: 13:52, Off Timer: 18:45",
+ "Current Time: 10:15, On Timer: 13:20, Off Timer: 18:45",
haier.toString());
uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x96, 0xEA, 0xCF, 0x32,
- 0xED, 0x2D, 0x74, 0xB4};
+ 0xED, 0x6D, 0x54, 0xD4};
EXPECT_STATE_EQ(expectedState, haier.getRaw(), kHaierACBits);
// Check that the checksum is valid.
@@ -419,7 +406,7 @@ TEST(TestHaierACClass, MessageConstuction) {
EXPECT_FALSE(IRHaierAC::validChecksum(randomState));
haier.setRaw(randomState);
EXPECT_EQ(
- "Command: 9 (Timer Set), Mode: 3 (HEAT), Temp: 20C, Fan: 2, "
+ "Command: 9 (Timer Set), Mode: 3 (HEAT), Temp: 20C, Fan: 2 (Medium), "
"Swing: 1 (Up), Sleep: On, Health: Off, "
"Current Time: 16:32, On Timer: Off, Off Timer: Off",
haier.toString());
@@ -683,7 +670,7 @@ TEST(TestHaierACYRW02Class, MessageConstuction) {
IRHaierACYRW02 haier(0);
EXPECT_EQ(
- "Power: On, Button: 5 (Power), Mode: 0 (Auto), Temp: 25C,"
+ "Power: On, Button: 5 (Power), Mode: 0 (AUTO), Temp: 25C,"
" Fan: 10 (Auto), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off,"
" Health: On",
haier.toString());
@@ -691,7 +678,7 @@ TEST(TestHaierACYRW02Class, MessageConstuction) {
haier.setTemp(21);
haier.setFan(kHaierAcYrw02FanHigh);
EXPECT_EQ(
- "Power: On, Button: 4 (Fan), Mode: 2 (Cool), Temp: 21C,"
+ "Power: On, Button: 4 (Fan), Mode: 2 (COOL), Temp: 21C,"
" Fan: 2 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off,"
" Health: On",
haier.toString());
@@ -701,7 +688,7 @@ TEST(TestHaierACYRW02Class, MessageConstuction) {
haier.setSleep(true);
haier.setTurbo(kHaierAcYrw02TurboHigh);
EXPECT_EQ(
- "Power: On, Button: 8 (Turbo), Mode: 2 (Cool), Temp: 21C,"
+ "Power: On, Button: 8 (Turbo), Mode: 2 (COOL), Temp: 21C,"
" Fan: 2 (High), Turbo: 1 (High), Swing: 2 (Middle),"
" Sleep: On, Health: Off",
haier.toString());
@@ -716,7 +703,7 @@ TEST(TestHaierACYRW02Class, RealStates) {
IRHaierACYRW02 haier(0);
haier.setRaw(expectedState1);
EXPECT_EQ(
- "Power: On, Button: 7 (Health), Mode: 8 (Heat), Temp: 30C,"
+ "Power: On, Button: 7 (Health), Mode: 8 (HEAT), Temp: 30C,"
" Fan: 2 (High), Turbo: 0 (Off), Swing: 1 (Top), Sleep: Off,"
" Health: Off",
haier.toString());
@@ -726,7 +713,7 @@ TEST(TestHaierACYRW02Class, RealStates) {
0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x75};
haier.setRaw(expectedState2);
EXPECT_EQ(
- "Power: Off, Button: 5 (Power), Mode: 8 (Heat), Temp: 30C,"
+ "Power: Off, Button: 5 (Power), Mode: 8 (HEAT), Temp: 30C,"
" Fan: 2 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off,"
" Health: Off",
haier.toString());
@@ -736,7 +723,7 @@ TEST(TestHaierACYRW02Class, RealStates) {
0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2B};
haier.setRaw(expectedState3);
EXPECT_EQ(
- "Power: On, Button: 1 (Temp Down), Mode: 2 (Cool), Temp: 16C,"
+ "Power: On, Button: 1 (Temp Down), Mode: 2 (COOL), Temp: 16C,"
" Fan: 2 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off,"
" Health: On",
haier.toString());
@@ -747,7 +734,7 @@ TEST(TestHaierACYRW02Class, RealStates) {
0x20, 0x80, 0x00, 0x00, 0x00, 0x0B, 0xD7};
haier.setRaw(expectedState4);
EXPECT_EQ(
- "Power: On, Button: 11 (Sleep), Mode: 2 (Cool), Temp: 25C,"
+ "Power: On, Button: 11 (Sleep), Mode: 2 (COOL), Temp: 25C,"
" Fan: 10 (Auto), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On,"
" Health: On",
haier.toString());
@@ -758,7 +745,7 @@ TEST(TestHaierACYRW02Class, RealStates) {
0x20, 0x80, 0x00, 0x00, 0x00, 0x04, 0x85};
haier.setRaw(expectedState5);
EXPECT_EQ(
- "Power: On, Button: 4 (Fan), Mode: 2 (Cool), Temp: 25C,"
+ "Power: On, Button: 4 (Fan), Mode: 2 (COOL), Temp: 25C,"
" Fan: 2 (High), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On,"
" Health: On",
haier.toString());
@@ -831,7 +818,7 @@ TEST(TestDecodeHaierAC, RealExample1) {
IRHaierAC haier(0);
haier.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Command: 1 (On), Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), "
+ "Command: 1 (On), Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), "
"Swing: 0 (Off), Sleep: Off, Health: Off, "
"Current Time: 00:01, On Timer: Off, Off Timer: Off",
haier.toString());
@@ -873,7 +860,7 @@ TEST(TestDecodeHaierAC, RealExample2) {
IRHaierAC haier(0);
haier.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Command: 6 (Temp Up), Mode: 0 (AUTO), Temp: 22C, Fan: 0 (AUTO), "
+ "Command: 6 (Temp Up), Mode: 1 (COOL), Temp: 22C, Fan: 0 (Auto), "
"Swing: 0 (Off), Sleep: Off, Health: Off, "
"Current Time: 00:01, On Timer: Off, Off Timer: Off",
haier.toString());
@@ -915,7 +902,7 @@ TEST(TestDecodeHaierAC, RealExample3) {
IRHaierAC haier(0);
haier.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Command: 12 (Health), Mode: 0 (AUTO), Temp: 30C, Fan: 0 (AUTO), "
+ "Command: 12 (Health), Mode: 1 (COOL), Temp: 30C, Fan: 0 (Auto), "
"Swing: 0 (Off), Sleep: Off, Health: On, "
"Current Time: 00:09, On Timer: Off, Off Timer: Off",
haier.toString());
@@ -985,14 +972,14 @@ TEST(TestDecodeHaierAC_YRW02, RealExample) {
IRHaierACYRW02 haier(0);
haier.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Button: 5 (Power), Mode: 2 (Cool), Temp: 17C,"
+ "Power: On, Button: 5 (Power), Mode: 2 (COOL), Temp: 17C,"
" Fan: 2 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off,"
" Health: On",
haier.toString());
}
// Default state of the remote needed to include hidden data.
-// Ref: https://github.com/markszabo/IRremoteESP8266/issues/668
+// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/668
TEST(TestHaierAcIssues, Issue668) {
IRHaierAC ac(0);
IRHaierAC acText(1);
@@ -1002,13 +989,14 @@ TEST(TestHaierAcIssues, Issue668) {
// Turn on the AC.
ac._irsend.reset();
char expected_on[] =
- "Command: 1 (On), Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), "
+ "Command: 1 (On), Mode: 1 (COOL), Temp: 25C, Fan: 0 (Auto), "
"Swing: 0 (Off), Sleep: Off, Health: Off, Current Time: 00:00, "
"On Timer: Off, Off Timer: Off";
// State taken from real capture:
- // https://github.com/markszabo/IRremoteESP8266/issues/668#issuecomment-483531895
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/668#issuecomment-483531895
uint8_t expected_on_state[9] = {
0xA5, 0x91, 0x20, 0x00, 0x0C, 0xC0, 0x20, 0x00, 0x42};
+ ac.setMode(kHaierAcCool);
ac.setCommand(kHaierAcCmdOn);
EXPECT_EQ(expected_on, ac.toString());
ac.send();
@@ -1039,11 +1027,11 @@ TEST(TestHaierAcIssues, Issue668) {
// Increase the temp by 1.
ac._irsend.reset();
char expected_temp_plus_one[] =
- "Command: 6 (Temp Up), Mode: 0 (AUTO), Temp: 26C, Fan: 0 (AUTO), "
+ "Command: 6 (Temp Up), Mode: 1 (COOL), Temp: 26C, Fan: 0 (Auto), "
"Swing: 0 (Off), Sleep: Off, Health: Off, Current Time: 00:00, "
"On Timer: Off, Off Timer: Off";
// State taken from real capture:
- // https://github.com/markszabo/IRremoteESP8266/issues/668#issuecomment-483531895
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/668#issuecomment-483531895
uint8_t expected_temp_plus_one_state[9] = {
0xA5, 0xA6, 0x20, 0x00, 0x0C, 0xC0, 0x20, 0x00, 0x57};
ASSERT_EQ(25, ac.getTemp());
@@ -1063,7 +1051,7 @@ TEST(TestHaierAcIssues, Issue668) {
// Decrease the temp by 1.
ac._irsend.reset();
char expected_temp_minus_one[] =
- "Command: 7 (Temp Down), Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), "
+ "Command: 7 (Temp Down), Mode: 1 (COOL), Temp: 25C, Fan: 0 (Auto), "
"Swing: 0 (Off), Sleep: Off, Health: Off, Current Time: 00:00, "
"On Timer: Off, Off Timer: Off";
ASSERT_EQ(26, ac.getTemp());
@@ -1078,3 +1066,65 @@ TEST(TestHaierAcIssues, Issue668) {
acText.setRaw(ac._irsend.capture.state);
EXPECT_EQ(expected_temp_minus_one, acText.toString());
}
+
+TEST(TestHaierACClass, toCommon) {
+ IRHaierAC ac(0);
+ ac.setCommand(kHaierAcCmdOn);
+ ac.setMode(kHaierAcCool);
+ ac.setTemp(20);
+ ac.setFan(kHaierAcFanHigh);
+ ac.setSwing(kHaierAcSwingChg);
+ ac.setHealth(true);
+ ac.setSleep(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::HAIER_AC, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_TRUE(ac.toCommon().filter);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(0, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestHaierACYRW02Class, toCommon) {
+ IRHaierACYRW02 ac(0);
+ ac.setPower(true);
+ ac.setMode(kHaierAcYrw02Cool);
+ ac.setTemp(20);
+ ac.setFan(kHaierAcYrw02FanHigh);
+ ac.setSwing(kHaierAcYrw02SwingTop);
+ ac.setHealth(true);
+ ac.setSleep(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::HAIER_AC_YRW02, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_TRUE(ac.toCommon().filter);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kHighest, ac.toCommon().swingv);
+ ASSERT_EQ(0, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Hitachi_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Hitachi_test.cpp
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Hitachi_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Hitachi_test.cpp
index a2471c4aa..7e7935638 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Hitachi_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Hitachi_test.cpp
@@ -300,7 +300,7 @@ TEST(TestIRHitachiAcClass, HumanReadable) {
ac.setFan(kHitachiAcFanHigh);
ac.setSwingVertical(true);
EXPECT_EQ(
- "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (HIGH), "
+ "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (High), "
"Swing (Vertical): On, Swing (Horizontal): Off",
ac.toString());
ac.setMode(kHitachiAcCool);
@@ -309,7 +309,7 @@ TEST(TestIRHitachiAcClass, HumanReadable) {
ac.setSwingVertical(false);
ac.setSwingHorizontal(true);
EXPECT_EQ(
- "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 2 (LOW), "
+ "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 2 (Low), "
"Swing (Vertical): Off, Swing (Horizontal): On",
ac.toString());
}
@@ -376,7 +376,7 @@ TEST(TestDecodeHitachiAC, NormalRealExample1) {
0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC};
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/417
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/417
// 'On' '16c' 'auto fan' 'cooling mode'
uint16_t rawData[451] = {
3318, 1720, 400, 1276, 400, 432, 398, 434, 398, 434, 400, 432,
@@ -428,7 +428,7 @@ TEST(TestDecodeHitachiAC, NormalRealExample1) {
IRHitachiAc ac(0);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 1 (AUTO), "
+ "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 1 (Auto), "
"Swing (Vertical): Off, Swing (Horizontal): Off",
ac.toString());
}
@@ -444,7 +444,7 @@ TEST(TestDecodeHitachiAC, NormalRealExample2) {
0xC0, 0x02, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xD0};
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/417
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/417
// 'On' '32c' 'auto fan' 'heating mode'
uint16_t rawData[451] = {
3322, 1718, 400, 1278, 398, 432, 402, 430, 400, 430, 402, 430,
@@ -496,7 +496,7 @@ TEST(TestDecodeHitachiAC, NormalRealExample2) {
IRHitachiAc ac(0);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (HIGH), "
+ "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (High), "
"Swing (Vertical): Off, Swing (Horizontal): Off",
ac.toString());
}
@@ -543,7 +543,7 @@ TEST(TestDecodeHitachiAC1, NormalRealExample) {
0x61, 0x84, 0x00, 0x00, 0x00,
0x00, 0x10, 0x98};
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/453
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/453
uint16_t rawData[211] = {
3400, 3350, 450, 1250, 450, 400, 400, 1300, 400, 1300, 400, 400,
450, 400, 400, 1300, 400, 400, 400, 1300, 400, 400, 450, 1250,
@@ -685,7 +685,7 @@ TEST(TestDecodeHitachiAC2, NormalRealExample) {
0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F, 0x11, 0xEE, 0x00, 0xFF, 0x00,
0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00};
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/417
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/417
uint16_t rawData[851] = {
// ON - 32c cool (fan auto)
3432, 1654, 492, 1180, 488, 360, 486, 360, 486, 360, 486, 362,
@@ -768,3 +768,33 @@ TEST(TestDecodeHitachiAC2, NormalRealExample) {
ASSERT_EQ(kHitachiAc2Bits, irsend.capture.bits);
EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAc2Bits);
}
+
+TEST(TestIRHitachiAcClass, toCommon) {
+ IRHitachiAc ac(0);
+ ac.setPower(true);
+ ac.setMode(kHitachiAcCool);
+ ac.setTemp(20);
+ ac.setFan(kHitachiAcFanHigh);
+ ac.setSwingVertical(true);
+ ac.setSwingHorizontal(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::HITACHI_AC, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Inax_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Inax_test.cpp
new file mode 100644
index 000000000..b182cce32
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Inax_test.cpp
@@ -0,0 +1,119 @@
+// Copyright 2019 crankyoldgit (David Conran)
+
+#include "IRsend.h"
+#include "IRsend_test.h"
+#include "IRutils.h"
+#include "gtest/gtest.h"
+
+
+// General housekeeping
+TEST(TestInax, Housekeeping) {
+ ASSERT_EQ("INAX", typeToString(INAX));
+ ASSERT_FALSE(hasACState(INAX));
+}
+
+// Tests for sendInax().
+// Test sending typical data only.
+TEST(TestSendInax, SendDataOnly) {
+ IRsendTest irsend(0);
+ irsend.begin();
+
+ irsend.reset();
+ irsend.sendInax(0x5C32CD); // Small flush.
+ EXPECT_EQ(
+ "f38000d50"
+ "m9000s4500"
+ "m560s560m560s1675m560s560m560s1675m560s1675m560s1675m560s560m560s560"
+ "m560s560m560s560m560s1675m560s1675m560s560m560s560m560s1675m560s560"
+ "m560s1675m560s1675m560s560m560s560m560s1675m560s1675m560s560m560s1675"
+ "m560s40000"
+ "m9000s4500"
+ "m560s560m560s1675m560s560m560s1675m560s1675m560s1675m560s560m560s560"
+ "m560s560m560s560m560s1675m560s1675m560s560m560s560m560s1675m560s560"
+ "m560s1675m560s1675m560s560m560s560m560s1675m560s1675m560s560m560s1675"
+ "m560s40000",
+ irsend.outputStr());
+
+ irsend.reset();
+}
+
+// Test sending with different repeats.
+TEST(TestSendInax, SendWithRepeats) {
+ IRsendTest irsend(0);
+ irsend.begin();
+
+ irsend.reset();
+ irsend.sendInax(0x5C32CD, kInaxBits, 0); // 0 repeats.
+ EXPECT_EQ(
+ "f38000d50"
+ "m9000s4500"
+ "m560s560m560s1675m560s560m560s1675m560s1675m560s1675m560s560m560s560"
+ "m560s560m560s560m560s1675m560s1675m560s560m560s560m560s1675m560s560"
+ "m560s1675m560s1675m560s560m560s560m560s1675m560s1675m560s560m560s1675"
+ "m560s40000",
+ irsend.outputStr());
+ irsend.sendInax(0x5C32CD, kInaxBits, 2); // 2 repeats.
+ EXPECT_EQ(
+ "f38000d50"
+ "m9000s4500"
+ "m560s560m560s1675m560s560m560s1675m560s1675m560s1675m560s560m560s560"
+ "m560s560m560s560m560s1675m560s1675m560s560m560s560m560s1675m560s560"
+ "m560s1675m560s1675m560s560m560s560m560s1675m560s1675m560s560m560s1675"
+ "m560s40000"
+ "m9000s4500"
+ "m560s560m560s1675m560s560m560s1675m560s1675m560s1675m560s560m560s560"
+ "m560s560m560s560m560s1675m560s1675m560s560m560s560m560s1675m560s560"
+ "m560s1675m560s1675m560s560m560s560m560s1675m560s1675m560s560m560s1675"
+ "m560s40000"
+ "m9000s4500"
+ "m560s560m560s1675m560s560m560s1675m560s1675m560s1675m560s560m560s560"
+ "m560s560m560s560m560s1675m560s1675m560s560m560s560m560s1675m560s560"
+ "m560s1675m560s1675m560s560m560s560m560s1675m560s1675m560s560m560s1675"
+ "m560s40000",
+ irsend.outputStr());
+}
+
+// Tests for decodeInax().
+
+// Decode normal Inax messages.
+TEST(TestDecodeInax, SyntheticDecode) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ // Normal Inax 24-bit message.
+ irsend.reset();
+ irsend.sendInax(0x5C32CD);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(INAX, irsend.capture.decode_type);
+ EXPECT_EQ(kInaxBits, irsend.capture.bits);
+ EXPECT_EQ(0x5C32CD, irsend.capture.value);
+ EXPECT_EQ(0, irsend.capture.address);
+ EXPECT_EQ(0, irsend.capture.command);
+}
+
+// Decode real example via Issue #704
+TEST(TestDecodeInax, DecodeExamples) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ irsend.reset();
+ // Inax Small Flush from Issue #309
+ uint16_t smallFlushRawData[51] = {
+ 8996, 4474, 568, 556, 560, 1676, 568, 556, 562, 1676, 562, 1678, 566,
+ 1674, 566, 558, 560, 560, 566, 556, 566, 556, 560, 1678, 562, 1676, 566,
+ 556, 562, 560, 564, 1672, 566, 556, 562, 1676, 562, 1678, 562, 560, 564,
+ 558, 564, 1674, 560, 1678, 564, 560, 566, 1670, 562};
+
+ irsend.sendRaw(smallFlushRawData, 51, 38);
+ irsend.makeDecodeResult();
+
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(INAX, irsend.capture.decode_type);
+ EXPECT_EQ(kInaxBits, irsend.capture.bits);
+ EXPECT_EQ(0x5C32CD, irsend.capture.value);
+ EXPECT_EQ(0, irsend.capture.address);
+ EXPECT_EQ(0, irsend.capture.command);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_JVC_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_JVC_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_JVC_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_JVC_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Kelvinator_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Kelvinator_test.cpp
similarity index 93%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Kelvinator_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Kelvinator_test.cpp
index 38a298e58..436336c04 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Kelvinator_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Kelvinator_test.cpp
@@ -422,7 +422,7 @@ TEST(TestKelvinatorClass, HumanReadable) {
IRKelvinatorAC irkelv(0);
EXPECT_EQ(
- "Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), Turbo: Off, "
+ "Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Turbo: Off, "
"Quiet: Off, XFan: Off, IonFilter: Off, Light: Off, "
"Swing (Horizontal): Off, Swing (Vertical): Off",
irkelv.toString());
@@ -435,7 +435,7 @@ TEST(TestKelvinatorClass, HumanReadable) {
irkelv.setLight(true);
irkelv.setSwingHorizontal(true);
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 25C, Fan: 5 (MAX), Turbo: Off, "
+ "Power: On, Mode: 1 (COOL), Temp: 25C, Fan: 5 (High), Turbo: Off, "
"Quiet: Off, XFan: On, IonFilter: On, Light: On, "
"Swing (Horizontal): On, Swing (Vertical): Off",
irkelv.toString());
@@ -520,3 +520,39 @@ TEST(TestDecodeKelvinator, NormalSynthetic) {
ASSERT_EQ(kKelvinatorBits, irsend.capture.bits);
EXPECT_STATE_EQ(kelv_code, irsend.capture.state, kKelvinatorBits);
}
+
+TEST(TestKelvinatorClass, toCommon) {
+ IRKelvinatorAC ac(0);
+ ac.setPower(true);
+ ac.setMode(kKelvinatorCool);
+ ac.setTemp(20);
+ ac.setFan(kKelvinatorFanMax);
+ ac.setIonFilter(true);
+ ac.setXFan(true);
+ ac.setQuiet(false);
+ ac.setTurbo(true);
+ ac.setLight(true);
+ ac.setSwingHorizontal(false);
+ ac.setSwingVertical(true);
+
+ // Now test it.
+ ASSERT_EQ(decode_type_t::KELVINATOR, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_TRUE(ac.toCommon().filter);
+ ASSERT_TRUE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().light);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_LG_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_LG_test.cpp
similarity index 99%
rename from lib/IRremoteESP8266-2.6.0/test/ir_LG_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_LG_test.cpp
index 2925494b9..d1e1b8659 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_LG_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_LG_test.cpp
@@ -429,7 +429,7 @@ TEST(TestDecodeLG2, RealLG2Example) {
}
// Tests for issue reported in
-// https://github.com/markszabo/IRremoteESP8266/issues/620
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/620
TEST(TestDecodeLG, Issue620) {
IRsendTest irsend(0);
IRrecv irrecv(0);
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Lasertag_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Lasertag_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Lasertag_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Lasertag_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Lego_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Lego_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Lego_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Lego_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Lutron_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Lutron_test.cpp
similarity index 98%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Lutron_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Lutron_test.cpp
index d682967ca..81cf0df9c 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Lutron_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Lutron_test.cpp
@@ -120,7 +120,7 @@ TEST(TestDecodeLutron, DocumentedExampleFullOff) {
irsend.begin();
// Full Off code.
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/515
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/515
uint16_t rawData[14] = {20518, 6839, 2280, 6839, 2280, 2280, 9119,
2280, 2280, 6839, 2280, 4560, 2280, 11399};
irsend.reset();
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_MWM_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_MWM_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_MWM_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_MWM_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Magiquest_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Magiquest_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Magiquest_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Magiquest_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Midea_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Midea_test.cpp
similarity index 86%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Midea_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Midea_test.cpp
index ced3ea10c..319528e9c 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Midea_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Midea_test.cpp
@@ -397,13 +397,13 @@ TEST(TestMideaACClass, Temperature) {
EXPECT_EQ(kMideaACMaxTempF, midea.getTemp(false));
// General changes.
- midea.setTemp(17, true); // C
- EXPECT_EQ(17, midea.getTemp(true)); // C
- EXPECT_EQ(63, midea.getTemp(false)); // F
+ midea.setTemp(18, true); // C
+ EXPECT_EQ(18, midea.getTemp(true)); // C
+ EXPECT_EQ(64, midea.getTemp(false)); // F
midea.setTemp(21, true); // C
EXPECT_EQ(21, midea.getTemp(true)); // C
- EXPECT_EQ(70, midea.getTemp(false)); // F
+ EXPECT_EQ(69, midea.getTemp(false)); // F
midea.setTemp(25, true); // C
EXPECT_EQ(25, midea.getTemp(true)); // C
@@ -414,7 +414,7 @@ TEST(TestMideaACClass, Temperature) {
EXPECT_EQ(86, midea.getTemp(false)); // F
midea.setTemp(80, false); // F
- EXPECT_EQ(26, midea.getTemp(true)); // C
+ EXPECT_EQ(27, midea.getTemp(true)); // C
EXPECT_EQ(80, midea.getTemp(false)); // F
midea.setTemp(70); // F
@@ -440,25 +440,30 @@ TEST(TestMideaACClass, Sleep) {
}
TEST(TestMideaACClass, HumanReadableOutput) {
- IRMideaAC midea(0);
- midea.begin();
+ IRMideaAC ac(0);
+ ac.begin();
- midea.setRaw(0xA1826FFFFF62);
+ ac.setRaw(0xA1826FFFFF62);
EXPECT_EQ(
- "Power: On, Mode: 2 (AUTO), Temp: 25C/77F, Fan: 0 (AUTO), "
- "Sleep: Off",
- midea.toString());
- midea.off();
- midea.setTemp(25);
- midea.setFan(kMideaACFanHigh);
- midea.setMode(kMideaACDry);
- midea.setSleep(true);
- EXPECT_EQ("Power: Off, Mode: 1 (DRY), Temp: 16C/62F, Fan: 3 (HI), Sleep: On",
- midea.toString());
+ "Power: On, Mode: 2 (AUTO), Celsius: Off, Temp: 25C/77F, Fan: 0 (Auto), "
+ "Sleep: Off, Swing(V) Toggle: Off", ac.toString());
+ ac.off();
+ ac.setTemp(25, true);
+ ac.setFan(kMideaACFanHigh);
+ ac.setMode(kMideaACDry);
+ ac.setSleep(true);
+ EXPECT_EQ(
+ "Power: Off, Mode: 1 (DRY), Celsius: Off, Temp: 25C/77F, Fan: 3 (High), "
+ "Sleep: On, Swing(V) Toggle: Off", ac.toString());
+ ac.setUseCelsius(true);
+ EXPECT_EQ(
+ "Power: Off, Mode: 1 (DRY), Celsius: On, Temp: 25C/77F, Fan: 3 (High), "
+ "Sleep: On, Swing(V) Toggle: Off", ac.toString());
- midea.setRaw(0xA19867FFFF7E);
- EXPECT_EQ("Power: On, Mode: 0 (COOL), Temp: 20C/69F, Fan: 3 (HI), Sleep: Off",
- midea.toString());
+ ac.setRaw(0xA19867FFFF7E);
+ EXPECT_EQ(
+ "Power: On, Mode: 0 (COOL), Celsius: Off, Temp: 21C/69F, Fan: 3 (High), "
+ "Sleep: Off, Swing(V) Toggle: Off", ac.toString());
}
// Tests for decodeMidea().
@@ -656,3 +661,84 @@ TEST(TestDecodeMidea, DecodeRealExample) {
EXPECT_EQ(kMideaBits, irsend.capture.bits);
EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value);
}
+
+TEST(TestMideaACClass, toCommon) {
+ IRMideaAC ac(0);
+ ac.setPower(true);
+ ac.setMode(kMideaACCool);
+ ac.setUseCelsius(true);
+ ac.setTemp(20, true);
+ ac.setFan(kMideaACFanHigh);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::MIDEA, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv);
+ // Unsupported.
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/819
+TEST(TestMideaACClass, CelsiusRemoteTemp) {
+ IRMideaAC ac(0);
+ uint64_t on_cool_low_17c = 0xA18840FFFF56;
+ uint64_t on_cool_low_30c = 0xA1884DFFFF5D;
+ ac.on();
+ ac.setMode(kMideaACCool);
+ ac.setFan(kMideaACFanLow);
+ ac.setTemp(17, true);
+ EXPECT_FALSE(ac.getUseCelsius());
+ ac.setUseCelsius(true);
+ EXPECT_TRUE(ac.getUseCelsius());
+ EXPECT_EQ(on_cool_low_17c, ac.getRaw());
+ EXPECT_EQ(
+ "Power: On, Mode: 0 (COOL), Celsius: On, Temp: 17C/62F, Fan: 1 (Low), "
+ "Sleep: Off, Swing(V) Toggle: Off", ac.toString());
+ ac.setRaw(on_cool_low_17c);
+ EXPECT_EQ(17, ac.getTemp(true));
+ EXPECT_EQ(62, ac.getTemp(false));
+ EXPECT_EQ(
+ "Power: On, Mode: 0 (COOL), Celsius: On, Temp: 17C/62F, Fan: 1 (Low), "
+ "Sleep: Off, Swing(V) Toggle: Off", ac.toString());
+ ac.setTemp(17, true);
+ EXPECT_EQ(17, ac.getTemp(true));
+ EXPECT_EQ(62, ac.getTemp(false));
+ EXPECT_EQ(on_cool_low_17c, ac.getRaw());
+
+ ac.setRaw(on_cool_low_30c);
+ EXPECT_EQ(
+ "Power: On, Mode: 0 (COOL), Celsius: On, Temp: 30C/86F, Fan: 1 (Low), "
+ "Sleep: Off, Swing(V) Toggle: Off", ac.toString());
+}
+
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/819
+TEST(TestMideaACClass, SwingV) {
+ IRMideaAC ac(0);
+ ac.setSwingVToggle(false);
+ ASSERT_FALSE(ac.getSwingVToggle());
+ ac.setSwingVToggle(true);
+ ASSERT_TRUE(ac.getSwingVToggle());
+ EXPECT_EQ(
+ "Power: On, Mode: 2 (AUTO), Celsius: Off, Temp: 25C/77F, Fan: 0 (Auto), "
+ "Sleep: Off, Swing(V) Toggle: On", ac.toString());
+ ac.setSwingVToggle(false);
+ ASSERT_FALSE(ac.getSwingVToggle());
+ EXPECT_EQ(
+ "Power: On, Mode: 2 (AUTO), Celsius: Off, Temp: 25C/77F, Fan: 0 (Auto), "
+ "Sleep: Off, Swing(V) Toggle: Off", ac.toString());
+ ac.setRaw(kMideaACToggleSwingV);
+ EXPECT_EQ("Swing(V) Toggle: On", ac.toString());
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_MitsubishiHeavy_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_MitsubishiHeavy_test.cpp
similarity index 87%
rename from lib/IRremoteESP8266-2.6.0/test/ir_MitsubishiHeavy_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_MitsubishiHeavy_test.cpp
index 340a04078..0af6b5d07 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_MitsubishiHeavy_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_MitsubishiHeavy_test.cpp
@@ -293,7 +293,7 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) {
IRMitsubishiHeavy152Ac ac(0);
EXPECT_EQ(
- "Power: Off, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), "
+ "Power: Off, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (Auto), "
"Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, "
"Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off",
ac.toString());
@@ -310,7 +310,7 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) {
ac.setSwingVertical(kMitsubishiHeavy152SwingVAuto);
ac.setSwingHorizontal(kMitsubishiHeavy152SwingHAuto);
EXPECT_EQ(
- "Power: On, Mode: 1 (Cool), Temp: 17C, Fan: 4 (Max), "
+ "Power: On, Mode: 1 (COOL), Temp: 17C, Fan: 4 (Max), "
"Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: On, Turbo: Off, "
"Econo: Off, Night: On, Filter: On, 3D: On, Clean: Off",
ac.toString());
@@ -327,7 +327,7 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) {
ac.setSwingHorizontal(kMitsubishiHeavy152SwingHLeftMax);
EXPECT_EQ(
- "Power: On, Mode: 4 (Heat), Temp: 31C, Fan: 8 (Turbo), "
+ "Power: On, Mode: 4 (HEAT), Temp: 31C, Fan: 8 (Turbo), "
"Swing (V): 5 (Lowest), Swing (H): 1 (Max Left), Silent: Off, Turbo: On, "
"Econo: Off, Night: Off, Filter: On, 3D: Off, Clean: Off",
ac.toString());
@@ -338,7 +338,7 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) {
ac.setSwingVertical(kMitsubishiHeavy152SwingVOff);
EXPECT_EQ(
- "Power: On, Mode: 0 (Auto), Temp: 31C, Fan: 6 (Econo), "
+ "Power: On, Mode: 0 (AUTO), Temp: 31C, Fan: 6 (Econo), "
"Swing (V): 6 (Off), Swing (H): 1 (Max Left), Silent: Off, "
"Turbo: Off, Econo: On, Night: Off, Filter: On, 3D: Off, Clean: On",
ac.toString());
@@ -349,7 +349,7 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) {
ac.setMode(kMitsubishiHeavyDry);
ac.setSwingHorizontal(kMitsubishiHeavy152SwingHLeftRight);
EXPECT_EQ(
- "Power: On, Mode: 2 (Dry), Temp: 25C, Fan: 0 (Auto), "
+ "Power: On, Mode: 2 (DRY), Temp: 25C, Fan: 0 (Auto), "
"Swing (V): 6 (Off), Swing (H): 7 (Left Right), Silent: Off, "
"Turbo: Off, Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off",
ac.toString());
@@ -359,7 +359,7 @@ TEST(TestMitsubishiHeavy152AcClass, ReconstructKnownExample) {
IRMitsubishiHeavy152Ac ac(0);
EXPECT_EQ(
- "Power: Off, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), "
+ "Power: Off, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (Auto), "
"Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, "
"Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off",
ac.toString());
@@ -377,7 +377,7 @@ TEST(TestMitsubishiHeavy152AcClass, ReconstructKnownExample) {
ac.setSwingVertical(kMitsubishiHeavy152SwingVAuto);
ac.setSwingHorizontal(kMitsubishiHeavy152SwingHAuto);
EXPECT_EQ(
- "Power: On, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), "
+ "Power: On, Mode: 4 (HEAT), Temp: 24C, Fan: 4 (Max), "
"Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, "
"Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off",
ac.toString());
@@ -635,7 +635,7 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) {
IRMitsubishiHeavy88Ac ac(0);
EXPECT_EQ(
- "Power: Off, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), "
+ "Power: Off, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (Auto), "
"Swing (V): 0 (Off), Swing (H): 0 (Off), "
"Turbo: Off, Econo: Off, 3D: Off, Clean: Off",
ac.toString());
@@ -648,7 +648,7 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) {
ac.set3D(true);
ac.setSwingVertical(kMitsubishiHeavy88SwingVAuto);
EXPECT_EQ(
- "Power: On, Mode: 1 (Cool), Temp: 17C, Fan: 4 (High), "
+ "Power: On, Mode: 1 (COOL), Temp: 17C, Fan: 4 (High), "
"Swing (V): 16 (Auto), Swing (H): 200 (3D), "
"Turbo: Off, Econo: Off, 3D: On, Clean: Off",
ac.toString());
@@ -662,7 +662,7 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) {
ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftMax);
EXPECT_EQ(
- "Power: On, Mode: 4 (Heat), Temp: 31C, Fan: 6 (Turbo), "
+ "Power: On, Mode: 4 (HEAT), Temp: 31C, Fan: 6 (Turbo), "
"Swing (V): 26 (Lowest), Swing (H): 4 (Max Left), Turbo: On, Econo: Off, "
"3D: Off, Clean: Off",
ac.toString());
@@ -673,7 +673,7 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) {
ac.setSwingVertical(kMitsubishiHeavy88SwingVOff);
EXPECT_EQ(
- "Power: On, Mode: 0 (Auto), Temp: 31C, Fan: 7 (Econo), "
+ "Power: On, Mode: 0 (AUTO), Temp: 31C, Fan: 7 (Econo), "
"Swing (V): 0 (Off), Swing (H): 4 (Max Left), Turbo: Off, Econo: On, "
"3D: Off, Clean: On",
ac.toString());
@@ -684,7 +684,7 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) {
ac.setMode(kMitsubishiHeavyDry);
ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftRight);
EXPECT_EQ(
- "Power: On, Mode: 2 (Dry), Temp: 25C, Fan: 0 (Auto), "
+ "Power: On, Mode: 2 (DRY), Temp: 25C, Fan: 0 (Auto), "
"Swing (V): 0 (Off), Swing (H): 72 (Left Right), Turbo: Off, Econo: Off, "
"3D: Off, Clean: Off",
ac.toString());
@@ -704,7 +704,7 @@ TEST(TestDecodeMitsubishiHeavy, ZmsRealExample) {
0xF8, 0x04, 0xFB, 0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0x80, 0x7F};
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/660#issuecomment-480571466
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/660#issuecomment-480571466
uint16_t rawData[307] = {
3136, 1638, 364, 428, 366, 1224, 362, 432, 364, 430, 364, 1226, 362, 432,
364, 1224, 366, 428, 366, 430, 366, 1224, 362, 1228, 362, 1228, 362, 432,
@@ -739,7 +739,7 @@ TEST(TestDecodeMitsubishiHeavy, ZmsRealExample) {
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), "
+ "Power: On, Mode: 4 (HEAT), Temp: 24C, Fan: 4 (Max), "
"Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, "
"Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off",
ac.toString());
@@ -766,7 +766,7 @@ TEST(TestDecodeMitsubishiHeavy, ZmsSyntheticExample) {
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), "
+ "Power: On, Mode: 4 (HEAT), Temp: 24C, Fan: 4 (Max), "
"Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, "
"Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off",
ac.toString());
@@ -784,7 +784,7 @@ TEST(TestDecodeMitsubishiHeavy, ZmsRealExample2) {
0xF8, 0x04, 0xFB, 0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0x80, 0x7F};
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/660#issuecomment-480571466
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/660#issuecomment-480571466
uint16_t rawData[307] = {
3196, 1580, 398, 390, 404, 1190, 400, 390, 402, 390, 402, 1192, 402, 388,
402, 1192, 400, 390, 402, 392, 402, 1192, 400, 1188, 400, 1188, 400, 390,
@@ -819,7 +819,7 @@ TEST(TestDecodeMitsubishiHeavy, ZmsRealExample2) {
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: Off, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), "
+ "Power: Off, Mode: 4 (HEAT), Temp: 24C, Fan: 4 (Max), "
"Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, "
"Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off",
ac.toString());
@@ -844,8 +844,77 @@ TEST(TestDecodeMitsubishiHeavy, ZjsSyntheticExample) {
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 2 (Dry), Temp: 25C, Fan: 0 (Auto), "
+ "Power: On, Mode: 2 (DRY), Temp: 25C, Fan: 0 (Auto), "
"Swing (V): 0 (Off), Swing (H): 72 (Left Right), Turbo: Off, Econo: Off, "
"3D: Off, Clean: Off",
ac.toString());
}
+
+TEST(TestMitsubishiHeavy152AcClass, toCommon) {
+ IRMitsubishiHeavy152Ac ac(0);
+ ac.setPower(true);
+ ac.setMode(kMitsubishiHeavyCool);
+ ac.setTemp(20);
+ ac.setFan(kMitsubishiHeavy152FanLow);
+ ac.setSwingVertical(kMitsubishiHeavy152SwingVHighest);
+ ac.setSwingHorizontal(kMitsubishiHeavy152SwingHRightMax);
+ ac.setTurbo(false);
+ ac.setEcono(true);
+ ac.setClean(true);
+ ac.setFilter(true);
+ ac.setSilent(true);
+ ac.setNight(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::MITSUBISHI_HEAVY_152, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMin, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kHighest, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kRightMax, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().econo);
+ ASSERT_TRUE(ac.toCommon().clean);
+ ASSERT_TRUE(ac.toCommon().quiet);
+ ASSERT_TRUE(ac.toCommon().filter);
+ ASSERT_EQ(0, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestMitsubishiHeavy88AcClass, toCommon) {
+ IRMitsubishiHeavy88Ac ac(0);
+ ac.setPower(true);
+ ac.setMode(kMitsubishiHeavyCool);
+ ac.setTemp(20);
+ ac.setFan(kMitsubishiHeavy88FanLow);
+ ac.setSwingVertical(kMitsubishiHeavy88SwingVHighest);
+ ac.setSwingHorizontal(kMitsubishiHeavy88SwingHRightMax);
+ ac.setTurbo(false);
+ ac.setEcono(true);
+ ac.setClean(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::MITSUBISHI_HEAVY_88, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMin, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kHighest, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kRightMax, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().econo);
+ ASSERT_TRUE(ac.toCommon().clean);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Mitsubishi_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Mitsubishi_test.cpp
similarity index 97%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Mitsubishi_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Mitsubishi_test.cpp
index 6c9480b31..7d16ed91e 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Mitsubishi_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Mitsubishi_test.cpp
@@ -984,8 +984,8 @@ TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatNeededButError) {
TEST(TestMitsubishiACClass, HumanReadable) {
IRMitsubishiAC irMitsu(0);
EXPECT_EQ(
- "Power: On (HEAT), Temp: 22C, FAN: SILENT, VANE: AUTO, "
- "Time: 17:10, On timer: 00:00, Off timer: 00:00, Timer: -",
+ "Power: On, Mode: 8 (HEAT), Temp: 22C, Fan: 6 (Quiet), Vane: AUTO, "
+ "Wide Vane: 3, Time: 17:10, On timer: 00:00, Off timer: 00:00, Timer: -",
irMitsu.toString());
}
@@ -1133,3 +1133,33 @@ TEST(TestDecodeMitsubishi2, DecodeRealExample) {
EXPECT_EQ(0xF, irsend.capture.address);
EXPECT_EQ(0x82, irsend.capture.command);
}
+
+TEST(TestMitsubishiACClass, toCommon) {
+ IRMitsubishiAC ac(0);
+ ac.setPower(true);
+ ac.setMode(kMitsubishiAcCool);
+ ac.setTemp(20);
+ ac.setFan(kMitsubishiAcFanSilent);
+ ac.setVane(kMitsubishiAcVaneAuto);
+ ac.setWideVane(kMitsubishiAcWideVaneAuto);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::MITSUBISHI_AC, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMin, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh);
+ ASSERT_TRUE(ac.toCommon().quiet);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_NEC_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_NEC_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_NEC_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_NEC_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Neoclima_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Neoclima_test.cpp
new file mode 100644
index 000000000..38747f276
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Neoclima_test.cpp
@@ -0,0 +1,434 @@
+// Copyright 2019 David Conran (crankyoldgit)
+
+#include "ir_Neoclima.h"
+#include
+#include "IRsend.h"
+#include "IRsend_test.h"
+#include "IRrecv.h"
+#include "IRrecv_test.h"
+#include "gtest/gtest.h"
+
+TEST(TestUtils, Housekeeping) {
+ ASSERT_EQ("NEOCLIMA", typeToString(decode_type_t::NEOCLIMA));
+ ASSERT_EQ(decode_type_t::NEOCLIMA, strToDecodeType("NEOCLIMA"));
+ ASSERT_TRUE(hasACState(decode_type_t::NEOCLIMA));
+}
+
+// Test sending typical data only.
+TEST(TestSendNeoclima, SendDataOnly) {
+ IRsendTest irsend(0);
+ irsend.begin();
+
+ uint8_t state[kNeoclimaStateLength] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6A, 0x00, 0x2A, 0xA5, 0x39};
+ irsend.reset();
+ irsend.sendNeoclima(state);
+ EXPECT_EQ(
+ "f38000d50"
+ "m6112s7391"
+ "m537s571m537s571m537s571m537s571m537s571m537s571m537s571m537s571"
+ "m537s571m537s571m537s571m537s571m537s571m537s571m537s571m537s571"
+ "m537s571m537s571m537s571m537s571m537s571m537s571m537s571m537s571"
+ "m537s571m537s571m537s571m537s571m537s571m537s571m537s571m537s571"
+ "m537s571m537s571m537s571m537s571m537s571m537s571m537s571m537s571"
+ "m537s571m537s571m537s571m537s571m537s571m537s571m537s571m537s571"
+ "m537s571m537s571m537s571m537s571m537s571m537s571m537s571m537s571"
+ "m537s571m537s1651m537s571m537s1651m537s571m537s1651m537s1651m537s571"
+ "m537s571m537s571m537s571m537s571m537s571m537s571m537s571m537s571"
+ "m537s571m537s1651m537s571m537s1651m537s571m537s1651m537s571m537s571"
+ "m537s1651m537s571m537s1651m537s571m537s571m537s1651m537s571m537s1651"
+ "m537s1651m537s571m537s571m537s1651m537s1651m537s1651m537s571m537s571"
+ "m537s7391"
+ "m537s100000",
+ irsend.outputStr());
+}
+
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/764#issuecomment-503755096
+TEST(TestDecodeNeoclima, RealExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ uint16_t rawData[197] = {
+ 6112, 7392, 540, 602, 516, 578, 522, 604, 540, 554, 540, 554, 540, 576,
+ 518, 576, 516, 554, 540, 608, 542, 554, 540, 554, 540, 576, 518, 604, 516,
+ 556, 540, 576, 546, 580, 542, 578, 542, 602, 518, 554, 542, 554, 568, 582,
+ 540, 554, 540, 582, 540, 578, 518, 582, 542, 576, 544, 530, 566, 534, 562,
+ 534, 562, 552, 542, 582, 540, 604, 518, 608, 542, 554, 540, 582, 540, 604,
+ 518, 580, 540, 606, 544, 554, 542, 554, 542, 580, 542, 576, 520, 554, 540,
+ 578, 518, 578, 518, 582, 544, 552, 570, 580, 544, 580, 542, 554, 542, 604,
+ 520, 576, 520, 580, 540, 556, 540, 556, 542, 584, 566, 580, 542, 1622,
+ 542, 554, 542, 1620, 544, 604, 520, 1642, 518, 1674, 548, 560, 564, 580,
+ 544, 554, 544, 552, 544, 554, 542, 556, 542, 576, 522, 554, 542, 556, 542,
+ 580, 542, 1670, 520, 578, 520, 1622, 542, 580, 518, 1646, 520, 558, 568,
+ 552, 546, 1628, 566, 580, 544, 1668, 522, 576, 520, 578, 520, 1670, 522,
+ 576, 522, 1670, 496, 1676, 570, 560, 566, 532, 564, 1648, 544, 1670, 522,
+ 1650, 544, 552, 544, 576, 520, 7390, 544}; // UNKNOWN EE182D95
+
+ uint8_t expectedState[kNeoclimaStateLength] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6A, 0x00, 0x2A, 0xA5, 0x39};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendRaw(rawData, 197, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(decode_type_t::NEOCLIMA, irsend.capture.decode_type);
+ ASSERT_EQ(kNeoclimaBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+ IRNeoclimaAc ac(0);
+ ac.setRaw(irsend.capture.state);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 26C, Fan: 3 (Low), "
+ "Swing(V): Off, Swing(H): On, Sleep: Off, Turbo: Off, Hold: Off, "
+ "Ion: Off, Eye: Off, Light: Off, Follow: Off, 8C Heat: Off, Fresh: Off, "
+ "Button: 0 (Power)",
+ ac.toString());
+}
+
+// Self decode.
+TEST(TestDecodeNeoclima, SyntheticExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+
+ uint8_t expectedState[kNeoclimaStateLength] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6A, 0x00, 0x2A, 0xA5, 0x39};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendNeoclima(expectedState);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(decode_type_t::NEOCLIMA, irsend.capture.decode_type);
+ ASSERT_EQ(kNeoclimaBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+}
+
+TEST(TestIRNeoclimaAcClass, Power) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+
+ ac.on();
+ EXPECT_TRUE(ac.getPower());
+
+ ac.off();
+ EXPECT_FALSE(ac.getPower());
+
+ ac.setPower(true);
+ EXPECT_TRUE(ac.getPower());
+
+ ac.setPower(false);
+ EXPECT_FALSE(ac.getPower());
+
+ EXPECT_EQ(kNeoclimaButtonPower, ac.getButton());
+}
+
+TEST(TestIRNeoclimaAcClass, OperatingMode) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+
+ ac.setMode(kNeoclimaAuto);
+ EXPECT_EQ(kNeoclimaAuto, ac.getMode());
+ EXPECT_EQ(kNeoclimaButtonMode, ac.getButton());
+
+
+ ac.setMode(kNeoclimaCool);
+ EXPECT_EQ(kNeoclimaCool, ac.getMode());
+
+ ac.setMode(kNeoclimaHeat);
+ EXPECT_EQ(kNeoclimaHeat, ac.getMode());
+
+ ASSERT_NE(kNeoclimaFanHigh, kNeoclimaFanLow);
+ ac.setFan(kNeoclimaFanHigh);
+ ac.setMode(kNeoclimaDry); // Dry should lock the fan to speed LOW.
+ EXPECT_EQ(kNeoclimaDry, ac.getMode());
+ EXPECT_EQ(kNeoclimaFanLow, ac.getFan());
+ ac.setFan(kNeoclimaFanHigh);
+ EXPECT_EQ(kNeoclimaFanLow, ac.getFan());
+
+ ac.setMode(kNeoclimaFan);
+ EXPECT_EQ(kNeoclimaFan, ac.getMode());
+
+ ac.setMode(kNeoclimaHeat + 1);
+ EXPECT_EQ(kNeoclimaAuto, ac.getMode());
+
+ ac.setMode(255);
+ EXPECT_EQ(kNeoclimaAuto, ac.getMode());
+}
+
+TEST(TestIRNeoclimaAcClass, SetAndGetTemp) {
+ IRNeoclimaAc ac(0);
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+ ac.setTemp(kNeoclimaMinTemp);
+ EXPECT_EQ(kNeoclimaMinTemp, ac.getTemp());
+ EXPECT_EQ(kNeoclimaButtonTempDown, ac.getButton());
+ ac.setTemp(kNeoclimaMinTemp - 1);
+ EXPECT_EQ(kNeoclimaMinTemp, ac.getTemp());
+ ac.setTemp(kNeoclimaMaxTemp);
+ EXPECT_EQ(kNeoclimaMaxTemp, ac.getTemp());
+ EXPECT_EQ(kNeoclimaButtonTempUp, ac.getButton());
+ ac.setTemp(kNeoclimaMaxTemp + 1);
+ EXPECT_EQ(kNeoclimaMaxTemp, ac.getTemp());
+}
+
+TEST(TestIRNeoclimaAcClass, FanSpeed) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+
+ ac.setFan(0);
+ EXPECT_EQ(0, ac.getFan());
+
+ ac.setFan(255);
+ EXPECT_EQ(kNeoclimaFanAuto, ac.getFan());
+
+ ac.setFan(kNeoclimaFanHigh);
+ EXPECT_EQ(kNeoclimaFanHigh, ac.getFan());
+
+ ac.setFan(std::max(kNeoclimaFanHigh, kNeoclimaFanLow) + 1);
+ EXPECT_EQ(kNeoclimaFanAuto, ac.getFan());
+
+ ac.setFan(kNeoclimaFanHigh - 1);
+ EXPECT_EQ(kNeoclimaFanHigh - 1, ac.getFan());
+
+ ac.setFan(1);
+ EXPECT_EQ(1, ac.getFan());
+
+ ac.setFan(1);
+ EXPECT_EQ(1, ac.getFan());
+
+ ac.setFan(3);
+ EXPECT_EQ(3, ac.getFan());
+ EXPECT_EQ(kNeoclimaButtonFanSpeed, ac.getButton());
+
+ // Data from:
+ // https://drive.google.com/file/d/1kjYk4zS9NQcMQhFkak-L4mp4UuaAIesW/view
+ uint8_t fan_low[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x6A, 0x00, 0x29, 0xA5, 0x3D};
+ uint8_t fan_medium[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x4A, 0x00, 0x29, 0xA5, 0x1D};
+ uint8_t fan_high[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x29, 0xA5, 0xFD};
+ uint8_t fan_auto[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x29, 0xA5, 0xDD};
+ ac.setRaw(fan_low);
+ EXPECT_EQ(kNeoclimaFanLow, ac.getFan());
+ EXPECT_EQ(kNeoclimaButtonFanSpeed, ac.getButton());
+ ac.setRaw(fan_medium);
+ EXPECT_EQ(kNeoclimaFanMed, ac.getFan());
+ EXPECT_EQ(kNeoclimaButtonFanSpeed, ac.getButton());
+ ac.setRaw(fan_high);
+ EXPECT_EQ(kNeoclimaFanHigh, ac.getFan());
+ EXPECT_EQ(kNeoclimaButtonFanSpeed, ac.getButton());
+ ac.setRaw(fan_auto);
+ EXPECT_EQ(kNeoclimaFanAuto, ac.getFan());
+ EXPECT_EQ(kNeoclimaButtonFanSpeed, ac.getButton());
+}
+
+TEST(TestIRNeoclimaAcClass, Sleep) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+ ac.setSleep(true);
+ EXPECT_TRUE(ac.getSleep());
+ ac.setSleep(false);
+ EXPECT_FALSE(ac.getSleep());
+ ac.setSleep(true);
+ EXPECT_TRUE(ac.getSleep());
+ EXPECT_EQ(kNeoclimaButtonSleep, ac.getButton());
+}
+
+TEST(TestIRNeoclimaAcClass, Turbo) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+ ac.setTurbo(true);
+ EXPECT_TRUE(ac.getTurbo());
+ ac.setTurbo(false);
+ EXPECT_FALSE(ac.getTurbo());
+ ac.setTurbo(true);
+ EXPECT_TRUE(ac.getTurbo());
+ EXPECT_EQ(kNeoclimaButtonTurbo, ac.getButton());
+ // Data from:
+ // https://drive.google.com/file/d/1tA09Gu_ZqDcHucscnqzv0V3cIUWOE0d1/view
+ uint8_t turbo_on[12] = {
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x6A, 0x00, 0x88, 0xA5, 0xA9};
+ uint8_t turbo_off[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x6A, 0x00, 0x88, 0xA5, 0xA1};
+ ac.setRaw(turbo_on);
+ EXPECT_TRUE(ac.getTurbo());
+ EXPECT_EQ(kNeoclimaButtonTurbo, ac.getButton());
+ ac.setRaw(turbo_off);
+ EXPECT_EQ(kNeoclimaButtonTurbo, ac.getButton());
+ EXPECT_FALSE(ac.getTurbo());
+}
+
+TEST(TestIRNeoclimaAcClass, Fresh) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+ ac.setFresh(true);
+ EXPECT_TRUE(ac.getFresh());
+ ac.setFresh(false);
+ EXPECT_FALSE(ac.getFresh());
+ ac.setFresh(true);
+ EXPECT_TRUE(ac.getFresh());
+ EXPECT_EQ(kNeoclimaButtonFresh, ac.getButton());
+ // Data from:
+ // https://drive.google.com/file/d/1kjYk4zS9NQcMQhFkak-L4mp4UuaAIesW/view
+ uint8_t on[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x6A, 0x00, 0x29, 0xA5, 0xCD};
+ uint8_t off[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x6A, 0x00, 0x29, 0xA5, 0x4D};
+ ac.setRaw(on);
+ EXPECT_TRUE(ac.getFresh());
+ EXPECT_EQ(kNeoclimaButtonFresh, ac.getButton());
+ ac.setRaw(off);
+ EXPECT_EQ(kNeoclimaButtonFresh, ac.getButton());
+ EXPECT_FALSE(ac.getFresh());
+}
+
+TEST(TestIRNeoclimaAcClass, Hold) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+ ac.setHold(true);
+ EXPECT_TRUE(ac.getHold());
+ ac.setHold(false);
+ EXPECT_FALSE(ac.getHold());
+ ac.setHold(true);
+ EXPECT_TRUE(ac.getHold());
+ EXPECT_EQ(kNeoclimaButtonHold, ac.getButton());
+}
+
+TEST(TestIRNeoclimaAcClass, 8CHeat) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+ ac.set8CHeat(true);
+ EXPECT_TRUE(ac.get8CHeat());
+ ac.set8CHeat(false);
+ EXPECT_FALSE(ac.get8CHeat());
+ ac.set8CHeat(true);
+ EXPECT_TRUE(ac.get8CHeat());
+ EXPECT_EQ(kNeoclimaButton8CHeat, ac.getButton());
+}
+
+TEST(TestIRNeoclimaAcClass, Light) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+ ac.setLight(true);
+ EXPECT_TRUE(ac.getLight());
+ ac.setLight(false);
+ EXPECT_FALSE(ac.getLight());
+ ac.setLight(true);
+ EXPECT_TRUE(ac.getLight());
+ EXPECT_EQ(kNeoclimaButtonLight, ac.getButton());
+}
+
+TEST(TestIRNeoclimaAcClass, Ion) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+ ac.setIon(true);
+ EXPECT_TRUE(ac.getIon());
+ ac.setIon(false);
+ EXPECT_FALSE(ac.getIon());
+ ac.setIon(true);
+ EXPECT_TRUE(ac.getIon());
+ EXPECT_EQ(kNeoclimaButtonIon, ac.getButton());
+}
+
+TEST(TestIRNeoclimaAcClass, Eye) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+ ac.setEye(true);
+ EXPECT_TRUE(ac.getEye());
+ ac.setEye(false);
+ EXPECT_FALSE(ac.getEye());
+ ac.setEye(true);
+ EXPECT_TRUE(ac.getEye());
+ EXPECT_EQ(kNeoclimaButtonEye, ac.getButton());
+}
+
+TEST(TestIRNeoclimaAcClass, Follow) {
+ IRNeoclimaAc ac(0);
+ ac.begin();
+ /* DISABLED: See TODO in ir_Neoclima.cpp
+ ac.setFollow(true);
+ EXPECT_TRUE(ac.getFollow());
+ ac.setFollow(false);
+ EXPECT_FALSE(ac.getFollow());
+ ac.setFollow(true);
+ EXPECT_TRUE(ac.getFollow());
+ EXPECT_EQ(kNeoclimaButtonFollow, ac.getButton());
+ */
+ uint8_t on_5F[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x0A, 0x5F, 0x89, 0xA5, 0xAA};
+ uint8_t on_5D[12] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x6A, 0x5D, 0x29, 0xA5, 0xA8};
+ uint8_t off[12] = {
+ 0x00, 0x04, 0x00, 0x40, 0x00, 0x13, 0x00, 0x6B, 0x00, 0x29, 0xA5, 0x90};
+ ac.setRaw(on_5F);
+ EXPECT_TRUE(ac.getFollow());
+ ac.setRaw(off);
+ EXPECT_FALSE(ac.getFollow());
+ ac.setRaw(on_5D);
+ EXPECT_TRUE(ac.getFollow());
+}
+
+TEST(TestIRNeoclimaAcClass, ChecksumCalculation) {
+ uint8_t examplestate[kNeoclimaStateLength] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6A, 0x00, 0x2A, 0xA5, 0x39};
+ const uint8_t originalstate[kNeoclimaStateLength] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6A, 0x00, 0x2A, 0xA5, 0x39};
+
+ EXPECT_TRUE(IRNeoclimaAc::validChecksum(examplestate));
+ EXPECT_EQ(0x39, IRNeoclimaAc::calcChecksum(examplestate));
+
+ examplestate[11] = 0x12; // Set an incorrect checksum.
+ EXPECT_FALSE(IRNeoclimaAc::validChecksum(examplestate));
+ EXPECT_EQ(0x39, IRNeoclimaAc::calcChecksum(examplestate));
+ IRNeoclimaAc ac(0);
+ ac.setRaw(examplestate);
+ // Extracting the state from the object should have a correct checksum.
+ EXPECT_TRUE(IRNeoclimaAc::validChecksum(ac.getRaw()));
+ EXPECT_STATE_EQ(originalstate, ac.getRaw(), kNeoclimaBits);
+ examplestate[11] = 0x39; // Restore old checksum value.
+
+ // Change the state to force a different checksum.
+ examplestate[8] = 0x01;
+ EXPECT_FALSE(IRNeoclimaAc::validChecksum(examplestate));
+ EXPECT_EQ(0x3A, IRNeoclimaAc::calcChecksum(examplestate));
+}
+
+TEST(TestIRNeoclimaAcClass, toCommon) {
+ IRNeoclimaAc ac(0);
+ ac.setPower(true);
+ ac.setMode(kNeoclimaCool);
+ ac.setTemp(20);
+ ac.setFan(kNeoclimaFanHigh);
+ ac.setSwingV(true);
+ ac.setSwingH(true);
+ ac.setTurbo(false);
+ ac.setIon(true);
+ ac.setLight(true);
+ ac.setSleep(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::NEOCLIMA, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().filter);
+ ASSERT_TRUE(ac.toCommon().light);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh);
+ ASSERT_EQ(0, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Nikai_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Nikai_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Nikai_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Nikai_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Panasonic_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Panasonic_test.cpp
similarity index 95%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Panasonic_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Panasonic_test.cpp
index 4d10f8fb1..7f84c2a8a 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Panasonic_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Panasonic_test.cpp
@@ -543,7 +543,7 @@ TEST(TestIRPanasonicAcClass, ChecksumCalculation) {
EXPECT_TRUE(IRPanasonicAc::validChecksum(examplestate));
EXPECT_EQ(0x83, IRPanasonicAc::calcChecksum(examplestate));
- examplestate[kPanasonicAcStateLength - 1] = 0x0; // Set incoorect checksum.
+ examplestate[kPanasonicAcStateLength - 1] = 0x0; // Set incorrect checksum.
EXPECT_FALSE(IRPanasonicAc::validChecksum(examplestate));
EXPECT_EQ(0x83, IRPanasonicAc::calcChecksum(examplestate));
pana.setRaw(examplestate);
@@ -739,7 +739,7 @@ TEST(TestIRPanasonicAcClass, HumanReadable) {
EXPECT_EQ(
"Model: 4 (JKE), Power: Off, Mode: 0 (AUTO), Temp: 0C, "
"Fan: 253 (UNKNOWN), Swing (Vertical): 0 (UNKNOWN), Quiet: Off, "
- "Powerful: Off, Clock: 0:00, On Timer: Off, Off Timer: Off",
+ "Powerful: Off, Clock: 00:00, On Timer: Off, Off Timer: Off",
pana.toString());
pana.setPower(true);
pana.setTemp(kPanasonicAcMaxTemp);
@@ -749,24 +749,24 @@ TEST(TestIRPanasonicAcClass, HumanReadable) {
pana.setPowerful(true);
EXPECT_EQ(
"Model: 4 (JKE), Power: On, Mode: 4 (HEAT), Temp: 30C, "
- "Fan: 4 (MAX), Swing (Vertical): 15 (AUTO), Quiet: Off, "
- "Powerful: On, Clock: 0:00, On Timer: Off, Off Timer: Off",
+ "Fan: 4 (High), Swing (Vertical): 15 (AUTO), Quiet: Off, "
+ "Powerful: On, Clock: 00:00, On Timer: Off, Off Timer: Off",
pana.toString());
pana.setQuiet(true);
pana.setModel(kPanasonicLke);
EXPECT_EQ(
"Model: 1 (LKE), Power: Off, Mode: 4 (HEAT), Temp: 30C, "
- "Fan: 4 (MAX), Swing (Vertical): 15 (AUTO), "
+ "Fan: 4 (High), Swing (Vertical): 15 (AUTO), "
"Swing (Horizontal): 6 (Middle), Quiet: On, Powerful: Off, "
- "Clock: 0:00, On Timer: 0:00, Off Timer: Off",
+ "Clock: 00:00, On Timer: 00:00, Off Timer: Off",
pana.toString());
pana.setModel(kPanasonicDke);
pana.setSwingHorizontal(kPanasonicAcSwingHRight);
EXPECT_EQ(
"Model: 3 (DKE), Power: Off, Mode: 4 (HEAT), Temp: 30C, "
- "Fan: 4 (MAX), Swing (Vertical): 15 (AUTO), "
+ "Fan: 4 (High), Swing (Vertical): 15 (AUTO), "
"Swing (Horizontal): 11 (Right), Quiet: On, Powerful: Off, "
- "Clock: 0:00, On Timer: Off, Off Timer: Off",
+ "Clock: 00:00, On Timer: Off, Off Timer: Off",
pana.toString());
}
@@ -857,8 +857,8 @@ TEST(TestDecodePanasonicAC, SyntheticExample) {
pana.setRaw(irsend.capture.state);
EXPECT_EQ(
"Model: 4 (JKE), Power: Off, Mode: 3 (COOL), Temp: 25C, "
- "Fan: 7 (AUTO), Swing (Vertical): 15 (AUTO), Quiet: Off, "
- "Powerful: Off, Clock: 0:00, On Timer: Off, Off Timer: Off",
+ "Fan: 7 (Auto), Swing (Vertical): 15 (AUTO), Quiet: Off, "
+ "Powerful: Off, Clock: 00:00, On Timer: Off, Off Timer: Off",
pana.toString());
}
@@ -936,9 +936,9 @@ TEST(TestDecodePanasonicAC, Issue540) {
// TODO(crankyoldgit): Try to figure out what model this should be.
EXPECT_EQ(
"Model: 0 (UNKNOWN), Power: On, Mode: 3 (COOL), Temp: 26C, "
- "Fan: 7 (AUTO), Swing (Vertical): 15 (AUTO), "
+ "Fan: 7 (Auto), Swing (Vertical): 15 (AUTO), "
"Swing (Horizontal): 13 (AUTO), Quiet: Off, Powerful: Off, "
- "Clock: 0:00, On Timer: Off, Off Timer: Off",
+ "Clock: 00:00, On Timer: Off, Off Timer: Off",
pana.toString());
}
@@ -948,20 +948,10 @@ TEST(TestIRPanasonicAcClass, TimeBasics) {
EXPECT_EQ(0x448, IRPanasonicAc::encodeTime(18, 16));
EXPECT_EQ(0, IRPanasonicAc::encodeTime(0, 0));
EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(23, 59));
- EXPECT_EQ("16:10",
- IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(16, 10)));
- EXPECT_EQ("6:30",
- IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(6, 30)));
- EXPECT_EQ("18:16",
- IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(18, 16)));
- EXPECT_EQ("1:01",
- IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(1, 1)));
EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(23, 59));
EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(25, 72));
EXPECT_EQ(59, IRPanasonicAc::encodeTime(0, 72));
EXPECT_EQ(23 * 60, IRPanasonicAc::encodeTime(27, 0));
- EXPECT_EQ("0:00", IRPanasonicAc::timeToString(0));
- EXPECT_EQ("23:59", IRPanasonicAc::timeToString(kPanasonicAcTimeMax));
}
TEST(TestIRPanasonicAcClass, TimersAndClock) {
@@ -1126,8 +1116,8 @@ TEST(TestDecodePanasonicAC, CkpModelSpecifics) {
pana.setRaw(irsend.capture.state);
EXPECT_EQ(
"Model: 5 (CKP), Power: Off, Mode: 4 (HEAT), Temp: 23C, "
- "Fan: 7 (AUTO), Swing (Vertical): 15 (AUTO), Quiet: Off, "
- "Powerful: On, Clock: 0:00, On Timer: 0:00, Off Timer: 0:00",
+ "Fan: 7 (Auto), Swing (Vertical): 15 (AUTO), Quiet: Off, "
+ "Powerful: On, Clock: 00:00, On Timer: 00:00, Off Timer: 00:00",
pana.toString());
pana.setQuiet(true);
@@ -1142,3 +1132,36 @@ TEST(TestDecodePanasonicAC, CkpModelSpecifics) {
EXPECT_EQ(kPanasonicCkp, pana.getModel());
EXPECT_STATE_EQ(ckpPowerfulOn, pana.getRaw(), kPanasonicAcBits);
}
+
+TEST(TestIRPanasonicAcClass, toCommon) {
+ IRPanasonicAc ac(0);
+ ac.setModel(panasonic_ac_remote_model_t::kPanasonicDke);
+ ac.setPower(true);
+ ac.setMode(kPanasonicAcCool);
+ ac.setTemp(20);
+ ac.setFan(kPanasonicAcFanMax);
+ ac.setSwingVertical(kPanasonicAcSwingVAuto);
+ ac.setSwingHorizontal(kPanasonicAcSwingHMiddle);
+ ac.setPowerful(true);
+ ac.setQuiet(false);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::PANASONIC_AC, ac.toCommon().protocol);
+ ASSERT_EQ(panasonic_ac_remote_model_t::kPanasonicDke, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kMiddle, ac.toCommon().swingh);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Pioneer_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Pioneer_test.cpp
similarity index 60%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Pioneer_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Pioneer_test.cpp
index 36d61c706..37cb56fa2 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Pioneer_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Pioneer_test.cpp
@@ -13,35 +13,35 @@ TEST(TestSendPioneer, SendDataOnly) {
irsend.begin();
irsend.sendPioneer(0);
EXPECT_EQ(
- "f38000d33"
- "m8960s4480"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s58240"
- "m8960s4480"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s58240",
+ "f40000d33"
+ "m8544s4272"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s37380"
+ "m8544s4272"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s37380",
irsend.outputStr());
irsend.sendPioneer(0x55FF00AAAA00FF55);
EXPECT_EQ(
- "f38000d33"
- "m8960s4480"
- "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680"
- "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
- "m560s40320"
- "m8960s4480"
- "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
- "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
- "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
- "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680"
- "m560s40320",
+ "f40000d33"
+ "m8544s4272"
+ "m534s534m534s1602m534s534m534s1602m534s534m534s1602m534s534m534s1602"
+ "m534s1602m534s1602m534s1602m534s1602m534s1602m534s1602m534s1602m534s1602"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s1602m534s534m534s1602m534s534m534s1602m534s534m534s1602m534s534"
+ "m534s25098"
+ "m8544s4272"
+ "m534s1602m534s534m534s1602m534s534m534s1602m534s534m534s1602m534s534"
+ "m534s534m534s534m534s534m534s534m534s534m534s534m534s534m534s534"
+ "m534s1602m534s1602m534s1602m534s1602m534s1602m534s1602m534s1602m534s1602"
+ "m534s534m534s1602m534s534m534s1602m534s534m534s1602m534s534m534s1602"
+ "m534s25098",
irsend.outputStr());
}
@@ -61,7 +61,7 @@ TEST(TestEncodePioneer, SimpleEncoding) {
EXPECT_EQ(0xA55A6A95F50A04FB, irsend.encodePioneer(0xA556, 0xAF20));
// "Source" from
- // https://github.com/markszabo/IRremoteESP8266/pull/547#issuecomment-429616582
+ // https://github.com/crankyoldgit/IRremoteESP8266/pull/547#issuecomment-429616582
EXPECT_EQ(0x659A05FAF50AC53A, irsend.encodePioneer(0xA6A0, 0xAFA3));
}
@@ -92,7 +92,7 @@ TEST(TestDecodePioneer, RealExampleLongDecodeSourceButton) {
irsend.reset();
// "Source" button.
- // https://github.com/markszabo/IRremoteESP8266/pull/547#issuecomment-429616582
+ // https://github.com/crankyoldgit/IRremoteESP8266/pull/547#issuecomment-429616582
uint16_t rawData[135] = {
8552, 4184, 596, 472, 592, 1524, 594, 1524, 594, 472, 592, 472,
598, 1520, 596, 472, 594, 1524, 592, 1524, 592, 472, 592, 472,
@@ -119,7 +119,7 @@ TEST(TestDecodePioneer, RealExampleLongDecodeSourceButton) {
// Synthetic Pioneer message.
// For:
-// https://github.com/markszabo/IRremoteESP8266/pull/547#issuecomment-430800734
+// https://github.com/crankyoldgit/IRremoteESP8266/pull/547#issuecomment-430800734
TEST(TestDecodePioneer, SyntheticPioneerMessage) {
IRsendTest irsend(0);
IRrecv irrecv(0);
@@ -138,18 +138,18 @@ TEST(TestDecodePioneer, SyntheticPioneerMessage) {
irsend.reset();
irsend.sendPioneer(0x659A857AF50A3DC2, 64, 0);
EXPECT_EQ(
- "f38000d33"
- "m8960s4480"
- "m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680"
- "m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560"
- "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680"
- "m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560"
- "m560s40320"
- "m8960s4480"
- "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680"
- "m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680m560s560"
- "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s1680"
- "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560"
- "m560s40320",
+ "f40000d33"
+ "m8544s4272"
+ "m534s534m534s1602m534s1602m534s534m534s534m534s1602m534s534m534s1602"
+ "m534s1602m534s534m534s534m534s1602m534s1602m534s534m534s1602m534s534"
+ "m534s1602m534s534m534s534m534s534m534s534m534s1602m534s534m534s1602"
+ "m534s534m534s1602m534s1602m534s1602m534s1602m534s534m534s1602m534s534"
+ "m534s25098"
+ "m8544s4272"
+ "m534s1602m534s1602m534s1602m534s1602m534s534m534s1602m534s534m534s1602"
+ "m534s534m534s534m534s534m534s534m534s1602m534s534m534s1602m534s534"
+ "m534s534m534s534m534s1602m534s1602m534s1602m534s1602m534s534m534s1602"
+ "m534s1602m534s1602m534s534m534s534m534s534m534s534m534s1602m534s534"
+ "m534s25098",
irsend.outputStr());
}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Pronto_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Pronto_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Pronto_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Pronto_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_RC5_RC6_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_RC5_RC6_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_RC5_RC6_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_RC5_RC6_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_RCMM_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_RCMM_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_RCMM_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_RCMM_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Samsung_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Samsung_test.cpp
similarity index 75%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Samsung_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Samsung_test.cpp
index 8670ac4ab..b928350b6 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Samsung_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Samsung_test.cpp
@@ -1,5 +1,6 @@
// Copyright 2017, 2018, 2019 David Conran
+#include
#include "ir_Samsung.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
@@ -414,7 +415,7 @@ TEST(TestIRSamsungAcClass, SetAndGetSwing) {
EXPECT_TRUE(samsung.getSwing());
// Real examples from:
- // https://github.com/markszabo/IRremoteESP8266/issues/505#issuecomment-424036602
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/505#issuecomment-424036602
// TODO(Hollako): Explain why state[9] lowest bit changes between on and off.
const uint8_t expected_off[kSamsungAcStateLength] = {
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
@@ -499,15 +500,87 @@ TEST(TestIRSamsungAcClass, SetAndGetFan) {
}
TEST(TestIRSamsungAcClass, SetAndGetQuiet) {
- IRSamsungAc samsung(0);
- samsung.setQuiet(false);
- EXPECT_FALSE(samsung.getQuiet());
- samsung.setFan(kSamsungAcFanHigh);
- samsung.setQuiet(true);
- EXPECT_TRUE(samsung.getQuiet());
- EXPECT_EQ(kSamsungAcFanAuto, samsung.getFan());
- samsung.setQuiet(false);
- EXPECT_FALSE(samsung.getQuiet());
+ IRSamsungAc ac(0);
+ ac.setQuiet(false);
+ EXPECT_FALSE(ac.getQuiet());
+ ac.setFan(kSamsungAcFanHigh);
+ ac.setQuiet(true);
+ EXPECT_TRUE(ac.getQuiet());
+ EXPECT_EQ(kSamsungAcFanAuto, ac.getFan());
+ ac.setQuiet(false);
+ EXPECT_FALSE(ac.getQuiet());
+
+ // Actual quiet on & off states from:
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/734#issuecomment-500071419
+ uint8_t on[14] = {
+ 0x02, 0x82, 0x0F, 0x00, 0x00, 0x20, 0xF0,
+ 0x01, 0xF2, 0xFE, 0x71, 0x00, 0x11, 0xF0};
+ ac.setRaw(on, 14);
+ EXPECT_TRUE(ac.getQuiet());
+ EXPECT_EQ(kSamsungAcFanAuto, ac.getFan());
+ uint8_t off[14] = {
+ 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
+ 0x01, 0xF2, 0xFE, 0x71, 0x00, 0x11, 0xF0};
+ ac.setRaw(off, 14);
+ EXPECT_FALSE(ac.getQuiet());
+}
+
+
+TEST(TestIRSamsungAcClass, SetAndGetPowerful) {
+ IRSamsungAc ac(0);
+ ac.setFan(kSamsungAcFanMed);
+ ac.setPowerful(false);
+ EXPECT_FALSE(ac.getPowerful());
+ EXPECT_EQ(kSamsungAcFanMed, ac.getFan());
+ ac.setPowerful(true);
+ EXPECT_TRUE(ac.getPowerful());
+ EXPECT_EQ(kSamsungAcFanTurbo, ac.getFan());
+ ac.setPowerful(false);
+ EXPECT_FALSE(ac.getPowerful());
+ EXPECT_EQ(kSamsungAcFanAuto, ac.getFan());
+
+ // Actual powerful on & off states from:
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/734#issuecomment-500120270
+ uint8_t on[kSamsungAcStateLength] = {
+ 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
+ 0x01, 0xA2, 0xFE, 0x77, 0x00, 0x1F, 0xF0};
+ ac.setRaw(on, kSamsungAcStateLength);
+ EXPECT_TRUE(ac.getPowerful());
+ EXPECT_EQ(kSamsungAcFanTurbo, ac.getFan());
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 7 (Turbo), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: On", ac.toString());
+
+ uint8_t off[kSamsungAcStateLength] = {
+ 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
+ 0x01, 0xF2, 0xFE, 0x71, 0x00, 0x11, 0xF0};
+ ac.setRaw(off, kSamsungAcStateLength);
+ EXPECT_FALSE(ac.getPowerful());
+ EXPECT_NE(kSamsungAcFanTurbo, ac.getFan());
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", ac.toString());
+}
+
+TEST(TestIRSamsungAcClass, QuietAndPowerfulAreMutuallyExclusive) {
+ IRSamsungAc ac(0);
+ ac.setQuiet(false);
+ ac.setPowerful(false);
+ EXPECT_FALSE(ac.getQuiet());
+ EXPECT_FALSE(ac.getPowerful());
+ EXPECT_NE(kSamsungAcFanTurbo, ac.getFan());
+ ac.setQuiet(true);
+ EXPECT_TRUE(ac.getQuiet());
+ EXPECT_FALSE(ac.getPowerful());
+ EXPECT_EQ(kSamsungAcFanAuto, ac.getFan());
+ ac.setPowerful(true);
+ EXPECT_FALSE(ac.getQuiet());
+ EXPECT_TRUE(ac.getPowerful());
+ EXPECT_EQ(kSamsungAcFanTurbo, ac.getFan());
+ ac.setQuiet(true);
+ EXPECT_TRUE(ac.getQuiet());
+ EXPECT_FALSE(ac.getPowerful());
+ EXPECT_NE(kSamsungAcFanTurbo, ac.getFan());
}
TEST(TestIRSamsungAcClass, ChecksumCalculation) {
@@ -529,7 +602,7 @@ TEST(TestIRSamsungAcClass, ChecksumCalculation) {
EXPECT_TRUE(IRSamsungAc::validChecksum(examplestate));
EXPECT_EQ(0, IRSamsungAc::calcChecksum(examplestate));
- examplestate[8] = 0x12; // Set an incoorect checksum.
+ examplestate[8] = 0x12; // Set an incorrect checksum.
EXPECT_FALSE(IRSamsungAc::validChecksum(examplestate));
EXPECT_EQ(0, IRSamsungAc::calcChecksum(examplestate));
samsung.setRaw(examplestate);
@@ -550,8 +623,8 @@ TEST(TestIRSamsungAcClass, ChecksumCalculation) {
TEST(TestIRSamsungAcClass, HumanReadable) {
IRSamsungAc samsung(0);
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (LOW), Swing: On, "
- "Beep: Off, Clean: Off, Quiet: Off",
+ "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (Low), Swing: On, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off",
samsung.toString());
samsung.setTemp(kSamsungAcMaxTemp);
samsung.setMode(kSamsungAcHeat);
@@ -561,13 +634,19 @@ TEST(TestIRSamsungAcClass, HumanReadable) {
samsung.setBeep(true);
samsung.setClean(true);
EXPECT_EQ(
- "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 5 (HIGH), Swing: Off, "
- "Beep: On, Clean: On, Quiet: Off",
+ "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 5 (High), Swing: Off, "
+ "Beep: On, Clean: On, Quiet: Off, Powerful: Off",
samsung.toString());
samsung.setQuiet(true);
EXPECT_EQ(
- "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 0 (AUTO), Swing: Off, "
- "Beep: On, Clean: On, Quiet: On",
+ "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: On, Clean: On, Quiet: On, Powerful: Off",
+ samsung.toString());
+ samsung.setQuiet(false);
+ samsung.setPowerful(true);
+ EXPECT_EQ(
+ "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 7 (Turbo), Swing: Off, "
+ "Beep: On, Clean: On, Quiet: Off, Powerful: On",
samsung.toString());
}
@@ -670,8 +749,8 @@ TEST(TestDecodeSamsungAC, DecodeRealExample) {
IRSamsungAc samsung(0);
samsung.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (LOW), Swing: On, "
- "Beep: Off, Clean: Off, Quiet: Off",
+ "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (Low), Swing: On, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off",
samsung.toString());
}
@@ -719,13 +798,13 @@ TEST(TestDecodeSamsungAC, DecodeRealExample2) {
IRSamsungAc samsung(0);
samsung.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (AUTO), Swing: Off, "
- "Beep: Off, Clean: Off, Quiet: Off",
+ "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off",
samsung.toString());
}
// Decode a real Samsung A/C example from:
-// https://github.com/markszabo/IRremoteESP8266/issues/505#issuecomment-424036602
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/505#issuecomment-424036602
TEST(TestDecodeSamsungAC, DecodePowerOnSample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
@@ -778,13 +857,13 @@ TEST(TestDecodeSamsungAC, DecodePowerOnSample) {
IRSamsungAc samsung(0);
samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength);
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (AUTO), Swing: Off, "
- "Beep: Off, Clean: Off, Quiet: Off",
+ "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off",
samsung.toString());
}
// Decode a real Samsung A/C example from:
-// https://github.com/markszabo/IRremoteESP8266/issues/505#issuecomment-424036602
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/505#issuecomment-424036602
TEST(TestDecodeSamsungAC, DecodePowerOffSample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
@@ -838,8 +917,8 @@ TEST(TestDecodeSamsungAC, DecodePowerOffSample) {
IRSamsungAc samsung(0);
samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength);
EXPECT_EQ(
- "Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 0 (AUTO), Swing: Off, "
- "Beep: Off, Clean: Off, Quiet: Off",
+ "Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off",
samsung.toString());
}
@@ -885,8 +964,8 @@ TEST(TestDecodeSamsungAC, DecodeHeatSample) {
IRSamsungAc samsung(0);
samsung.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 4 (HEAT), Temp: 17C, Fan: 0 (AUTO), Swing: On, "
- "Beep: Off, Clean: Off, Quiet: Off",
+ "Power: On, Mode: 4 (HEAT), Temp: 17C, Fan: 0 (Auto), Swing: On, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off",
samsung.toString());
}
@@ -932,8 +1011,8 @@ TEST(TestDecodeSamsungAC, DecodeCoolSample) {
IRSamsungAc samsung(0);
samsung.setRaw(irsend.capture.state);
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 0 (AUTO), Swing: Off, "
- "Beep: Off, Clean: Off, Quiet: Off",
+ "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off",
samsung.toString());
}
@@ -990,8 +1069,8 @@ TEST(TestDecodeSamsungAC, Issue604DecodeExtended) {
IRSamsungAc samsung(0);
samsung.setRaw(irsend.capture.state, irsend.capture.bits / 8);
EXPECT_EQ(
- "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 0 (AUTO), Swing: Off, "
- "Beep: Off, Clean: Off, Quiet: Off",
+ "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off",
samsung.toString());
}
@@ -1128,3 +1207,239 @@ TEST(TestDecodeSamsung36, SyntheticExample) {
EXPECT_EQ(0xE00FF, irsend.capture.command);
EXPECT_EQ(0x400, irsend.capture.address);
}
+
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/604
+TEST(TestIRSamsungAcClass, Issue604SendPowerHack) {
+ IRSamsungAc ac(0);
+ ac.begin();
+
+ std::string freqduty = "f38000d50";
+
+ std::string poweron =
+ "m690s17844"
+ "m3086s8864"
+ "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s1432m586s436m586s436m586s1432m586s436m586s436m586s1432"
+ "m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
+ "m586s2886"
+ "m3086s8864"
+ "m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432"
+ "m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s2886"
+ "m3086s8864"
+ "m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432"
+ "m586s436m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432"
+ "m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s1432"
+ "m586s1432m586s436m586s436m586s436m586s1432m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
+ "m586s100000";
+ std::string settings =
+ "m690s17844"
+ "m3086s8864"
+ "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s1432m586s436m586s436m586s1432m586s436m586s436m586s1432"
+ "m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
+ "m586s2886"
+ "m3086s8864"
+ "m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
+ "m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432"
+ "m586s436m586s1432m586s1432m586s1432m586s436m586s1432m586s436m586s1432"
+ "m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
+ "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
+ "m586s1432m586s436m586s436m586s1432m586s1432m586s436m586s436m586s436"
+ "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
+ "m586s100000";
+ std::string text = "Power: On, Mode: 1 (COOL), Temp: 23C, Fan: 4 (Medium), "
+ "Swing: On, Beep: Off, Clean: Off, Quiet: Off, "
+ "Powerful: Off";
+ // Don't do a setPower()/on()/off() as that will trigger the special message.
+ // So it should only be the normal "settings" message.
+ ac.setTemp(23);
+ ac.setMode(kSamsungAcCool);
+ ac.setFan(kSamsungAcFanMed);
+ ac.send();
+ EXPECT_EQ(text, ac.toString());
+ EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
+ ac._irsend.reset();
+ // Now trigger a special power message by using a power method.
+ ac.on();
+ ac.send(); // This should result in two messages. 1 x extended + 1 x normal.
+ EXPECT_EQ(text, ac.toString());
+ EXPECT_EQ(freqduty + poweron + settings, ac._irsend.outputStr());
+ ac._irsend.reset();
+ // Subsequent sending should be just the "settings" message.
+ ac.send();
+ EXPECT_EQ(text, ac.toString());
+ EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
+ ac._irsend.reset();
+ // Now trigger a special power message by using a power method (again).
+ ac.setPower(true);
+ ac.send(); // This should result in two messages. 1 x extended + 1 x normal.
+ EXPECT_EQ(text, ac.toString());
+ EXPECT_EQ(freqduty + poweron + settings, ac._irsend.outputStr());
+}
+
+TEST(TestIRSamsungAcClass, toCommon) {
+ IRSamsungAc ac(0);
+ ac.setPower(true);
+ ac.setMode(kSamsungAcCool);
+ ac.setTemp(20);
+ ac.setFan(kSamsungAcFanAuto);
+ ac.setSwing(true);
+ ac.setBeep(true);
+ ac.setClean(true);
+ ac.setQuiet(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::SAMSUNG_AC, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kAuto, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().quiet);
+ ASSERT_TRUE(ac.toCommon().clean);
+ ASSERT_TRUE(ac.toCommon().beep);
+ // Unsupported.
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestDecodeSamsungAC, Issue734QuietSetting) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ irsend.reset();
+ // QUIET MODE ON data from:
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/734#issuecomment-499791618
+ uint16_t quietOn[233] = {
+ 624, 17360, 3076, 8902, 520, 476, 520, 1472, 520, 476, 520, 474, 520, 476,
+ 520, 476, 520, 474, 522, 476, 520, 478, 518, 1476, 516, 500, 494, 502,
+ 548, 448, 546, 450, 544, 452, 522, 1468, 520, 1474, 520, 1472, 520, 1472,
+ 520, 1472, 520, 476, 520, 476, 518, 478, 516, 480, 516, 500, 496, 500,
+ 494, 502, 550, 446, 546, 450, 544, 452, 524, 472, 522, 474, 518, 476, 520,
+ 476, 520, 474, 522, 474, 520, 474, 520, 476, 520, 474, 520, 476, 518, 478,
+ 518, 480, 516, 480, 516, 502, 494, 502, 548, 1444, 524, 472, 522, 472,
+ 520, 474, 518, 478, 518, 476, 520, 476, 520, 1472, 520, 1470, 520, 1472,
+ 520, 1474, 516, 2980, 2998, 8980, 498, 1498, 548, 448, 526, 470, 544, 452,
+ 524, 472, 520, 474, 520, 476, 520, 476, 520, 476, 520, 1472, 520, 474,
+ 520, 476, 520, 1474, 518, 1476, 516, 1496, 496, 1498, 548, 446, 546, 1446,
+ 524, 1468, 518, 1474, 520, 1472, 520, 1472, 520, 1472, 520, 1474, 518,
+ 1476, 518, 480, 516, 500, 496, 528, 520, 1446, 544, 1446, 524, 1470, 518,
+ 476, 520, 476, 520, 474, 520, 476, 520, 474, 520, 476, 520, 474, 520, 476,
+ 520, 476, 518, 1476, 516, 482, 514, 502, 548, 448, 548, 1442, 544, 452,
+ 522, 474, 518, 476, 518, 476, 520, 476, 520, 474, 520, 476, 520, 1472,
+ 520, 1470, 522, 1474, 518, 1476, 536};
+
+ uint8_t expectedState[kSamsungAcStateLength] = {
+ 0x02, 0x82, 0x0F, 0x00, 0x00, 0x20, 0xF0,
+ 0x01, 0xF2, 0xFE, 0x71, 0x00, 0x11, 0xF0};
+
+ irsend.sendRaw(quietOn, 233, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type);
+ EXPECT_EQ(kSamsungAcBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+
+ IRSamsungAc ac(0);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: On, Powerful: Off",
+ ac.toString());
+
+ // Make sure the ac class state is in something wildly different first.
+ ac.stateReset();
+ ac.setPower(false);
+ ac.setMode(kSamsungAcAuto);
+ ac.setTemp(30);
+ ac.setSwing(true);
+ ac.setBeep(true);
+ ac.setClean(true);
+ ac.setQuiet(false);
+ // See if we can build the state from scratch.
+ ac.setPower(true);
+ ac.setMode(kSamsungAcCool);
+ ac.setTemp(16);
+ ac.setSwing(false);
+ ac.setBeep(false);
+ ac.setClean(false);
+ ac.setQuiet(true);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: On, Powerful: Off",
+ ac.toString());
+ // Check it matches the known good/expected state.
+ EXPECT_STATE_EQ(expectedState, ac.getRaw(), kSamsungAcBits);
+}
+
+TEST(TestDecodeSamsungAC, Issue734PowerfulOff) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ irsend.reset();
+ // 1st Powerful off data from:
+ // https://github.com/crankyoldgit/IRremoteESP8266/issues/734#issuecomment-500114580
+ uint16_t powerfulOff[233] = {
+ 652, 17336, 3078, 8910, 562, 456, 546, 1448, 550, 446, 552, 444, 552, 444,
+ 550, 446, 550, 446, 552, 446, 550, 446, 552, 1440, 550, 446, 550, 446,
+ 550, 1470, 478, 518, 502, 492, 536, 1458, 542, 1450, 552, 1440, 552, 1442,
+ 552, 1442, 550, 446, 550, 446, 550, 446, 552, 444, 550, 446, 550, 446,
+ 550, 472, 524, 472, 480, 516, 510, 488, 538, 458, 542, 452, 548, 448, 550,
+ 446, 550, 446, 550, 444, 552, 444, 552, 444, 552, 444, 552, 444, 552, 444,
+ 552, 444, 550, 446, 550, 446, 550, 472, 524, 472, 482, 514, 510, 486, 536,
+ 460, 542, 454, 546, 450, 550, 446, 552, 1442, 552, 1442, 550, 1442, 552,
+ 1440, 508, 2994, 3030, 8932, 552, 1638, 450, // <= (was 356)
+ // Above hack due to poor data.
+ 470, 526, 470, 506, 492, 510,
+ 486, 542, 454, 544, 450, 550, 446, 554, 444, 550, 1442, 550, 444, 550,
+ 446, 550, 1442, 552, 1440, 550, 1442, 550, 1470, 524, 470, 480, 1512, 512,
+ 1480, 546, 1448, 550, 1442, 552, 1442, 552, 1442, 550, 1440, 552, 1440,
+ 552, 446, 550, 444, 552, 444, 550, 1468, 484, 1510, 512, 1482, 544, 452,
+ 550, 446, 552, 442, 554, 444, 552, 444, 554, 442, 554, 442, 552, 444, 554,
+ 442, 554, 1440, 552, 444, 554, 442, 554, 468, 528, 1466, 508, 488, 512,
+ 484, 544, 450, 550, 446, 554, 442, 556, 442, 554, 442, 554, 1438, 554,
+ 1438, 554, 1438, 554, 1438, 562}; // UNKNOWN 7B551B62};
+
+ uint8_t expectedState[kSamsungAcStateLength] = {
+ 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
+ 0x01, 0xF2, 0xFE, 0x71, 0x00, 0x11, 0xF0};
+
+ irsend.sendRaw(powerfulOff, 233, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decodeSamsungAC(&irsend.capture));
+ ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type);
+ EXPECT_EQ(kSamsungAcBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+
+ IRSamsungAc ac(0);
+ ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), Swing: Off, "
+ "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off",
+ ac.toString());
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Sanyo_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Sanyo_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Sanyo_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Sanyo_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Sharp_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Sharp_test.cpp
similarity index 52%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Sharp_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Sharp_test.cpp
index c9d3e851b..2949580ed 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Sharp_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Sharp_test.cpp
@@ -1,5 +1,8 @@
// Copyright 2017 David Conran
+#include "ir_Sharp.h"
+#include "IRrecv.h"
+#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
@@ -360,3 +363,345 @@ TEST(TestDecodeSharp, FailToDecodeNonSharpExample) {
ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture));
ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, false));
}
+
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/638#issue-421064165
+TEST(TestDecodeSharpAc, RealExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ // cool-auto-27.txt
+ uint16_t rawData[211] = {
+ 3804, 1892, 466, 486, 466, 1388, 466, 486, 466, 1386, 468, 486, 468, 1388,
+ 466, 486, 466, 1386, 468, 488, 466, 1388, 466, 488, 466, 1386, 468, 1388,
+ 466, 486, 466, 1388, 466, 486, 468, 1384, 468, 1388, 468, 1388, 466, 1388,
+ 466, 486, 468, 484, 468, 1386, 468, 1386, 468, 486, 466, 486, 468, 486,
+ 466, 488, 466, 1388, 466, 486, 466, 486, 468, 486, 466, 488, 466, 488,
+ 466, 1386, 468, 1388, 466, 486, 468, 486, 466, 1388, 464, 1388, 466, 1386,
+ 468, 486, 466, 486, 468, 486, 466, 1388, 468, 1384, 470, 486, 466, 486,
+ 468, 486, 468, 1386, 468, 486, 468, 486, 468, 486, 468, 1388, 466, 486,
+ 466, 486, 466, 486, 466, 488, 466, 486, 468, 486, 468, 486, 468, 486, 466,
+ 486, 466, 486, 466, 488, 466, 486, 466, 486, 466, 1388, 466, 486, 468,
+ 486, 466, 486, 468, 486, 468, 486, 466, 486, 466, 488, 466, 486, 466, 486,
+ 466, 488, 466, 486, 468, 1386, 468, 486, 466, 486, 466, 1390, 464, 488,
+ 466, 486, 468, 486, 468, 486, 466, 486, 466, 486, 466, 486, 468, 486, 468,
+ 486, 466, 486, 466, 1386, 468, 1390, 466, 1388, 466, 1388, 468, 486, 466,
+ 486, 468, 486, 466, 486, 466, 486, 466, 1390, 464, 486, 414};
+ // UNKNOWN F2B82C78
+ uint8_t expectedState[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCC, 0x31, 0x22, 0x00, 0x08, 0x80, 0x04, 0xE0,
+ 0x41};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendRaw(rawData, 211, 38000);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(SHARP_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kSharpAcBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+
+ IRSharpAc ac(0);
+ ac.begin();
+ ac.setRaw(irsend.capture.state);
+ EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 27C, Fan: 2 (Auto)",
+ ac.toString());
+}
+
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/638#issue-421064165
+TEST(TestDecodeSharpAc, SyntheticExample) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ // cool-auto-27.txt
+ uint8_t expectedState[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCC, 0x31, 0x22, 0x00, 0x08, 0x80, 0x04, 0xE0,
+ 0x41};
+
+ irsend.begin();
+ irsend.reset();
+ irsend.sendSharpAc(expectedState);
+ irsend.makeDecodeResult();
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(SHARP_AC, irsend.capture.decode_type);
+ ASSERT_EQ(kSharpAcBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+}
+
+TEST(TestIRUtils, Sharp) {
+ ASSERT_EQ("SHARP", typeToString(decode_type_t::SHARP));
+ ASSERT_EQ(decode_type_t::SHARP, strToDecodeType("SHARP"));
+ ASSERT_FALSE(hasACState(decode_type_t::SHARP));
+}
+
+TEST(TestIRUtils, SharpAc) {
+ ASSERT_EQ("SHARP_AC", typeToString(decode_type_t::SHARP_AC));
+ ASSERT_EQ(decode_type_t::SHARP_AC, strToDecodeType("SHARP_AC"));
+ ASSERT_TRUE(hasACState(decode_type_t::SHARP_AC));
+}
+
+// Tests for IRSharpAc class.
+
+TEST(TestSharpAcClass, Power) {
+ IRSharpAc ac(0);
+ ac.begin();
+
+ ac.on();
+ EXPECT_TRUE(ac.getPower());
+
+ ac.off();
+ EXPECT_FALSE(ac.getPower());
+
+ ac.setPower(true);
+ EXPECT_TRUE(ac.getPower());
+
+ ac.setPower(false);
+ EXPECT_FALSE(ac.getPower());
+}
+
+TEST(TestSharpAcClass, Checksum) {
+ uint8_t state[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCC, 0x31, 0x22, 0x00, 0x08, 0x80, 0x04, 0xE0,
+ 0x41};
+ EXPECT_EQ(0x4, IRSharpAc::calcChecksum(state));
+ EXPECT_TRUE(IRSharpAc::validChecksum(state));
+ // Change the state so it is not valid.
+ state[3] = 0;
+ EXPECT_FALSE(IRSharpAc::validChecksum(state));
+}
+
+TEST(TestSharpAcClass, Temperature) {
+ IRSharpAc ac(0);
+ ac.begin();
+ ac.setMode(kSharpAcCool); // Cool mode doesn't have temp restrictions.
+
+ ac.setTemp(0);
+ EXPECT_EQ(kSharpAcMinTemp, ac.getTemp());
+
+ ac.setTemp(255);
+ EXPECT_EQ(kSharpAcMaxTemp, ac.getTemp());
+
+ ac.setTemp(kSharpAcMinTemp);
+ EXPECT_EQ(kSharpAcMinTemp, ac.getTemp());
+
+ ac.setTemp(kSharpAcMaxTemp);
+ EXPECT_EQ(kSharpAcMaxTemp, ac.getTemp());
+
+ ac.setTemp(kSharpAcMinTemp - 1);
+ EXPECT_EQ(kSharpAcMinTemp, ac.getTemp());
+
+ ac.setTemp(kSharpAcMaxTemp + 1);
+ EXPECT_EQ(kSharpAcMaxTemp, ac.getTemp());
+
+ ac.setTemp(kSharpAcMinTemp + 1);
+ EXPECT_EQ(kSharpAcMinTemp + 1, ac.getTemp());
+
+ ac.setTemp(21);
+ EXPECT_EQ(21, ac.getTemp());
+
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+
+ ac.setTemp(29);
+ EXPECT_EQ(29, ac.getTemp());
+}
+
+TEST(TestSharpAcClass, OperatingMode) {
+ IRSharpAc ac(0);
+ ac.begin();
+
+ ac.setTemp(25);
+ ac.setMode(kSharpAcAuto);
+ EXPECT_EQ(kSharpAcAuto, ac.getMode());
+
+ ac.setMode(kSharpAcCool);
+ EXPECT_EQ(kSharpAcCool, ac.getMode());
+
+ ac.setMode(kSharpAcHeat);
+ EXPECT_EQ(kSharpAcHeat, ac.getMode());
+
+ ac.setMode(kSharpAcDry);
+ EXPECT_EQ(kSharpAcDry, ac.getMode());
+ ASSERT_EQ(kSharpAcMinTemp, ac.getTemp()); // Dry mode restricts the temp.
+ ac.setTemp(25);
+ ASSERT_EQ(kSharpAcMinTemp, ac.getTemp());
+
+ ac.setMode(kSharpAcDry + 1);
+ EXPECT_EQ(kSharpAcAuto, ac.getMode());
+
+ ac.setMode(kSharpAcCool);
+ EXPECT_EQ(kSharpAcCool, ac.getMode());
+ // We are no longer restricted.
+ ac.setTemp(25);
+ ASSERT_EQ(25, ac.getTemp());
+
+ ac.setMode(255);
+ EXPECT_EQ(kSharpAcAuto, ac.getMode());
+}
+
+
+TEST(TestSharpAcClass, FanSpeed) {
+ IRSharpAc ac(0);
+ ac.begin();
+
+ // Unexpected value should default to Auto.
+ ac.setFan(0);
+ EXPECT_EQ(kSharpAcFanAuto, ac.getFan());
+
+ // Unexpected value should default to Auto.
+ ac.setFan(255);
+ EXPECT_EQ(kSharpAcFanAuto, ac.getFan());
+
+ ac.setFan(kSharpAcFanMax);
+ EXPECT_EQ(kSharpAcFanMax, ac.getFan());
+
+ // Beyond Max should default to Auto.
+ ac.setFan(kSharpAcFanMax + 1);
+ EXPECT_EQ(kSharpAcFanAuto, ac.getFan());
+
+ ac.setFan(kSharpAcFanMed);
+ EXPECT_EQ(kSharpAcFanMed, ac.getFan());
+
+ ac.setFan(kSharpAcFanMin);
+ EXPECT_EQ(kSharpAcFanMin, ac.getFan());
+
+ ac.setFan(kSharpAcFanAuto - 1);
+ EXPECT_EQ(kSharpAcFanAuto, ac.getFan());
+
+ ac.setFan(kSharpAcFanMax + 1);
+ EXPECT_EQ(kSharpAcFanAuto, ac.getFan());
+
+ ac.setFan(kSharpAcFanAuto);
+ EXPECT_EQ(kSharpAcFanAuto, ac.getFan());
+}
+
+TEST(TestSharpAcClass, ReconstructKnownState) {
+ IRSharpAc ac(0);
+ ac.begin();
+
+ uint8_t on_auto_auto[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x11, 0x20, 0x00, 0x08, 0x80, 0x00, 0xE0,
+ 0x01};
+ ac.on();
+ ac.setMode(kSharpAcAuto);
+ ac.setTemp(kSharpAcMinTemp);
+ ac.setFan(kSharpAcFanAuto);
+ EXPECT_STATE_EQ(on_auto_auto, ac.getRaw(), kSharpAcBits);
+ EXPECT_EQ("Power: On, Mode: 0 (AUTO), Temp: 15C, Fan: 2 (Auto)",
+ ac.toString());
+
+ uint8_t cool_auto_28[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x22, 0x00, 0x08, 0x80, 0x04, 0xE0,
+ 0x51};
+ ac.stateReset();
+ ac.on();
+ ac.setMode(kSharpAcCool);
+ ac.setTemp(28);
+ ac.setFan(kSharpAcFanAuto);
+ EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 2 (Auto)",
+ ac.toString());
+ EXPECT_STATE_EQ(cool_auto_28, ac.getRaw(), kSharpAcBits);
+}
+
+// https://github.com/crankyoldgit/IRremoteESP8266/issues/638#issue-421064165
+TEST(TestSharpAcClass, KnownStates) {
+ IRSharpAc ac(0);
+ ac.begin();
+
+ uint8_t off_auto_auto[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x21, 0x20, 0x00, 0x08, 0x80, 0x00, 0xE0,
+ 0x31};
+ ASSERT_TRUE(ac.validChecksum(off_auto_auto));
+ ac.setRaw(off_auto_auto);
+ EXPECT_EQ("Power: Off, Mode: 0 (AUTO), Temp: 15C, Fan: 2 (Auto)",
+ ac.toString());
+ uint8_t on_auto_auto[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x11, 0x20, 0x00, 0x08, 0x80, 0x00, 0xE0,
+ 0x01};
+ ASSERT_TRUE(ac.validChecksum(on_auto_auto));
+ ac.setRaw(on_auto_auto);
+ EXPECT_EQ("Power: On, Mode: 0 (AUTO), Temp: 15C, Fan: 2 (Auto)",
+ ac.toString());
+ uint8_t cool_auto_28[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x22, 0x00, 0x08, 0x80, 0x04, 0xE0,
+ 0x51};
+ ASSERT_TRUE(ac.validChecksum(cool_auto_28));
+ ac.setRaw(cool_auto_28);
+ EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 2 (Auto)",
+ ac.toString());
+ uint8_t cool_fan1_28[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x42, 0x00, 0x08, 0x80, 0x05, 0xE0,
+ 0x21};
+ ASSERT_TRUE(ac.validChecksum(cool_fan1_28));
+ ac.setRaw(cool_fan1_28);
+ EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 4 (Low)",
+ ac.toString());
+ uint8_t cool_fan2_28[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x32, 0x00, 0x08, 0x80, 0x05, 0xE0,
+ 0x51};
+ ASSERT_TRUE(ac.validChecksum(cool_fan2_28));
+ ac.setRaw(cool_fan2_28);
+ EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 3 (Medium)",
+ ac.toString());
+ uint8_t cool_fan3_28[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x52, 0x00, 0x08, 0x80, 0x05, 0xE0,
+ 0x31};
+ ASSERT_TRUE(ac.validChecksum(cool_fan3_28));
+ ac.setRaw(cool_fan3_28);
+ EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 5 (UNKNOWN)",
+ ac.toString());
+ uint8_t cool_fan4_28[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x72, 0x00, 0x08, 0x80, 0x05, 0xE0,
+ 0x11};
+ ASSERT_TRUE(ac.validChecksum(cool_fan4_28));
+ ac.setRaw(cool_fan4_28);
+ EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 7 (High)",
+ ac.toString());
+ /* Unsupported / Not yet reverse engineered.
+ uint8_t cool_fan4_28_ion_on[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x61, 0x72, 0x08, 0x08, 0x80, 0x00, 0xE4,
+ 0xD1};
+ ASSERT_TRUE(ac.validChecksum(cool_fan4_28_ion_on));
+ ac.setRaw(cool_fan4_28_ion_on);
+ EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 7 (MAX)",
+ ac.toString());
+ uint8_t cool_fan4_28_eco1[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x61, 0x72, 0x18, 0x08, 0x80, 0x00, 0xE8,
+ 0x01};
+ ASSERT_TRUE(ac.validChecksum(cool_fan4_28_eco1));
+ ac.setRaw(cool_fan4_28_eco1);
+ EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 7 (MAX)",
+ ac.toString()); */
+ uint8_t dry_auto[kSharpAcStateLength] = {
+ 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x31, 0x23, 0x00, 0x08, 0x80, 0x00, 0xE0,
+ 0x11};
+ ASSERT_TRUE(ac.validChecksum(dry_auto));
+ ac.setRaw(dry_auto);
+ EXPECT_EQ("Power: On, Mode: 3 (DRY), Temp: 15C, Fan: 2 (Auto)",
+ ac.toString());
+}
+
+TEST(TestSharpAcClass, toCommon) {
+ IRSharpAc ac(0);
+ ac.setPower(true);
+ ac.setMode(kSharpAcCool);
+ ac.setTemp(20);
+ ac.setFan(kSharpAcFanMax);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::SHARP_AC, ac.toCommon().protocol);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ // Unsupported.
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Sherwood_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Sherwood_test.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Sherwood_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Sherwood_test.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Sony_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Sony_test.cpp
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Sony_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Sony_test.cpp
index 35c3287b0..51bacbd6d 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Sony_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Sony_test.cpp
@@ -153,7 +153,7 @@ TEST(TestDecodeSony, NormalSonyDecodeWithStrict) {
irsend.reset();
irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1));
irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(kSony20Bits, irsend.capture.bits);
EXPECT_EQ(0x81080, irsend.capture.value);
@@ -164,7 +164,7 @@ TEST(TestDecodeSony, NormalSonyDecodeWithStrict) {
irsend.reset();
irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits);
irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(kSony15Bits, irsend.capture.bits);
EXPECT_EQ(0x5480, irsend.capture.value);
@@ -175,7 +175,7 @@ TEST(TestDecodeSony, NormalSonyDecodeWithStrict) {
irsend.reset();
irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits);
irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(kSony12Bits, irsend.capture.bits);
EXPECT_EQ(0xA90, irsend.capture.value);
@@ -248,7 +248,7 @@ TEST(TestDecodeSony, SonyDecodeWithIllegalSize) {
EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true));
EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true));
// Should work with a 'normal' match (not strict)
- ASSERT_TRUE(irrecv.decodeSony(&irsend.capture));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(8, irsend.capture.bits);
EXPECT_EQ(0xFF, irsend.capture.value);
@@ -264,7 +264,7 @@ TEST(TestDecodeSony, SonyDecodeWithIllegalSize) {
EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true));
EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true));
// Should work with a 'normal' match (not strict)
- ASSERT_TRUE(irrecv.decodeSony(&irsend.capture));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(13, irsend.capture.bits);
EXPECT_EQ(0x1FFF, irsend.capture.value);
@@ -280,7 +280,7 @@ TEST(TestDecodeSony, SonyDecodeWithIllegalSize) {
EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true));
EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true));
// Should work with a 'normal' match (not strict)
- ASSERT_TRUE(irrecv.decodeSony(&irsend.capture));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(17, irsend.capture.bits);
EXPECT_EQ(0x1FFFF, irsend.capture.value);
@@ -296,19 +296,18 @@ TEST(TestDecodeSony, SonyDecodeWithIllegalSize) {
EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true));
EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true));
// Should work with a 'normal' match (not strict)
- ASSERT_TRUE(irrecv.decodeSony(&irsend.capture));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(21, irsend.capture.bits);
EXPECT_EQ(0x1FFFFF, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
-
irsend.reset();
// Illegal 64-bit (max) Sony-like message.
irsend.sendSony(0xFFFFFFFFFFFFFFFF, 64, 0);
irsend.makeDecodeResult();
// Should work with a 'normal' match (not strict)
- ASSERT_TRUE(irrecv.decodeSony(&irsend.capture));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(64, irsend.capture.bits);
EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value);
@@ -316,7 +315,6 @@ TEST(TestDecodeSony, SonyDecodeWithIllegalSize) {
EXPECT_EQ(0x0, irsend.capture.command);
}
-// Decode unsupported Sony messages. i.e non-standard sizes.
TEST(TestDecodeSony, DecodeGlobalCacheExample) {
IRsendTest irsend(4);
IRrecv irrecv(4);
@@ -331,7 +329,7 @@ TEST(TestDecodeSony, DecodeGlobalCacheExample) {
irsend.makeDecodeResult();
// Without strict.
- ASSERT_TRUE(irrecv.decodeSony(&irsend.capture));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(12, irsend.capture.bits);
EXPECT_EQ(0x750, irsend.capture.value);
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Tcl_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Tcl_test.cpp
similarity index 78%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Tcl_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Tcl_test.cpp
index 249dcc637..8432cf9ac 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Tcl_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Tcl_test.cpp
@@ -246,7 +246,6 @@ TEST(TestTcl112AcClass, Power) {
ac.toString());
}
-
TEST(TestTcl112AcClass, Checksum) {
uint8_t temp16C[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
@@ -382,3 +381,82 @@ TEST(TestTcl112AcClass, FanSpeed) {
ac.setFan(kTcl112AcFanHigh + 1);
EXPECT_EQ(kTcl112AcFanAuto, ac.getFan());
}
+
+
+TEST(TestTcl112AcClass, toCommon) {
+ IRTcl112Ac ac(0);
+ ac.setPower(true);
+ ac.setMode(kTcl112AcCool);
+ ac.setTemp(20);
+ ac.setFan(kTcl112AcFanHigh);
+ ac.setSwingVertical(true);
+ ac.setSwingHorizontal(true);
+ ac.setTurbo(true);
+ ac.setHealth(true);
+ ac.setEcono(true);
+ ac.setLight(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::TCL112AC, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().econo);
+ ASSERT_TRUE(ac.toCommon().light);
+ ASSERT_TRUE(ac.toCommon().filter);
+ // Unsupported.
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestDecodeTcl112Ac, Issue744) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ irsend.reset();
+ uint16_t rawData[227] = {
+ 3164, 1532, 584, 1082, 472, 1068, 580, 244, 602, 264, 542, 328, 530, 1034,
+ 586, 262, 540, 326, 508, 1064, 582, 1082, 490, 328, 532, 1032, 586, 262,
+ 544, 352, 478, 1060, 584, 1082, 486, 328, 502, 1058, 588, 1084, 472, 344,
+ 530, 250, 600, 1086, 492, 322, 530, 258, 594, 1082, 494, 318, 510, 344,
+ 530, 248, 600, 262, 544, 326, 504, 296, 578, 252, 598, 260, 550, 318, 506,
+ 344, 530, 250, 600, 258, 546, 318, 508, 342, 532, 254, 596, 236, 606, 266,
+ 524, 1066, 580, 242, 602, 266, 542, 1054, 574, 246, 604, 262, 550, 1088,
+ 530, 1034, 588, 262, 542, 328, 504, 296, 582, 238, 606, 262, 546, 322,
+ 508, 342, 530, 250, 602, 260, 544, 1052, 572, 252, 600, 260, 546, 320,
+ 506, 344, 530, 254, 596, 264, 578, 268, 552, 316, 528, 256, 598, 260, 578,
+ 272, 520, 372, 476, 294, 582, 240, 604, 266, 542, 328, 502, 294, 582, 238,
+ 604, 268, 540, 322, 506, 346, 530, 244, 604, 260, 542, 354, 478, 298, 580,
+ 240, 604, 262, 542, 326, 506, 342, 530, 250, 600, 260, 548, 318, 506, 344,
+ 530, 250, 600, 260, 546, 320, 528, 322, 530, 254, 598, 262, 548, 316, 468,
+ 380, 532, 250, 600, 260, 546, 1092, 500, 300, 578, 246, 602, 1082, 474,
+ 346, 530, 248, 602, 260, 542, 1054, 570, 1090, 524}; // UNKNOWN 3338FACE
+
+ uint8_t expectedState[kTcl112AcStateLength] = {
+ 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC4};
+
+ irsend.sendRaw(rawData, 227, 38000);
+ irsend.makeDecodeResult();
+
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
+ ASSERT_EQ(TCL112AC, irsend.capture.decode_type);
+ EXPECT_EQ(kTcl112AcBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+
+ IRTcl112Ac ac(0);
+ ac.setRaw(irsend.capture.state);
+ EXPECT_EQ(
+ "Power: On, Mode: 3 (COOL), Temp: 23C, Fan: 0 (Auto), Econo: Off, "
+ "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off",
+ ac.toString());
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Teco_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Teco_test.cpp
similarity index 77%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Teco_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Teco_test.cpp
index 6b03a671d..4ed7fbd9f 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Teco_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Teco_test.cpp
@@ -198,26 +198,72 @@ TEST(TestTecoACClass, Sleep) {
EXPECT_TRUE(ac.getSleep());
}
+TEST(TestTecoACClass, Light) {
+ IRTecoAc ac(0);
+ ac.begin();
+
+ ac.setLight(true);
+ EXPECT_TRUE(ac.getLight());
+ ac.setLight(false);
+ EXPECT_EQ(false, ac.getLight());
+ ac.setLight(true);
+ EXPECT_TRUE(ac.getLight());
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/870#issue-484797174
+ ac.setRaw(0x250200A09);
+ EXPECT_TRUE(ac.getLight());
+}
+
+TEST(TestTecoACClass, Humid) {
+ IRTecoAc ac(0);
+ ac.begin();
+
+ ac.setHumid(true);
+ EXPECT_TRUE(ac.getHumid());
+ ac.setHumid(false);
+ EXPECT_EQ(false, ac.getHumid());
+ ac.setHumid(true);
+ EXPECT_TRUE(ac.getHumid());
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/870#issuecomment-524536810
+ ac.setRaw(0x250100A09);
+ EXPECT_TRUE(ac.getHumid());
+}
+
+TEST(TestTecoACClass, Save) {
+ IRTecoAc ac(0);
+ ac.begin();
+
+ ac.setSave(true);
+ EXPECT_TRUE(ac.getSave());
+ ac.setSave(false);
+ EXPECT_EQ(false, ac.getSave());
+ ac.setSave(true);
+ EXPECT_TRUE(ac.getSave());
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/870#issuecomment-524536810
+ ac.setRaw(0x250800A09);
+ EXPECT_TRUE(ac.getSave());
+}
+
TEST(TestTecoACClass, MessageConstuction) {
IRTecoAc ac(0);
EXPECT_EQ(
"Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, "
- "Swing: Off",
+ "Swing: Off, Light: Off, Humid: Off, Save: Off",
ac.toString());
ac.setPower(true);
ac.setMode(kTecoCool);
ac.setTemp(21);
ac.setFan(kTecoFanHigh);
ac.setSwing(false);
+ ac.setLight(false);
EXPECT_EQ(
"Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, "
- "Swing: Off",
+ "Swing: Off, Light: Off, Humid: Off, Save: Off",
ac.toString());
ac.setSwing(true);
EXPECT_EQ(
"Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, "
- "Swing: On",
+ "Swing: On, Light: Off, Humid: Off, Save: Off",
ac.toString());
ac.setSwing(false);
ac.setFan(kTecoFanLow);
@@ -225,17 +271,20 @@ TEST(TestTecoACClass, MessageConstuction) {
ac.setMode(kTecoHeat);
EXPECT_EQ(
"Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: On, "
- "Swing: Off",
+ "Swing: Off, Light: Off, Humid: Off, Save: Off",
ac.toString());
ac.setSleep(false);
EXPECT_EQ(
"Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: Off, "
- "Swing: Off",
+ "Swing: Off, Light: Off, Humid: Off, Save: Off",
ac.toString());
ac.setTemp(25);
+ ac.setLight(true);
+ ac.setSave(true);
+ ac.setHumid(true);
EXPECT_EQ(
"Power: On, Mode: 4 (HEAT), Temp: 25C, Fan: 1 (Low), Sleep: Off, "
- "Swing: Off",
+ "Swing: Off, Light: On, Humid: On, Save: On",
ac.toString());
}
@@ -253,7 +302,7 @@ TEST(TestTecoACClass, ReconstructKnownMessage) {
EXPECT_EQ(expected, ac.getRaw());
EXPECT_EQ(
"Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, "
- "Swing: On",
+ "Swing: On, Light: Off, Humid: Off, Save: Off",
ac.toString());
}
@@ -295,7 +344,7 @@ TEST(TestDecodeTeco, NormalDecodeWithStrict) {
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
"Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, "
- "Swing: Off",
+ "Swing: Off, Light: Off, Humid: Off, Save: Off",
ac.toString());
}
@@ -328,7 +377,7 @@ TEST(TestDecodeTeco, RealNormalExample) {
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
"Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, "
- "Swing: On",
+ "Swing: On, Light: Off, Humid: Off, Save: Off",
ac.toString());
uint16_t rawData2[73] = {
@@ -352,7 +401,38 @@ TEST(TestDecodeTeco, RealNormalExample) {
ac.begin();
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
- "Power: On, Mode: 2 (DRY), Temp: 21C, Fan: 2 (Med), Sleep: Off, "
- "Swing: On",
+ "Power: On, Mode: 2 (DRY), Temp: 21C, Fan: 2 (Medium), Sleep: Off, "
+ "Swing: On, Light: Off, Humid: Off, Save: Off",
ac.toString());
}
+
+
+TEST(TestTecoACClass, toCommon) {
+ IRTecoAc ac(0);
+ ac.setPower(true);
+ ac.setMode(kTecoCool);
+ ac.setTemp(20);
+ ac.setFan(kTecoFanHigh);
+ ac.setSwing(true);
+ ac.setSleep(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::TECO, ac.toCommon().protocol);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_EQ(0, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Toshiba_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Toshiba_test.cpp
similarity index 96%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Toshiba_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Toshiba_test.cpp
index d74866f92..15f8e6b90 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Toshiba_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Toshiba_test.cpp
@@ -352,16 +352,17 @@ TEST(TestToshibaACClass, HumanReadableOutput) {
0x00, 0xC1, 0x00, 0xC0};
toshiba.setRaw(initial_state);
- EXPECT_EQ("Power: On, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (AUTO)",
+ EXPECT_EQ("Power: On, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (Auto)",
toshiba.toString());
toshiba.setRaw(modified_state);
- EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 17C, Fan: 5 (MAX)",
+ EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 17C, Fan: 5 (High)",
toshiba.toString());
toshiba.off();
toshiba.setTemp(25);
toshiba.setFan(3);
toshiba.setMode(kToshibaAcDry);
- EXPECT_EQ("Power: Off, Mode: 2 (DRY), Temp: 25C, Fan: 3", toshiba.toString());
+ EXPECT_EQ("Power: Off, Mode: 2 (DRY), Temp: 25C, Fan: 3 (Medium)",
+ toshiba.toString());
}
TEST(TestToshibaACClass, MessageConstuction) {
@@ -669,3 +670,31 @@ TEST(TestDecodeToshibaAC, RealExamples) {
// sending the power off message.
EXPECT_EQ(kToshibaAcHeat, toshiba.getMode());
}
+
+TEST(TestToshibaACClass, toCommon) {
+ IRToshibaAC ac(0);
+ ac.setPower(true);
+ ac.setMode(kToshibaAcCool);
+ ac.setTemp(20);
+ ac.setFan(kToshibaAcFanMax);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::TOSHIBA_AC, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ // Unsupported.
+ ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Trotec_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Trotec_test.cpp
new file mode 100644
index 000000000..f9272f384
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Trotec_test.cpp
@@ -0,0 +1,179 @@
+// Copyright 2019 David Conran
+#include "ir_Trotec.h"
+#include "IRrecv.h"
+#include "IRrecv_test.h"
+#include "IRsend.h"
+#include "IRsend_test.h"
+#include "gtest/gtest.h"
+
+
+TEST(TestTrotecESPClass, toCommon) {
+ IRTrotecESP ac(0);
+ ac.setPower(true);
+ ac.setMode(kTrotecCool);
+ ac.setTemp(20);
+ ac.setSpeed(kTrotecFanHigh);
+ ac.setSleep(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::TROTEC, ac.toCommon().protocol);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(0, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv);
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().turbo);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
+
+TEST(TestTrotecESPClass, MessageConstructon) {
+ IRTrotecESP ac(0);
+ ac.setPower(true);
+ ac.setTemp(20);
+ ac.setMode(kTrotecCool);
+ ac.setSpeed(kTrotecFanMed);
+ ac.setSleep(true);
+
+ uint8_t expected[kTrotecStateLength] = {
+ 0x12, 0x34, 0x29, 0x82, 0x00, 0x00, 0x00, 0x00, 0xAB};
+ EXPECT_STATE_EQ(expected, ac.getRaw(), kTrotecBits);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 2 (Medium), Sleep: On",
+ ac.toString());
+}
+
+// Tests for sendTrotec().
+
+// Test sending typical data only.
+TEST(TestSendTrotec, SendDataOnly) {
+ IRsendTest irsend(0);
+ irsend.begin();
+ uint8_t data[kTrotecStateLength] = {
+ 0x12, 0x34, 0x29, 0x82, 0x00, 0x00, 0x00, 0x00, 0xAB};
+
+ irsend.sendTrotec(data);
+ EXPECT_EQ(
+ "f36000d50"
+ "m5952s7364"
+ "m592s592m592s1560m592s592m592s592m592s1560m592s592m592s592m592s592"
+ "m592s592m592s592m592s1560m592s592m592s1560m592s1560m592s592m592s592"
+ "m592s1560m592s592m592s592m592s1560m592s592m592s1560m592s592m592s592"
+ "m592s592m592s1560m592s592m592s592m592s592m592s592m592s592m592s1560"
+ "m592s592m592s592m592s592m592s592m592s592m592s592m592s592m592s592"
+ "m592s592m592s592m592s592m592s592m592s592m592s592m592s592m592s592"
+ "m592s592m592s592m592s592m592s592m592s592m592s592m592s592m592s592"
+ "m592s592m592s592m592s592m592s592m592s592m592s592m592s592m592s592"
+ "m592s1560m592s1560m592s592m592s1560m592s592m592s1560m592s592m592s1560"
+ "m592s6184"
+ "m592s1500",
+ irsend.outputStr());
+}
+
+// Tests for decodeTrotec().
+// Decode normal Trotec messages.
+
+TEST(TestDecodeTrotec, SyntheticDecode) {
+ IRsendTest irsend(0);
+ IRrecv irrecv(0);
+ irsend.begin();
+
+ // Synthesised Normal Trotec message.
+ irsend.reset();
+ uint8_t expectedState[kTrotecStateLength] = {
+ 0x12, 0x34, 0x29, 0x82, 0x00, 0x00, 0x00, 0x00, 0xAB};
+ irsend.sendTrotec(expectedState);
+ irsend.makeDecodeResult();
+ EXPECT_TRUE(irrecv.decode(&irsend.capture));
+ EXPECT_EQ(decode_type_t::TROTEC, irsend.capture.decode_type);
+ EXPECT_EQ(kTrotecBits, irsend.capture.bits);
+ EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
+ IRTrotecESP ac(0);
+ ac.setRaw(irsend.capture.state);
+ EXPECT_EQ(
+ "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 2 (Medium), Sleep: On",
+ ac.toString());
+}
+
+
+TEST(TestTrotecESPClass, SetAndGetTemp) {
+ IRTrotecESP ac(0);
+
+ ac.setTemp(25);
+ EXPECT_EQ(25, ac.getTemp());
+ ac.setTemp(kTrotecMinTemp);
+ EXPECT_EQ(kTrotecMinTemp, ac.getTemp());
+ ac.setTemp(kTrotecMaxTemp);
+ EXPECT_EQ(kTrotecMaxTemp, ac.getTemp());
+ ac.setTemp(kTrotecMinTemp - 1);
+ EXPECT_EQ(kTrotecMinTemp, ac.getTemp());
+ ac.setTemp(kTrotecMaxTemp + 1);
+ EXPECT_EQ(kTrotecMaxTemp, ac.getTemp());
+}
+
+TEST(TestTrotecESPClass, SetAndGetMode) {
+ IRTrotecESP ac(0);
+
+ ac.setMode(kTrotecFan);
+ EXPECT_EQ(kTrotecFan, ac.getMode());
+ ac.setMode(kTrotecCool);
+ EXPECT_EQ(kTrotecCool, ac.getMode());
+ ac.setMode(kTrotecAuto);
+ EXPECT_EQ(kTrotecAuto, ac.getMode());
+ ac.setMode(kTrotecDry);
+ EXPECT_EQ(kTrotecDry, ac.getMode());
+ ac.setMode(255);
+ EXPECT_EQ(kTrotecAuto, ac.getMode());
+}
+
+TEST(TestTrotecESPClass, SetAndGetFan) {
+ IRTrotecESP ac(0);
+
+ ac.setSpeed(kTrotecFanHigh);
+ EXPECT_EQ(kTrotecFanHigh, ac.getSpeed());
+ ac.setSpeed(kTrotecFanLow);
+ EXPECT_EQ(kTrotecFanLow, ac.getSpeed());
+ ac.setSpeed(kTrotecFanMed);
+ EXPECT_EQ(kTrotecFanMed, ac.getSpeed());
+ ac.setSpeed(kTrotecFanHigh);
+ EXPECT_EQ(kTrotecFanHigh, ac.getSpeed());
+ ASSERT_NE(7, kTrotecFanHigh);
+ // Now try some unexpected value.
+ ac.setSpeed(7);
+ EXPECT_EQ(kTrotecFanHigh, ac.getSpeed());
+}
+
+TEST(TestTrotecESPClass, Sleep) {
+ IRTrotecESP ac(0);
+ ac.setSleep(false);
+ ASSERT_FALSE(ac.getSleep());
+ ac.setSleep(true);
+ ASSERT_TRUE(ac.getSleep());
+ ac.setSleep(false);
+ ASSERT_FALSE(ac.getSleep());
+}
+
+TEST(TestTrotecESPClass, Power) {
+ IRTrotecESP ac(0);
+ ac.setPower(false);
+ ASSERT_FALSE(ac.getPower());
+ ac.setPower(true);
+ ASSERT_TRUE(ac.getPower());
+ ac.setPower(false);
+ ASSERT_FALSE(ac.getPower());
+}
+
+TEST(TestUtils, Housekeeping) {
+ ASSERT_EQ("TROTEC", typeToString(decode_type_t::TROTEC));
+ ASSERT_EQ(decode_type_t::TROTEC, strToDecodeType("TROTEC"));
+ ASSERT_TRUE(hasACState(decode_type_t::TROTEC));
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Vestel_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Vestel_test.cpp
similarity index 88%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Vestel_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Vestel_test.cpp
index 077a0a25e..da95b57c4 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Vestel_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Vestel_test.cpp
@@ -321,7 +321,7 @@ TEST(TestVestelAcClass, MessageConstuction) {
IRVestelAc ac(0);
EXPECT_EQ(
- "Power: On, Mode: 0 (AUTO), Temp: 25C, Fan: 13 (AUTO HOT), Sleep: Off, "
+ "Power: On, Mode: 0 (AUTO), Temp: 25C, Fan: 13 (Auto Hot), Sleep: Off, "
"Turbo: Off, Ion: Off, Swing: Off",
ac.toString());
ac.setMode(kVestelAcCool);
@@ -329,7 +329,7 @@ TEST(TestVestelAcClass, MessageConstuction) {
ac.setFan(kVestelAcFanHigh);
EXPECT_FALSE(ac.isTimeCommand());
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 11 (HIGH), Sleep: Off, "
+ "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 11 (High), Sleep: Off, "
"Turbo: Off, Ion: Off, Swing: Off",
ac.toString());
ac.setSwing(true);
@@ -337,7 +337,7 @@ TEST(TestVestelAcClass, MessageConstuction) {
ac.setTurbo(true);
EXPECT_FALSE(ac.isTimeCommand());
EXPECT_EQ(
- "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 11 (HIGH), Sleep: Off, "
+ "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 11 (High), Sleep: Off, "
"Turbo: On, Ion: On, Swing: On",
ac.toString());
@@ -345,7 +345,7 @@ TEST(TestVestelAcClass, MessageConstuction) {
ac.setSleep(true);
ac.setMode(kVestelAcHeat);
EXPECT_EQ(
- "Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 11 (HIGH), Sleep: On, "
+ "Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 11 (High), Sleep: On, "
"Turbo: Off, Ion: On, Swing: On",
ac.toString());
EXPECT_FALSE(ac.isTimeCommand());
@@ -353,7 +353,7 @@ TEST(TestVestelAcClass, MessageConstuction) {
ac.setTemp(25);
ac.setPower(false);
EXPECT_EQ(
- "Power: Off, Mode: 4 (HEAT), Temp: 25C, Fan: 11 (HIGH), Sleep: On, "
+ "Power: Off, Mode: 4 (HEAT), Temp: 25C, Fan: 11 (High), Sleep: On, "
"Turbo: Off, Ion: On, Swing: On",
ac.toString());
EXPECT_FALSE(ac.isTimeCommand());
@@ -368,19 +368,19 @@ TEST(TestVestelAcClass, MessageConstuction) {
ac.setTimer(8 * 60 + 0);
EXPECT_TRUE(ac.isTimeCommand());
EXPECT_EQ(
- "Time: 23:59, Timer: 8:00, On Timer: Off, Off Timer: Off",
+ "Time: 23:59, Timer: 08:00, On Timer: Off, Off Timer: Off",
ac.toString());
ac.setOnTimer(7 * 60 + 40);
EXPECT_EQ(
- "Time: 23:59, Timer: Off, On Timer: 7:40, Off Timer: Off",
+ "Time: 23:59, Timer: Off, On Timer: 07:40, Off Timer: Off",
ac.toString());
ac.setOffTimer(17 * 60 + 10);
EXPECT_EQ(
- "Time: 23:59, Timer: Off, On Timer: 7:40, Off Timer: 17:10",
+ "Time: 23:59, Timer: Off, On Timer: 07:40, Off Timer: 17:10",
ac.toString());
ac.setTimer(8 * 60 + 0);
EXPECT_EQ(
- "Time: 23:59, Timer: 8:00, On Timer: Off, Off Timer: Off",
+ "Time: 23:59, Timer: 08:00, On Timer: Off, Off Timer: Off",
ac.toString());
ac.setTimer(0);
EXPECT_EQ(
@@ -389,7 +389,7 @@ TEST(TestVestelAcClass, MessageConstuction) {
ac.on();
EXPECT_FALSE(ac.isTimeCommand());
EXPECT_EQ(
- "Power: On, Mode: 4 (HEAT), Temp: 25C, Fan: 11 (HIGH), Sleep: On, "
+ "Power: On, Mode: 4 (HEAT), Temp: 25C, Fan: 11 (High), Sleep: On, "
"Turbo: Off, Ion: On, Swing: On",
ac.toString());
}
@@ -431,7 +431,7 @@ TEST(TestDecodeVestelAc, NormalDecodeWithStrict) {
ac.begin();
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
- "Power: On, Mode: 0 (AUTO), Temp: 25C, Fan: 13 (AUTO HOT), Sleep: Off, "
+ "Power: On, Mode: 0 (AUTO), Temp: 25C, Fan: 13 (Auto Hot), Sleep: Off, "
"Turbo: Off, Ion: Off, Swing: Off",
ac.toString());
}
@@ -467,7 +467,7 @@ TEST(TestDecodeVestelAc, RealNormalExample) {
ac.begin();
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
- "Power: On, Mode: 4 (HEAT), Temp: 16C, Fan: 1 (AUTO), Sleep: Off, "
+ "Power: On, Mode: 4 (HEAT), Temp: 16C, Fan: 1 (Auto), Sleep: Off, "
"Turbo: Off, Ion: On, Swing: Off",
ac.toString());
}
@@ -502,7 +502,7 @@ TEST(TestDecodeVestelAc, RealTimerExample) {
ac.begin();
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
- "Time: 5:45, Timer: Off, On Timer: 14:00, Off Timer: 23:00",
+ "Time: 05:45, Timer: Off, On Timer: 14:00, Off Timer: 23:00",
ac.toString());
}
@@ -511,3 +511,34 @@ TEST(TestDecodeVestelAc, Housekeeping) {
ASSERT_EQ("VESTEL_AC", typeToString(VESTEL_AC));
ASSERT_FALSE(hasACState(VESTEL_AC)); // Uses uint64_t, not uint8_t*.
}
+
+TEST(TestVestelAcClass, toCommon) {
+ IRVestelAc ac(0);
+ ac.setPower(true);
+ ac.setMode(kVestelAcCool);
+ ac.setTemp(20);
+ ac.setFan(kVestelAcFanHigh);
+ ac.setSwing(true);
+ ac.setTurbo(true);
+ ac.setIon(true);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::VESTEL_AC, ac.toCommon().protocol);
+ ASSERT_EQ(-1, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(20, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().filter);
+ // Unsupported.
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().light);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Whirlpool_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Whirlpool_test.cpp
similarity index 93%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Whirlpool_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Whirlpool_test.cpp
index e282989f0..6349a8154 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Whirlpool_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Whirlpool_test.cpp
@@ -70,7 +70,7 @@ TEST(TestDecodeWhirlpoolAC, SyntheticDecode) {
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
"Model: 1 (DG11J13A), Power toggle: Off, Mode: 1 (AUTO), Temp: 25C, "
- "Fan: 0 (AUTO), Swing: Off, Light: On, Clock: 17:31, On Timer: Off, "
+ "Fan: 0 (Auto), Swing: Off, Light: On, Clock: 17:31, On Timer: Off, "
"Off Timer: Off, Sleep: Off, Super: Off, Command: 2 (TEMP)",
ac.toString());
}
@@ -94,7 +94,7 @@ TEST(TestDecodeWhirlpoolAC, Real26CFanAutoCoolingSwingOnClock1918) {
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
"Model: 1 (DG11J13A), Power toggle: Off, Mode: 2 (COOL), Temp: 26C, "
- "Fan: 0 (AUTO), Swing: On, Light: On, Clock: 19:18, On Timer: Off, "
+ "Fan: 0 (Auto), Swing: On, Light: On, Clock: 19:18, On Timer: Off, "
"Off Timer: Off, Sleep: Off, Super: Off, Command: 7 (SWING)",
ac.toString());
}
@@ -149,7 +149,7 @@ TEST(TestDecodeWhirlpoolAC, RealTimerExample) {
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
"Model: 1 (DG11J13A), Power toggle: Off, Mode: 3 (DRY), Temp: 25C, "
- "Fan: 0 (AUTO), Swing: Off, Light: On, Clock: 07:35, On Timer: 07:40, "
+ "Fan: 0 (Auto), Swing: Off, Light: On, Clock: 07:35, On Timer: 07:40, "
"Off Timer: 08:05, Sleep: Off, Super: Off, Command: 5 (ONTIMER)",
ac.toString());
}
@@ -161,7 +161,7 @@ TEST(TestDecodeWhirlpoolAC, RealExampleDecode) {
irsend.begin();
// Real WhirlpoolAC message.
- // Ref: https://github.com/markszabo/IRremoteESP8266/issues/509
+ // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/509
uint16_t rawData[343] = {
8950, 4484, 598, 1642, 598, 1646, 594, 534, 594, 538, 602, 532,
598, 540, 600, 542, 598, 1650, 600, 522, 598, 1644, 596, 1650,
@@ -207,7 +207,7 @@ TEST(TestDecodeWhirlpoolAC, RealExampleDecode) {
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
"Model: 1 (DG11J13A), Power toggle: Off, Mode: 1 (AUTO), Temp: 25C, "
- "Fan: 0 (AUTO), Swing: Off, Light: On, Clock: 17:31, On Timer: Off, "
+ "Fan: 0 (Auto), Swing: Off, Light: On, Clock: 17:31, On Timer: Off, "
"Off Timer: Off, Sleep: Off, Super: Off, Command: 2 (TEMP)",
ac.toString());
}
@@ -324,25 +324,18 @@ TEST(TestIRWhirlpoolAcClass, SetAndGetClock) {
IRWhirlpoolAc ac(0);
ac.setClock(0);
EXPECT_EQ(0, ac.getClock());
- EXPECT_EQ("00:00", ac.timeToString(ac.getClock()));
ac.setClock(1);
EXPECT_EQ(1, ac.getClock());
- EXPECT_EQ("00:01", ac.timeToString(ac.getClock()));
ac.setClock(12 * 60 + 34);
EXPECT_EQ(12 * 60 + 34, ac.getClock());
- EXPECT_EQ("12:34", ac.timeToString(ac.getClock()));
ac.setClock(7 * 60 + 5);
EXPECT_EQ(7 * 60 + 5, ac.getClock());
- EXPECT_EQ("07:05", ac.timeToString(ac.getClock()));
ac.setClock(23 * 60 + 59);
EXPECT_EQ(23 * 60 + 59, ac.getClock());
- EXPECT_EQ("23:59", ac.timeToString(ac.getClock()));
ac.setClock(24 * 60 + 0);
EXPECT_EQ(0, ac.getClock());
- EXPECT_EQ("00:00", ac.timeToString(ac.getClock()));
ac.setClock(25 * 60 + 23);
EXPECT_EQ(1 * 60 + 23, ac.getClock());
- EXPECT_EQ("01:23", ac.timeToString(ac.getClock()));
}
TEST(TestIRWhirlpoolAcClass, OnOffTimers) {
@@ -353,56 +346,42 @@ TEST(TestIRWhirlpoolAcClass, OnOffTimers) {
ac.enableOnTimer(false);
ac.setOnTimer(0);
EXPECT_EQ(0, ac.getOnTimer());
- EXPECT_EQ("00:00", ac.timeToString(ac.getOnTimer()));
EXPECT_FALSE(ac.isOnTimerEnabled());
EXPECT_EQ(kWhirlpoolAcCommandOnTimer, ac.getCommand());
ac.setOnTimer(1);
EXPECT_EQ(1, ac.getOnTimer());
- EXPECT_EQ("00:01", ac.timeToString(ac.getOnTimer()));
ac.enableOnTimer(true);
ac.setOnTimer(12 * 60 + 34);
EXPECT_EQ(12 * 60 + 34, ac.getOnTimer());
- EXPECT_EQ("12:34", ac.timeToString(ac.getOnTimer()));
EXPECT_TRUE(ac.isOnTimerEnabled());
ac.setOnTimer(7 * 60 + 5);
EXPECT_EQ(7 * 60 + 5, ac.getOnTimer());
- EXPECT_EQ("07:05", ac.timeToString(ac.getOnTimer()));
ac.setOnTimer(23 * 60 + 59);
EXPECT_EQ(23 * 60 + 59, ac.getOnTimer());
- EXPECT_EQ("23:59", ac.timeToString(ac.getOnTimer()));
ac.setOnTimer(24 * 60 + 0);
EXPECT_EQ(0, ac.getOnTimer());
- EXPECT_EQ("00:00", ac.timeToString(ac.getOnTimer()));
ac.setOnTimer(25 * 60 + 23);
EXPECT_EQ(1 * 60 + 23, ac.getOnTimer());
- EXPECT_EQ("01:23", ac.timeToString(ac.getOnTimer()));
// Off Timer
ac.enableOffTimer(false);
ac.setOffTimer(0);
EXPECT_EQ(0, ac.getOffTimer());
- EXPECT_EQ("00:00", ac.timeToString(ac.getOffTimer()));
EXPECT_FALSE(ac.isOffTimerEnabled());
EXPECT_EQ(kWhirlpoolAcCommandOffTimer, ac.getCommand());
ac.setOffTimer(1);
EXPECT_EQ(1, ac.getOffTimer());
- EXPECT_EQ("00:01", ac.timeToString(ac.getOffTimer()));
ac.enableOffTimer(true);
ac.setOffTimer(12 * 60 + 34);
EXPECT_EQ(12 * 60 + 34, ac.getOffTimer());
- EXPECT_EQ("12:34", ac.timeToString(ac.getOffTimer()));
EXPECT_TRUE(ac.isOffTimerEnabled());
ac.setOffTimer(7 * 60 + 5);
EXPECT_EQ(7 * 60 + 5, ac.getOffTimer());
- EXPECT_EQ("07:05", ac.timeToString(ac.getOffTimer()));
ac.setOffTimer(23 * 60 + 59);
EXPECT_EQ(23 * 60 + 59, ac.getOffTimer());
- EXPECT_EQ("23:59", ac.timeToString(ac.getOffTimer()));
ac.setOffTimer(24 * 60 + 0);
EXPECT_EQ(0, ac.getOffTimer());
- EXPECT_EQ("00:00", ac.timeToString(ac.getOffTimer()));
ac.setOffTimer(25 * 60 + 23);
EXPECT_EQ(1 * 60 + 23, ac.getOffTimer());
- EXPECT_EQ("01:23", ac.timeToString(ac.getOffTimer()));
}
TEST(TestIRWhirlpoolAcClass, SetAndGetCommand) {
@@ -578,8 +557,41 @@ TEST(TestIRWhirlpoolAcClass, MessageConstruction) {
EXPECT_EQ(
"Model: 1 (DG11J13A), Power toggle: Off, Mode: 3 (DRY), Temp: 25C, "
- "Fan: 0 (AUTO), Swing: Off, Light: On, Clock: 07:35, On Timer: 07:40, "
+ "Fan: 0 (Auto), Swing: Off, Light: On, Clock: 07:35, On Timer: 07:40, "
"Off Timer: 08:05, Sleep: Off, Super: Off, Command: 5 (ONTIMER)",
ac.toString());
EXPECT_STATE_EQ(expectedState, ac.getRaw(), kWhirlpoolAcBits);
}
+
+TEST(TestIRWhirlpoolAcClass, toCommon) {
+ IRWhirlpoolAc ac(0);
+ ac.setModel(whirlpool_ac_remote_model_t::DG11J13A);
+ ac.setPowerToggle(true);
+ ac.setMode(kWhirlpoolAcCool);
+ ac.setTemp(18);
+ ac.setFan(kWhirlpoolAcFanHigh);
+ ac.setSwing(true);
+ ac.setSuper(true);
+ ac.setLight(true);
+ ac.setSleep(false);
+ // Now test it.
+ ASSERT_EQ(decode_type_t::WHIRLPOOL_AC, ac.toCommon().protocol);
+ ASSERT_EQ(whirlpool_ac_remote_model_t::DG11J13A, ac.toCommon().model);
+ ASSERT_TRUE(ac.toCommon().power);
+ ASSERT_TRUE(ac.toCommon().celsius);
+ ASSERT_EQ(18, ac.toCommon().degrees);
+ ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
+ ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
+ ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
+ ASSERT_TRUE(ac.toCommon().turbo);
+ ASSERT_TRUE(ac.toCommon().light);
+ ASSERT_EQ(-1, ac.toCommon().sleep);
+ // Unsupported.
+ ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
+ ASSERT_FALSE(ac.toCommon().econo);
+ ASSERT_FALSE(ac.toCommon().filter);
+ ASSERT_FALSE(ac.toCommon().clean);
+ ASSERT_FALSE(ac.toCommon().beep);
+ ASSERT_FALSE(ac.toCommon().quiet);
+ ASSERT_EQ(-1, ac.toCommon().clock);
+}
diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Whynter_test.cpp b/lib/IRremoteESP8266-2.6.5/test/ir_Whynter_test.cpp
similarity index 97%
rename from lib/IRremoteESP8266-2.6.0/test/ir_Whynter_test.cpp
rename to lib/IRremoteESP8266-2.6.5/test/ir_Whynter_test.cpp
index 92ced5cf6..0c45f2654 100644
--- a/lib/IRremoteESP8266-2.6.0/test/ir_Whynter_test.cpp
+++ b/lib/IRremoteESP8266-2.6.5/test/ir_Whynter_test.cpp
@@ -151,7 +151,7 @@ TEST(TestDecodeWhynter, NormalDecodeWithStrict) {
irsend.reset();
irsend.sendWhynter(0x87654321);
irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(WHYNTER, irsend.capture.decode_type);
EXPECT_EQ(kWhynterBits, irsend.capture.bits);
EXPECT_EQ(0x87654321, irsend.capture.value);
@@ -170,20 +170,20 @@ TEST(TestDecodeWhynter, NormalDecodeWithRepeatAndStrict) {
irsend.reset();
irsend.sendWhynter(0x87654321, kWhynterBits, 2);
irsend.makeDecodeResult();
- ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(WHYNTER, irsend.capture.decode_type);
EXPECT_EQ(kWhynterBits, irsend.capture.bits);
EXPECT_EQ(0x87654321, irsend.capture.value);
EXPECT_FALSE(irsend.capture.repeat);
irsend.makeDecodeResult(2 * kWhynterBits + 6);
- ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(WHYNTER, irsend.capture.decode_type);
EXPECT_EQ(kWhynterBits, irsend.capture.bits);
EXPECT_EQ(0x87654321, irsend.capture.value);
irsend.makeDecodeResult(2 * (2 * kWhynterBits + 6));
- ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true));
+ ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(WHYNTER, irsend.capture.decode_type);
EXPECT_EQ(kWhynterBits, irsend.capture.bits);
EXPECT_EQ(0x87654321, irsend.capture.value);
diff --git a/lib/IRremoteESP8266-2.6.0/tools/Makefile b/lib/IRremoteESP8266-2.6.5/tools/Makefile
similarity index 86%
rename from lib/IRremoteESP8266-2.6.0/tools/Makefile
rename to lib/IRremoteESP8266-2.6.5/tools/Makefile
index 08488949c..d2da05eb3 100644
--- a/lib/IRremoteESP8266-2.6.0/tools/Makefile
+++ b/lib/IRremoteESP8266-2.6.5/tools/Makefile
@@ -29,7 +29,7 @@ run_tests : all
failed=""; \
for py_unittest in *_test.py; do \
echo "RUNNING: $${py_unittest}"; \
- python ./$${py_unittest} || failed="$${failed} $${py_unittest}"; \
+ python3 ./$${py_unittest} || failed="$${failed} $${py_unittest}"; \
done; \
if [ -n "$${failed}" ]; then \
echo "FAIL: :-( :-( Unit test(s)$${failed} failed! :-( :-("; exit 1; \
@@ -50,7 +50,8 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \
ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o ir_Hitachi.o \
ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o ir_Pioneer.o \
ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o ir_Lego.o \
- ir_MitsubishiHeavy.o
+ ir_MitsubishiHeavy.o ir_Goodweather.o ir_Inax.o ir_Argo.o \
+ ir_Trotec.o ir_Neoclima.o ir_Amcor.o
# Common object files
COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS)
@@ -104,6 +105,9 @@ ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_DEPS
ir_Kelvinator.o : $(USER_DIR)/ir_Kelvinator.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Kelvinator.cpp
+ir_Inax.o : $(USER_DIR)/ir_Inax.cpp $(COMMON_DEPS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Inax.cpp
+
ir_JVC.o : $(USER_DIR)/ir_JVC.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_JVC.cpp
@@ -122,8 +126,8 @@ ir_MitsubishiHeavy.o : $(USER_DIR)/ir_MitsubishiHeavy.h $(USER_DIR)/ir_Mitsubish
ir_Fujitsu.o : $(USER_DIR)/ir_Fujitsu.h $(USER_DIR)/ir_Fujitsu.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Fujitsu.cpp
-ir_Sharp.o : $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sharp.cpp
+ir_Sharp.o : $(USER_DIR)/ir_Sharp.h $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Sharp.cpp
ir_RC5_RC6.o : $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RC5_RC6.cpp
@@ -192,7 +196,7 @@ ir_Lutron.o : $(USER_DIR)/ir_Lutron.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lutron.cpp
ir_Electra.o : $(USER_DIR)/ir_Electra.cpp $(GTEST_HEADERS)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Electra.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Electra.cpp
ir_Pioneer.o : $(USER_DIR)/ir_Pioneer.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pioneer.cpp
@@ -209,5 +213,20 @@ ir_Teco.o : $(USER_DIR)/ir_Teco.cpp $(GTEST_HEADERS)
ir_Tcl.o : $(USER_DIR)/ir_Tcl.cpp $(USER_DIR)/ir_Tcl.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Tcl.cpp
+ir_Trotec.o : $(USER_DIR)/ir_Trotec.cpp $(USER_DIR)/ir_Trotec.h $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Trotec.cpp
+
ir_Lego.o : $(USER_DIR)/ir_Lego.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lego.cpp
+
+ir_Argo.o : $(USER_DIR)/ir_Argo.cpp $(USER_DIR)/ir_Argo.h $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Argo.cpp
+
+ir_Goodweather.o : $(USER_DIR)/ir_Goodweather.cpp $(USER_DIR)/ir_Goodweather.h $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Goodweather.cpp
+
+ir_Neoclima.o : $(USER_DIR)/ir_Neoclima.cpp $(USER_DIR)/ir_Neoclima.h $(COMMON_DEPS) $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Neoclima.cpp
+
+ir_Amcor.o : $(USER_DIR)/ir_Amcor.cpp $(USER_DIR)/ir_Amcor.h $(GTEST_HEADERS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Amcor.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/tools/RawToGlobalCache.sh b/lib/IRremoteESP8266-2.6.5/tools/RawToGlobalCache.sh
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/tools/RawToGlobalCache.sh
rename to lib/IRremoteESP8266-2.6.5/tools/RawToGlobalCache.sh
diff --git a/lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data.py b/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data.py
similarity index 98%
rename from lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data.py
rename to lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data.py
index b23cdb46f..8a2e45794 100644
--- a/lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data.py
+++ b/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data.py
@@ -8,7 +8,7 @@ import argparse
import sys
-class RawIRMessage(object):
+class RawIRMessage():
"""Basic analyse functions & structure for raw IR messages."""
# pylint: disable=too-many-instance-attributes
@@ -62,7 +62,7 @@ class RawIRMessage(object):
def _usec_compare(self, seen, expected):
"""Compare two usec values and see if they match within a
subtractive margin."""
- return seen <= expected and seen > expected - self.margin
+ return expected - self.margin < seen <= expected
def _usec_compares(self, usecs, expecteds):
"""Compare a usec value to a list of values and return True
@@ -160,7 +160,7 @@ class RawIRMessage(object):
def avg_list(items):
"""Return the average of a list of numbers."""
if items:
- return sum(items) / len(items)
+ return int(sum(items) / len(items))
return 0
@@ -293,7 +293,7 @@ def decode_data(message, defines, function_code, output=sys.stdout):
output.write("kHdrSpace+")
function_code.append(" space(kHdrSpace);")
elif message.is_bit_mark(usec) and count % 2:
- if state != "HS" and state != "BS":
+ if state not in ("HS", "BS"):
output.write("kBitMark(UNEXPECTED)")
state = "BM"
elif message.is_zero_space(usec):
diff --git a/lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data_test.py b/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data_test.py
similarity index 97%
rename from lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data_test.py
rename to lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data_test.py
index 681ff5520..5d5504ffc 100644
--- a/lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data_test.py
+++ b/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data_test.py
@@ -1,6 +1,6 @@
-#!/usr/bin/python
+#!/usr/bin/python3
"""Unit tests for auto_analyse_raw_data.py"""
-import StringIO
+from io import StringIO
import unittest
import auto_analyse_raw_data as analyse
@@ -12,7 +12,7 @@ class TestRawIRMessage(unittest.TestCase):
def test_display_binary(self):
"""Test the display_binary() method."""
- output = StringIO.StringIO()
+ output = StringIO()
message = analyse.RawIRMessage(100, [8000, 4000, 500, 500, 500], output,
False)
self.assertEqual(output.getvalue(), '')
@@ -52,8 +52,8 @@ class TestAutoAnalyseRawData(unittest.TestCase):
def test_dump_constants_simple(self):
"""Simple tests for the dump_constants() function."""
- ignore = StringIO.StringIO()
- output = StringIO.StringIO()
+ ignore = StringIO()
+ output = StringIO()
defs = []
message = analyse.RawIRMessage(200, [
7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494,
@@ -75,8 +75,8 @@ class TestAutoAnalyseRawData(unittest.TestCase):
def test_dump_constants_aircon(self):
"""More complex tests for the dump_constants() function."""
- ignore = StringIO.StringIO()
- output = StringIO.StringIO()
+ ignore = StringIO()
+ output = StringIO()
defs = []
message = analyse.RawIRMessage(200, [
9008, 4496, 644, 1660, 676, 530, 648, 558, 672, 1636, 646, 1660, 644,
@@ -111,7 +111,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
self.assertEqual(analyse.convert_rawdata("0"), [0])
with self.assertRaises(ValueError) as context:
analyse.convert_rawdata("")
- self.assertEqual(context.exception.message,
+ self.assertEqual(str(context.exception),
"Raw Data contains a non-numeric value of ''.")
# Single parenthesis
@@ -132,13 +132,13 @@ class TestAutoAnalyseRawData(unittest.TestCase):
# Bad parentheses
with self.assertRaises(ValueError) as context:
analyse.convert_rawdata("}10{")
- self.assertEqual(context.exception.message,
+ self.assertEqual(str(context.exception),
"Raw Data not parsible due to parentheses placement.")
# Non base-10 values
with self.assertRaises(ValueError) as context:
analyse.convert_rawdata("10, 20, foo, bar, 30")
- self.assertEqual(context.exception.message,
+ self.assertEqual(str(context.exception),
"Raw Data contains a non-numeric value of 'foo'.")
# A messy usual "good" case.
@@ -155,7 +155,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
"""Tests for the parse_and_report() function."""
# Without code generation.
- output = StringIO.StringIO()
+ output = StringIO()
input_str = """
uint16_t rawbuf[139] = {9008, 4496, 644, 1660, 676, 530, 648, 558, 672,
1636, 646, 1660, 644, 556, 650, 584, 626, 560, 644, 580, 628, 1680,
@@ -210,7 +210,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
'Total Nr. of suspected bits: 67\n')
# With code generation.
- output = StringIO.StringIO()
+ output = StringIO()
input_str = """
uint16_t rawbuf[37] = {7930, 3952, 494, 1482, 520, 1482, 494,
1508, 494, 520, 494, 1482, 494, 520, 494, 1482, 494, 1482, 494,
@@ -294,7 +294,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
"""Tests for unusual Space Gaps in parse_and_report() function."""
# Tests for unusual Gaps. (Issue #482)
- output = StringIO.StringIO()
+ output = StringIO()
input_str = """
uint16_t rawbuf[272] = {3485, 3512, 864, 864, 864, 2620, 864, 864,
864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864,
@@ -466,7 +466,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
def test_reduce_list(self):
"""Tests for the reduce_list method."""
- ignore = StringIO.StringIO()
+ ignore = StringIO()
message = analyse.RawIRMessage(200, [
7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494,
520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494,
diff --git a/lib/IRremoteESP8266-2.6.0/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.6.5/tools/gc_decode.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/tools/gc_decode.cpp
rename to lib/IRremoteESP8266-2.6.5/tools/gc_decode.cpp
diff --git a/lib/IRremoteESP8266-2.6.0/tools/mkkeywords b/lib/IRremoteESP8266-2.6.5/tools/mkkeywords
similarity index 82%
rename from lib/IRremoteESP8266-2.6.0/tools/mkkeywords
rename to lib/IRremoteESP8266-2.6.5/tools/mkkeywords
index a2cdccd9b..3172383ad 100644
--- a/lib/IRremoteESP8266-2.6.0/tools/mkkeywords
+++ b/lib/IRremoteESP8266-2.6.5/tools/mkkeywords
@@ -30,9 +30,8 @@ cat << EndOfTextEndOfTextEndOfText
EndOfTextEndOfTextEndOfText
-CLASSES=$(grep "^class " src/*.h | cut -d' ' -f2 | sort -u)
-# Manually add typedefs as they are hard to parse out.
-CLASSES="${CLASSES} ir_params_t match_result_t"
+CLASSES=$(egrep -h "^ *((enum|class) |} [a-zA-Z0-9_]+_t;$)" src/*.h |
+ sed 's/^ *//;s/enum class//;s/\;$//' | cut -d' ' -f2 | sort -u)
for i in ${CLASSES}; do
echo -e "${i}\tKEYWORD1"
done | sort -du
@@ -44,10 +43,11 @@ cat << EndOfTextEndOfTextEndOfText
#######################################
EndOfTextEndOfTextEndOfText
-
-METHODS=$(egrep "^(u?int|void|bool|String|static|match_result_t).*\(" src/*.cpp|
- cut -d' ' -f2- | sed 's/^.*:://' | cut -d'(' -f1 | sort -u |
- grep -v ICACHE_RAM_ATTR)
+CTYPES="u?int(8|16|32|64)?(_t)?|void|bool|char|float|long|double|String|static"
+OURTYPES="match_result_t|state_t|decode_type_t"
+METHODS=$(egrep -h "^[ ]{0,2}(${CTYPES}|${OURTYPES})\*? [^ ]*\(" src/*.cpp |
+ sed 's/^ //' | cut -d' ' -f2 | sed 's/^\([^:]*::\| *\* *\)//' |
+ cut -d'(' -f1 | sort -u | grep -v RAM_ATTR)
for i in ${METHODS}; do
echo -e "${i}\tKEYWORD2"
done | sort -u
diff --git a/lib/IRremoteESP8266-2.6.0/tools/mode2_decode.cpp b/lib/IRremoteESP8266-2.6.5/tools/mode2_decode.cpp
similarity index 100%
rename from lib/IRremoteESP8266-2.6.0/tools/mode2_decode.cpp
rename to lib/IRremoteESP8266-2.6.5/tools/mode2_decode.cpp
diff --git a/lib/IRremoteESP8266-2.6.5/tools/scrape_supported_devices.py b/lib/IRremoteESP8266-2.6.5/tools/scrape_supported_devices.py
new file mode 100644
index 000000000..574eac351
--- /dev/null
+++ b/lib/IRremoteESP8266-2.6.5/tools/scrape_supported_devices.py
@@ -0,0 +1,255 @@
+#!/usr/bin/env python3
+"""Generate SupportedProtocols.md by scraping source code files"""
+import pathlib
+import argparse
+import sys
+import re
+import time
+
+CODE_URL = "https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_"
+
+BRAND_MODEL = re.compile(r"Brand: *(?P.+), *Model: *(?P.+)")
+ENUMS = re.compile(r"enum \w+ {(.+?)};", re.DOTALL)
+ENUM_ENTRY = re.compile(r"^\s+(\w+)", re.MULTILINE)
+DECODED_PROTOCOLS = re.compile(r".*results->decode_type *=.*?(\w+);")
+AC_FN = re.compile(r"ir_(.+).h")
+
+ALL_FN = re.compile(r"ir_(.+).(h|cpp)")
+
+EXCLUDED_PROTOCOLS = ["UNKNOWN", "UNUSED", "kLastDecodeType"]
+
+MARKDOWN_HEADER = """""".format(time.asctime())
+
+
+def getallprotocols():
+ """Return all protocls configured in IRremoteESP8266.h
+ """
+ irremote = ARGS.directory / "IRremoteESP8266.h"
+ enums = getenums(irremote)
+ if not enums:
+ errorexit("Error getting ENUMS from IRremoteESP8266.h")
+ return enums
+
+
+def getdecodedprotocols():
+ """All protocols that include decoding support"""
+ ret = set()
+ for path in ARGS.directory.iterdir():
+ if path.suffix != ".cpp":
+ continue
+ matches = DECODED_PROTOCOLS.finditer(path.open().read())
+ for match in matches:
+ protocol = match.group(1)
+ if protocol not in EXCLUDED_PROTOCOLS:
+ ret.add(protocol)
+ return ret
+
+
+def getallacs():
+ """All supported A/C codes"""
+ ret = {}
+ for path in ARGS.directory.iterdir():
+ match = AC_FN.match(path.name)
+ if not match:
+ continue
+ acprotocol = match.group(1)
+ rawmodels = getenums(path)
+ models = set()
+ for model in rawmodels:
+ model = model.upper()
+ model = model.replace("K{}".format(acprotocol.upper()), "")
+ if model and model not in EXCLUDED_PROTOCOLS:
+ models.add(model)
+ ret[acprotocol] = models
+ return ret
+
+
+def getalldevices():
+ """All devices and associated branding and model information (if available)
+ """
+ allcodes = {}
+ fnnomatch = set()
+ fnmatch = set()
+ for path in ARGS.directory.iterdir():
+ match = ALL_FN.match(path.name)
+ if not match:
+ continue
+ supports = extractsupports(path)
+ if supports:
+ fnmatch.add(path.stem)
+ else:
+ fnnomatch.add(path.stem)
+ protocol = match.group(1)
+ for brand, model in supports:
+ protocolbrand = (protocol, brand)
+ allcodes[protocolbrand] = allcodes.get(protocolbrand, list()) + [model]
+ nosupports = fnnomatch - fnmatch
+ for fnprotocol in nosupports:
+ allcodes[(fnprotocol[3:], "Unknown")] = []
+ return allcodes, nosupports
+
+
+def getenums(path):
+ """Returns the keys for the first enum type in path
+ """
+ enums = ENUMS.search(path.open().read())
+ ret = set()
+ if not enums:
+ return ret
+ for enum in ENUM_ENTRY.finditer(enums.group(1)):
+ enum = enum.group(1)
+ if enum in EXCLUDED_PROTOCOLS:
+ continue
+ ret.add(enum)
+ return ret
+
+
+ARGS = None
+
+
+def initargs():
+ """Init the command line arguments"""
+ global ARGS # pylint: disable=global-statement
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "-s",
+ "--stdout",
+ help="output to stdout rather than SupportedProtocols.md",
+ action="store_true",
+ )
+ parser.add_argument("-v",
+ "--verbose",
+ help="increase output verbosity",
+ action="store_true")
+ parser.add_argument(
+ "-a",
+ "--alert",
+ help="alert if a file does not have a supports section",
+ action="store_true",
+ )
+ parser.add_argument(
+ "directory",
+ nargs="?",
+ help="directory of the source git checkout",
+ default=None,
+ )
+ ARGS = parser.parse_args()
+ if ARGS.directory is None:
+ src = pathlib.Path("../src")
+ if not src.is_dir():
+ src = pathlib.Path("./src")
+ else:
+ src = pathlib.Path(ARGS.directory) / "src"
+ if not src.is_dir():
+ errorexit("Directory not valid: {}".format(str(src)))
+ ARGS.directory = src
+ return ARGS
+
+
+def errorexit(msg):
+ """Print an error and exit on critical error"""
+ sys.stderr.write("{}\n".format(msg))
+ sys.exit(1)
+
+
+def extractsupports(path):
+ """Extract all of the Supports: sections and associated brands and models
+ """
+ supports = []
+ insupports = False
+ for line in path.open():
+ if not line.startswith("//"):
+ continue
+ line = line[2:].strip()
+ if line == "Supports:":
+ insupports = True
+ continue
+ if insupports:
+ match = BRAND_MODEL.match(line)
+ if match:
+ supports.append((match.group("brand"), match.group("model")))
+ else:
+ insupports = False
+ continue
+ return supports
+
+
+def makeurl(txt, path):
+ """Make a Markup URL from given filename"""
+ return "[{}]({})".format(txt, CODE_URL + path)
+
+
+def outputprotocols(fout, protocols):
+ """For a given protocol set, sort and output the markdown"""
+ protocols = list(protocols)
+ protocols.sort()
+ for protocol in protocols:
+ fout.write("- {}\n".format(protocol))
+
+
+def main():
+ """Standard boiler plate"""
+ initargs()
+ if ARGS.verbose:
+ print("Looking for files in: {}".format(str(ARGS.directory.resolve())))
+ if ARGS.stdout:
+ fout = sys.stdout
+ else:
+ foutpath = ARGS.directory / "../SupportedProtocols.md"
+ foutpath = foutpath.resolve()
+ if ARGS.verbose:
+ print("Output path: {}".format(str(foutpath)))
+ fout = foutpath.open("w")
+ decodedprotocols = getdecodedprotocols()
+ sendonly = getallprotocols() - decodedprotocols
+ allacs = getallacs()
+
+ allcodes, nosupports = getalldevices()
+ allbrands = list(allcodes.keys())
+ allbrands.sort()
+
+ fout.write(MARKDOWN_HEADER)
+ fout.write("\n# IR Protocols supported by this library\n\n")
+ fout.write(
+ "| Protocol | Brand | Model | A/C Model | Detailed A/C Support |\n")
+ fout.write("| --- | --- | --- | --- | --- |\n")
+
+ for protocolbrand in allbrands:
+ protocol, brand = protocolbrand
+ codes = allcodes[protocolbrand]
+ codes.sort()
+ if protocol in allacs:
+ acmodels = list(allacs[protocol])
+ acmodels.sort()
+ acsupport = "Yes"
+ brand = makeurl(brand, protocol + ".h")
+ else:
+ acmodels = []
+ acsupport = "-"
+
+ fout.write("| {} | **{}** | {} | {} | {} |\n".format(
+ makeurl(protocol, protocol + ".cpp"),
+ brand,
+ " ".join(codes),
+ " ".join(acmodels),
+ acsupport,
+ ))
+
+ fout.write("\n\n## Send only protocols:\n\n")
+ outputprotocols(fout, sendonly)
+
+ fout.write("\n\n## Send & decodable protocols:\n\n")
+ outputprotocols(fout, decodedprotocols)
+
+ if ARGS.alert:
+ nosupports = list(nosupports)
+ nosupports.sort()
+ print("The following files had no supports section:")
+ for path in nosupports:
+ print("\t{}".format(path))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/lib/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp b/lib/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp
new file mode 100644
index 000000000..3e0aca9ee
--- /dev/null
+++ b/lib/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp
@@ -0,0 +1,1104 @@
+/***************************************************
+ STM32 Support added by Jaret Burkett at OSHlab.com
+
+ This is our library for the Adafruit ILI9488 Breakout and Shield
+ ----> http://www.adafruit.com/products/1651
+
+ Check out the links above for our tutorials and wiring diagrams
+ These displays use SPI to communicate, 4 or 5 pins are required to
+ interface (RST is optional)
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries.
+ MIT license, all text above must be included in any redistribution
+ ****************************************************/
+#include
+#include "ILI9488.h"
+#include
+
+// if using software spi this optimizes the code
+#define SWSPI_OPTMODE
+
+#define ILI9488_START start();
+#define ILI9488_STOP stop();
+
+const uint16_t ili9488_colors[]={ILI9488_BLACK,ILI9488_WHITE,ILI9488_RED,ILI9488_GREEN,ILI9488_BLUE,ILI9488_CYAN,ILI9488_MAGENTA,\
+ ILI9488_YELLOW,ILI9488_NAVY,ILI9488_DARKGREEN,ILI9488_DARKCYAN,ILI9488_MAROON,ILI9488_PURPLE,ILI9488_OLIVE,\
+ILI9488_LIGHTGREY,ILI9488_DARKGREY,ILI9488_ORANGE,ILI9488_GREENYELLOW,ILI9488_PINK};
+
+// Constructor when using software SPI. All output pins are configurable.
+ILI9488::ILI9488(int8_t cs,int8_t mosi,int8_t sclk,int8_t bp) : Renderer(ILI9488_TFTWIDTH, ILI9488_TFTHEIGHT) {
+ _cs = cs;
+ _mosi = mosi;
+ _sclk = sclk;
+ _bp = bp;
+ _hwspi = 0;
+}
+
+
+#include "spi_register.h"
+
+/*
+
+CPU Clock = 80 Mhz
+max clock of display is 15 Mhz (66ns sclk cycle)
+so cpu/8 => 10 Mhz should be ok
+
+HSPI CLK 5 GPIO14
+HSPI /CS 8 GPIO15
+HSPI MOSI 7 GPIO13
+HSPI MISO 6 GPIO12
+
+
+GPIO names for your easy reference:
+GPIO0: PERIPHS_IO_MUX_GPIO0_U
+GPIO1: PERIPHS_IO_MUX_U0TXD_U
+GPIO2: PERIPHS_IO_MUX_GPIO2_U
+GPIO3: PERIPHS_IO_MUX_U0RXD_U
+GPIO4: PERIPHS_IO_MUX_GPIO4_U
+GPIO5: PERIPHS_IO_MUX_GPIO5_U
+GPIO6: PERIPHS_IO_MUX_SD_CLK_U
+GPIO7: PERIPHS_IO_MUX_SD_DATA0_U
+GPIO8: PERIPHS_IO_MUX_SD_DATA1_U
+GPIO9: PERIPHS_IO_MUX_SD_DATA2_U
+GPIO10: PERIPHS_IO_MUX_SD_DATA3_U
+GPIO11: PERIPHS_IO_MUX_SD_CMD_U
+GPIO12: PERIPHS_IO_MUX_MTDI_U
+GPIO13: PERIPHS_IO_MUX_MTCK_U
+GPIO14: PERIPHS_IO_MUX_MTMS_U
+GPIO15: PERIPHS_IO_MUX_MTDO_U
+*/
+
+uint8_t ili9488_start;
+
+uint32_t ili9488_clock;
+uint32_t ili9488_usr;
+uint32_t ili9488_usr1;
+uint32_t ili9488_usr2;
+uint32_t ili9488_spi1c;
+uint32_t ili9488_spi1c1;
+uint32_t ili9488_spi1p;
+uint32_t ili9488_gpmux;
+uint32_t ili9488_mtdo;
+
+
+uint32_t ili9488_clock_prev;
+uint32_t ili9488_usr_prev;
+uint32_t ili9488_usr1_prev;
+uint32_t ili9488_usr2_prev;
+uint32_t ili9488_spi1c_prev;
+uint32_t ili9488_spi1c1_prev;
+uint32_t ili9488_spi1p_prev;
+uint32_t ili9488_gpmux_prev;
+uint32_t ili9488_mtdo_prev;
+
+// code from espressif SDK
+/******************************************************************************
+ * FunctionName : spi_lcd_mode_init
+ * Description : SPI master initial function for driving LCD 3 wire spi
+*******************************************************************************/
+void ILI9488::spi_lcd_mode_init(void) {
+
+ ili9488_clock_prev=SPI1CLK;
+ ili9488_usr_prev=SPI1U;
+ ili9488_usr1_prev=SPI1U1;
+ ili9488_usr2_prev=SPI1U2;
+ ili9488_spi1c_prev=SPI1C;
+ ili9488_spi1c1_prev=SPI1C1;
+ ili9488_spi1p_prev=SPI1P;
+ ili9488_gpmux_prev=GPMUX;
+ ili9488_mtdo_prev=READ_PERI_REG(PERIPHS_IO_MUX_MTDO_U);
+
+ SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE;
+ SPI1U1=0;
+ SPI1C = 0;
+ SPI1C1 = 0;
+
+ //bit9 of PERIPHS_IO_MUX should be cleared when HSPI clock doesn't equal CPU clock
+ //bit8 of PERIPHS_IO_MUX should be cleared when SPI clock doesn't equal CPU clock
+
+ WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9
+ //PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure miso to spi mode
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure mosi to spi mode
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure sclk to spi mode
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure cs to spi mode
+
+// the current implementation leaves about 1 us between transfers ????
+// due to lack of documentation i could not find the reason
+// skipping this would double the speed !!!
+
+ //SET_PERI_REG_MASK(SPI_USER(1), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND);
+
+ SET_PERI_REG_MASK(SPI_USER(1), SPI_USR_COMMAND);
+
+ CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_FLASH_MODE);
+ // SPI clock=CPU clock/8 => 10 Mhz
+ /*
+ WRITE_PERI_REG(SPI_CLOCK(1),
+ ((1&SPI_CLKDIV_PRE)<>1)|0x80;
+ else bytetemp=(low_8bit>>1)&0x7f;
+
+ regvalue= ((8&SPI_USR_COMMAND_BITLEN)<