diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 44032a982..88dc78c9d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -7,7 +7,7 @@ - [ ] Only relevant files were touched - [ ] Only one feature/fix was added per PR and the code change compiles without warnings - [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.4.9 - - [ ] The code change is tested and works with Tasmota core ESP32 V.2.0.4.1 + - [ ] The code change is tested and works with Tasmota core ESP32 V.2.0.5 - [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla). _NOTE: The code change must pass CI tests. **Your PR cannot be merged unless tests pass**_ diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index b7bc2224e..2bbc4fc66 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -59,13 +59,14 @@ jobs: with: ref: development - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 - name: Install dependencies run: | + pip install wheel pip install -U platformio - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: firmware path: ./build_output @@ -83,13 +84,14 @@ jobs: with: ref: development - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 - name: Install dependencies run: | + pip install wheel pip install -U platformio - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: firmware path: ./build_output @@ -99,7 +101,7 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: firmware path: ./mv_firmware diff --git a/.github/workflows/Tasmota_build_master.yml b/.github/workflows/Tasmota_build_master.yml index 951704d34..9905d287f 100644 --- a/.github/workflows/Tasmota_build_master.yml +++ b/.github/workflows/Tasmota_build_master.yml @@ -58,13 +58,14 @@ jobs: with: ref: master - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 - name: Install dependencies run: | + pip install wheel pip install -U platformio - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: firmware path: ./build_output @@ -82,13 +83,14 @@ jobs: with: ref: master - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 - name: Install dependencies run: | + pip install wheel pip install -U platformio - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: firmware path: ./build_output @@ -99,7 +101,7 @@ jobs: continue-on-error: true steps: - uses: actions/checkout@v3 - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: firmware path: ./mv_firmware diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index 65671604e..ae8e7e1eb 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -17,10 +17,63 @@ on: - '.github/workflows/build_all_the_things.yml' jobs: + os-check-win: + runs-on: windows-2019 + if: github.repository == 'arendst/Tasmota' + strategy: + fail-fast: true + matrix: + variant: + - tasmota32-safeboot + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + - name: Install dependencies + run: | + pip install wheel + #python -m pip install --upgrade pip + pip install -U platformio + #platformio upgrade --dev + #platformio update + - name: Run PlatformIO + run: platformio run -e ${{ matrix.variant }} + - uses: actions/upload-artifact@v3 + with: + name: firmware + path: ./build_output + + os-check-mac: + runs-on: macos-latest + if: github.repository == 'arendst/Tasmota' + strategy: + fail-fast: true + matrix: + variant: + - tasmota32-webcam + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + - name: Install dependencies + run: | + pip install wheel + #python -m pip install --upgrade pip + pip install -U platformio + #platformio upgrade --dev + #platformio update + - name: Run PlatformIO + run: platformio run -e ${{ matrix.variant }} + - uses: actions/upload-artifact@v3 + with: + name: firmware + path: ./build_output + base-images: runs-on: ubuntu-latest if: github.repository == 'arendst/Tasmota' strategy: + fail-fast: true matrix: variant: - tasmota @@ -32,25 +85,23 @@ jobs: - tasmota-minimal - tasmota-sensors - tasmota-zbbridge + - tasmota32 + - tasmota32c3 + - tasmota32s2 + - tasmota32s3 - tasmota32-zbbrdgpro - tasmota-zigbee - - tasmota32 - - tasmota32-webcam - tasmota32-bluetooth - tasmota32-core2 - tasmota32-nspanel - tasmota32-display - tasmota32-ir - tasmota32-lvgl - - tasmota32c3 - tasmota32c3cdc - - tasmota32s2 - tasmota32s2cdc - - tasmota32s3 - tasmota32s3cdc - tasmota32solo1 - tasmota32solo1-safeboot - - tasmota32-safeboot - tasmota32c3-safeboot - tasmota32c3cdc-safeboot - tasmota32s2-safeboot @@ -58,18 +109,19 @@ jobs: - tasmota32s3-safeboot - tasmota32s3cdc-safeboot steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v1 + uses: actions/setup-python@v3 - name: Install dependencies run: | + pip install wheel #python -m pip install --upgrade pip pip install -U platformio #platformio upgrade --dev #platformio update - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: firmware path: ./build_output @@ -78,22 +130,24 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'arendst/Tasmota' strategy: + fail-fast: true matrix: variant: [ tasmota ] language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v1 + uses: actions/setup-python@v3 - name: Install dependencies run: | + pip install wheel #python -m pip install --upgrade pip pip install -U platformio #platformio upgrade --dev #platformio update - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: firmware path: ./build_output diff --git a/.github/workflows/copy_change.yml b/.github/workflows/copy_change.yml index 1306ccd50..da236fc52 100644 --- a/.github/workflows/copy_change.yml +++ b/.github/workflows/copy_change.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'arendst/Tasmota' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Push I2CDevices.md to https://github.com/Tasmota/docs uses: Jason2866/copy_file_to_another_repo_action@main env: diff --git a/.gitignore b/.gitignore index 1dd51a787..22f113ae2 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,8 @@ firmware.asm tasmota/tasmota.ino.cpp platformio_override.ini platformio_tasmota_cenv.ini +lib/libesp32/berry/generate/* +lib/libesp32/berry/berry ## Visual Studio Code specific ###### .vscode diff --git a/BUILDS.md b/BUILDS.md index b0e6584e6..f10d3359a 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -6,174 +6,177 @@ l = lite, t = tasmota, k = knx, s = sensors, i = ir, d = display Note: `minimal` variant is not listed as it shouldn't be used outside of the [upgrading](https://tasmota.github.io/docs/Upgrading/) process. -| Feature or Sensor | l | t | k | s | i | d | Remarks -|-----------------------|---|-------|---|---|---|---|-------- -| MY_LANGUAGE en_GB | x | x / x | x | x | x | x | -| USE_IMPROV | x | x / x | x | x | x | x | -| USE_UFILESYS | - | - / x | - | - | - | - | -| USE_ARDUINO_OTA | - | - / - | - | - | - | - | -| USE_DOMOTICZ | - | x / x | x | x | x | - | -| USE_HOME_ASSISTANT | - | - / - | - | - | - | - | -| USE_TASMOTA_DISCOVERY | x | x / x | x | x | x | x | -| USE_MQTT_TLS* | - | - / x | - | - | - | - | -| USE_MQTT_AWS_IOT | - | - / - | - | - | - | - | -| USE_4K_RSA | - | - / - | - | - | - | - | -| USE_TELEGRAM | - | - / - | - | - | - | - | -| USE_KNX | - | - / x | x | - | - | - | -| USE_WEBSERVER | x | x / x | x | x | x | x | -| USE_WEBSEND_RESPONSE | - | - / - | - | - | - | - | -| USE_EMULATION_HUE | x | x / x | - | x | - | - | -| USE_EMULATION_WEMO | x | x / x | - | x | - | - | -| USE_DISCOVERY | - | - / - | - | - | - | - | -| WEBSERVER_ADVERTISE | - | x / - | x | - | - | x | -| MQTT_HOST_DISCOVERY | - | - / - | - | - | - | - | -| USE_TIMERS | x | x / x | x | x | x | x | -| USE_TIMERS_WEB | x | x / x | x | x | x | x | -| USE_SUNRISE | x | x / x | x | x | x | x | -| USE_RULES | x | x / x | x | x | x | x | -| USE_SCRIPT | - | - / - | - | - | - | - | -| USE_EXPRESSION | - | - / - | - | - | - | - | -| SUPPORT_IF_STATEMENT | - | - / - | - | - | - | - | -| USE_HOTPLUG | - | - / - | - | - | - | - | -| USE_PROMETHEUS | - | - / - | - | - | - | - | -| USE_PING | - | - / - | - | - | - | - | -| | | | | | | | -| Feature or Sensor | l | t | k | s | i | d | Remarks -| ROTARY_V1 | - | x / x | - | x | - | - | -| USE_SONOFF_RF | - | x / - | x | x | - | - | -| USE_RF_FLASH | - | x / - | x | x | - | - | -| USE_SONOFF_SC | - | x / - | x | x | - | - | -| USE_TUYA_MCU | x | x / - | x | x | - | x | -| USE_ARMTRONIX_DIMMERS | - | x / - | x | - | - | - | -| USE_PS_16_DZ | - | x / - | x | - | - | - | -| USE_SONOFF_IFAN | - | x / - | x | - | - | - | -| USE_BUZZER | - | x / x | x | x | - | - | -| USE_ARILUX_RF | - | x / - | x | - | - | - | -| USE_SHUTTER | - | x / x | x | - | - | - | -| USE_DEEPSLEEP | - | x / x | - | x | - | - | -| USE_EXS_DIMMER | - | x / - | x | - | - | - | -| USE_DEVICE_GROUPS | - | x / x | - | - | - | - | -| USE_PWM_DIMMER | - | x / - | x | - | - | - | -| USE_KEELOQ | - | - / - | - | - | - | - | -| USE_SONOFF_D1 | - | x / - | x | - | - | - | -| USE_SHELLY_DIMMER | - | x / - | - | - | - | - | -| USE_AC_ZERO_CROSS_DIMMER | - | x / x | x | x | x | x | -| | | | | | | | -| Feature or Sensor | l | t | k | s | i | d | Remarks -| USE_LIGHT | x | x / x | x | x | x | x | -| USE_WS2812 | - | x / 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_SM2335 | - | x / - | x | x | - | x | -| USE_BP5758D | - | x / - | x | x | - | x | -| USE_SONOFF_L1 | - | x / - | x | x | - | x | -| USE_ELECTRIQ_MOODL | - | x / - | x | x | - | x | -| | | | | | | | -| USE_ENERGY_SENSOR | x | x / x | x | x | - | - | -| USE_ENERGY_DUMMY | x | x / x | x | x | - | - | -| USE_PZEM004T | - | x / x | x | x | - | - | -| USE_PZEM_AC | - | x / x | x | x | - | - | -| USE_PZEM_DC | - | x / x | x | x | - | - | -| USE_MCP39F501 | x | x / - | x | x | - | - | -| USE_SDM72 | - | - / x | - | x | - | - | -| USE_SDM120 | - | - / x | - | x | - | - | -| USE_SDM230 | - | - / x | - | - | - | - | -| USE_SDM630 | - | - / x | - | x | - | - | -| USE_DDS2382 | - | - / x | - | x | - | - | -| USE_DDSU666 | - | - / x | - | x | - | - | -| USE_SOLAX_X1 | - | - / - | - | - | - | - | -| USE_LE01MR | - | - / - | - | - | - | - | -| USE_BL09XX | x | x / x | x | x | - | - | -| USE_TELEINFO | - | - / - | - | - | - | - | -| USE_IEM3000 | - | - / - | - | - | - | - | -| USE_WE517 | - | - / - | - | - | - | - | -| | | | | | | | -| USE_ADC_VCC | x | - / - | - | - | x | - | -| USE_COUNTER | - | x / x | x | x | - | x | -| USE_DS18x20 | - | x / x | x | x | - | x | -| USE_DHT | - | x / x | x | x | - | x | -| USE_MAX31855 | - | - / x | - | x | - | - | -| USE_MAX31865 | - | - / - | - | - | - | - | -| USE_THERMOSTAT | - | - / - | - | - | - | - | -| USE_LMT01 | - | - / x | - | x | - | - | -| | | | | | | | -| Feature or Sensor | l | t | k | s | i | d | Remarks -| USE_I2C | - | x / x | x | x | - | x | -| USE_SHT | - | - / x | - | x | - | - | -| USE_HTU | - | - / x | - | x | - | - | -| USE_BMP | - | - / x | - | x | - | - | -| USE_BME68X | - | - / x | - | x | - | - | -| USE_BH1750 | - | - / x | - | x | - | - | -| USE_VEML6070 | - | - / x | - | x | - | - | -| USE_ADS1115 | - | - / x | - | x | - | - | -| USE_INA219 | - | - / x | - | x | - | - | -| USE_INA226 | - | - / - | - | - | - | - | -| USE_SHT3X | - | - / x | - | x | - | - | -| USE_TSL2561 | - | - / - | - | - | - | - | -| USE_TSL2591 | - | - / - | - | - | - | - | -| USE_MGS | - | - / x | - | x | - | - | -| USE_SGP30 | - | - / x | - | x | - | - | -| USE_SI1145 | - | - / - | - | - | - | - | -| USE_LM75AD | - | - / x | - | x | - | - | -| USE_APDS9960 | - | - / - | - | - | - | - | -| USE_MCP230xx | - | - / - | - | - | - | - | -| USE_PCA9685 | - | - / - | - | - | - | - | -| USE_MPR121 | - | - / - | - | - | - | - | -| USE_CCS811 | - | - / - | - | x | - | - | -| USE_CCS811_V2 | - | - / x | - | - | - | - | -| USE_MPU6050 | - | - / - | - | - | - | - | -| USE_DS3231 | - | - / - | - | - | - | - | -| USE_MGC3130 | - | - / - | - | - | - | - | -| USE_MAX44009 | - | - / - | - | - | - | - | -| USE_SCD30 | - | - / x | - | x | - | - | -| USE_SCD40 | - | - / x | - | - | - | - | -| USE_SPS30 | - | - / - | - | - | - | - | -| USE_ADE7880 | - | - / - | - | - | - | - | -| USE_ADE7953 | - | x / x | x | x | - | x | -| USE_VL53L0X | - | - / x | - | x | - | - | -| USE_VL53L1X | - | - / - | - | - | - | - | -| USE_MLX90614 | - | - / - | - | - | - | - | -| USE_CHIRP | - | - / - | - | - | - | - | -| USE_PAJ7620 | - | - / - | - | - | - | - | -| USE_PCF8574 | - | - / - | - | - | - | - | -| | | | | | | | -| Feature or Sensor | l | t | k | s | i | d | Remarks -| USE_HIH6 | - | - / x | - | x | - | - | -| USE_DHT12 | - | - / x | - | x | - | - | -| USE_DS1624 | - | - / x | - | x | - | - | -| USE_AHT1x | - | - / - | - | - | - | - | -| USE_HDC1080 | - | - / - | - | - | - | - | -| USE_WEMOS_MOTOR_V1 | - | - / x | - | x | - | - | -| USE_IAQ | - | - / x | - | x | - | - | -| USE_AS3935 | - | - / x | - | x | - | - | -| USE_VEML6075 | - | - / - | - | - | - | - | -| USE_VEML7700 | - | - / - | - | - | - | - | -| USE_MCP9808 | - | - / - | - | - | - | - | -| USE_HP303B | - | - / - | - | - | - | - | -| USE_EZOCO2 | - | - / - | - | - | - | - | -| USE_EZODO | - | - / - | - | - | - | - | -| USE_EZOEC | - | - / - | - | - | - | - | -| USE_EZOFLO | - | - / - | - | - | - | - | -| USE_EZOHUM | - | - / - | - | - | - | - | -| USE_EZOO2 | - | - / - | - | - | - | - | -| USE_EZOORP | - | - / - | - | - | - | - | -| USE_EZOPH | - | - / - | - | - | - | - | -| USE_EZOPMP | - | - / - | - | - | - | - | -| USE_EZOPRS | - | - / - | - | - | - | - | -| USE_EZORGB | - | - / - | - | - | - | - | -| USE_EZORTD | - | - / - | - | - | - | - | -| USE_SEESAW_SOIL | - | - / - | - | - | - | - | -| USE_TOF10120 | - | - / - | - | - | - | - | -| USE_BM8563 | - | - / - | - | - | - | - | -| USE_AM2320 | - | - / - | - | - | - | - | +| Feature or Sensor | l | t | k | s | i | d | Remarks +|---------------------------|---|-------|---|---|---|---|-------- +| MY_LANGUAGE en_GB | x | x / x | x | x | x | x | +| USE_IMPROV | x | x / x | x | x | x | x | +| USE_UFILESYS | - | - / x | - | - | - | - | +| USE_ARDUINO_OTA | - | - / - | - | - | - | - | +| USE_DOMOTICZ | - | x / x | x | x | x | - | +| USE_HOME_ASSISTANT | - | - / - | - | - | - | - | +| USE_TASMOTA_DISCOVERY | x | x / x | x | x | x | x | +| USE_MQTT_TLS* | - | - / x | - | - | - | - | +| USE_MQTT_AWS_IOT | - | - / - | - | - | - | - | +| USE_4K_RSA | - | - / - | - | - | - | - | +| USE_TELEGRAM | - | - / - | - | - | - | - | +| USE_KNX | - | - / x | x | - | - | - | +| USE_WEBSERVER | x | x / x | x | x | x | x | +| USE_WEBSEND_RESPONSE | - | - / - | - | - | - | - | +| USE_EMULATION_HUE | x | x / x | - | x | - | - | +| USE_EMULATION_WEMO | x | x / x | - | x | - | - | +| USE_DISCOVERY | - | - / - | - | - | - | - | +| WEBSERVER_ADVERTISE | - | x / - | x | - | - | x | +| MQTT_HOST_DISCOVERY | - | - / - | - | - | - | - | +| USE_TIMERS | x | x / x | x | x | x | x | +| USE_TIMERS_WEB | x | x / x | x | x | x | x | +| USE_SUNRISE | x | x / x | x | x | x | x | +| USE_RULES | x | x / x | x | x | x | x | +| USE_SCRIPT | - | - / - | - | - | - | - | +| USE_EXPRESSION | - | - / - | - | - | - | - | +| SUPPORT_IF_STATEMENT | - | - / - | - | - | - | - | +| USE_HOTPLUG | - | - / - | - | - | - | - | +| USE_PROMETHEUS | - | - / - | - | - | - | - | +| USE_PING | - | - / - | - | - | - | - | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| ROTARY_V1 | - | x / x | - | x | - | - | +| USE_SONOFF_RF | - | x / - | x | x | - | - | +| USE_RF_FLASH | - | x / - | x | x | - | - | +| USE_SONOFF_SC | - | x / - | x | x | - | - | +| USE_TUYA_MCU | x | x / - | x | x | - | x | +| USE_ARMTRONIX_DIMMERS | - | x / - | x | - | - | - | +| USE_PS_16_DZ | - | x / - | x | - | - | - | +| USE_SONOFF_IFAN | - | x / - | x | - | - | - | +| USE_BUZZER | - | x / x | x | x | - | - | +| USE_ARILUX_RF | - | x / - | x | - | - | - | +| USE_SHUTTER | - | x / x | x | - | - | - | +| USE_DEEPSLEEP | - | x / x | - | x | - | - | +| USE_EXS_DIMMER | - | x / - | x | - | - | - | +| USE_DEVICE_GROUPS | - | x / x | - | - | - | - | +| USE_PWM_DIMMER | - | x / - | x | - | - | - | +| USE_KEELOQ | - | - / - | - | - | - | - | +| USE_SONOFF_D1 | - | x / - | x | - | - | - | +| USE_SHELLY_DIMMER | - | x / - | - | - | - | - | +| USE_AC_ZERO_CROSS_DIMMER | - | x / x | x | x | x | x | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| USE_LIGHT | x | x / x | x | x | x | x | +| USE_WS2812 | - | x / 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_SM2335 | - | x / - | x | x | - | x | +| USE_BP5758D | - | x / - | x | x | - | x | +| USE_SONOFF_L1 | - | x / - | x | x | - | x | +| USE_ELECTRIQ_MOODL | - | x / - | x | x | - | x | +| | | | | | | | +| USE_ENERGY_SENSOR | - | x / x | x | x | - | - | +| USE_ENERGY_DUMMY | - | x / x | x | x | - | - | +| USE_PZEM004T | - | x / x | x | x | - | - | +| USE_PZEM_AC | - | x / x | x | x | - | - | +| USE_PZEM_DC | - | x / x | x | x | - | - | +| USE_MCP39F501 | - | x / - | x | x | - | - | +| USE_SDM72 | - | - / x | - | x | - | - | +| USE_SDM120 | - | - / x | - | x | - | - | +| USE_SDM230 | - | - / x | - | - | - | - | +| USE_SDM630 | - | - / x | - | x | - | - | +| USE_DDS2382 | - | - / x | - | x | - | - | +| USE_DDSU666 | - | - / x | - | x | - | - | +| USE_SOLAX_X1 | - | - / - | - | - | - | - | +| USE_LE01MR | - | - / - | - | - | - | - | +| USE_BL09XX | - | x / x | x | x | - | - | +| USE_TELEINFO | - | - / - | - | - | - | - | +| USE_IEM3000 | - | - / - | - | - | - | - | +| USE_WE517 | - | - / - | - | - | - | - | +| | | | | | | | +| USE_ADC_VCC | x | - / - | - | - | x | - | +| USE_COUNTER | - | x / x | x | x | - | x | +| USE_DS18x20 | - | x / x | x | x | - | x | +| USE_DHT | - | x / x | x | x | - | x | +| USE_MAX31855 | - | - / x | - | x | - | - | +| USE_MAX31865 | - | - / - | - | - | - | - | +| USE_THERMOSTAT | - | - / - | - | - | - | - | +| USE_LMT01 | - | - / x | - | x | - | - | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| USE_I2C | - | x / x | x | x | - | x | +| USE_SHT | - | - / x | - | x | - | - | +| USE_HTU | - | - / x | - | x | - | - | +| USE_BMP | - | - / x | - | x | - | - | +| USE_BME68X | - | - / x | - | x | - | - | +| USE_BH1750 | - | - / x | - | x | - | - | +| USE_VEML6070 | - | - / x | - | x | - | - | +| USE_ADS1115 | - | - / x | - | x | - | - | +| USE_INA219 | - | - / x | - | x | - | - | +| USE_INA226 | - | - / - | - | - | - | - | +| USE_SHT3X | - | - / x | - | x | - | - | +| USE_TSL2561 | - | - / - | - | - | - | - | +| USE_TSL2591 | - | - / - | - | - | - | - | +| USE_MGS | - | - / x | - | x | - | - | +| USE_SGP30 | - | - / x | - | x | - | - | +| USE_SGP40 | - | - / x | - | x | - | - | +| USE_SI1145 | - | - / - | - | - | - | - | +| USE_LM75AD | - | - / x | - | x | - | - | +| USE_APDS9960 | - | - / - | - | - | - | - | +| USE_MCP230xx | - | - / - | - | - | - | - | +| USE_PCA9685 | - | - / - | - | - | - | - | +| USE_MPR121 | - | - / - | - | - | - | - | +| USE_CCS811 | - | - / - | - | x | - | - | +| USE_CCS811_V2 | - | - / x | - | - | - | - | +| USE_MPU6050 | - | - / - | - | - | - | - | +| USE_DS3231 | - | - / - | - | - | - | - | +| USE_MGC3130 | - | - / - | - | - | - | - | +| USE_MAX44009 | - | - / - | - | - | - | - | +| USE_SCD30 | - | - / x | - | x | - | - | +| USE_SCD40 | - | - / x | - | - | - | - | +| USE_SPS30 | - | - / - | - | - | - | - | +| USE_ADE7880 | - | - / - | - | - | - | - | +| USE_ADE7953 | - | x / x | x | x | - | x | +| USE_VL53L0X | - | - / x | - | x | - | - | +| USE_VL53L1X | - | - / - | - | - | - | - | +| USE_MLX90614 | - | - / - | - | - | - | - | +| USE_CHIRP | - | - / - | - | - | - | - | +| USE_PAJ7620 | - | - / - | - | - | - | - | +| USE_PCF8574 | - | - / - | - | - | - | - | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| USE_HIH6 | - | - / x | - | x | - | - | +| USE_DHT12 | - | - / x | - | x | - | - | +| USE_DS1624 | - | - / x | - | x | - | - | +| USE_AHT1x | - | - / - | - | - | - | - | +| USE_HDC1080 | - | - / - | - | - | - | - | +| USE_WEMOS_MOTOR_V1 | - | - / x | - | x | - | - | +| USE_IAQ | - | - / x | - | x | - | - | +| USE_AS3935 | - | - / x | - | x | - | - | +| USE_VEML6075 | - | - / - | - | - | - | - | +| USE_VEML7700 | - | - / - | - | - | - | - | +| USE_MCP9808 | - | - / - | - | - | - | - | +| USE_MLX90640 | - | - / - | - | - | - | - | +| USE_HP303B | - | - / - | - | - | - | - | +| USE_EZOCO2 | - | - / - | - | - | - | - | +| USE_EZODO | - | - / - | - | - | - | - | +| USE_EZOEC | - | - / - | - | - | - | - | +| USE_EZOFLO | - | - / - | - | - | - | - | +| USE_EZOHUM | - | - / - | - | - | - | - | +| USE_EZOO2 | - | - / - | - | - | - | - | +| USE_EZOORP | - | - / - | - | - | - | - | +| USE_EZOPH | - | - / - | - | - | - | - | +| USE_EZOPMP | - | - / - | - | - | - | - | +| USE_EZOPRS | - | - / - | - | - | - | - | +| USE_EZORGB | - | - / - | - | - | - | - | +| USE_EZORTD | - | - / - | - | - | - | - | +| USE_SEESAW_SOIL | - | - / - | - | - | - | - | +| USE_TOF10120 | - | - / - | - | - | - | - | +| USE_BM8563 | - | - / - | - | - | - | - | +| USE_AM2320 | - | - / - | - | - | - | - | | USE_T67XX | - | - / - | - | - | - | - | | USE_HM330X | - | - / - | - | - | - | - | | USE_HDC2010 | - | - / - | - | - | - | - | | USE_PCF85363 | - | - / - | - | - | - | - | | USE_DS3502 | - | - / - | - | - | - | - | | USE_HYT | - | - / - | - | - | - | - | +| USE_LUXV30B | - | - / - | - | - | - | - | | | | | | | | | | Feature or Sensor | l | t | k | s | i | d | Remarks | USE_SPI | - | - / - | - | - | - | x | @@ -198,7 +201,7 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_MIEL_HVAC | - | - / - | - | - | - | - | | USE_PROJECTOR_CTRL | - | - / - | - | - | - | - | | USE_AS608 | - | - / - | - | - | - | - | -| USE_TCP_BRIDGE | - | - / - | - | - | - | - | zbbridge +| USE_TCP_BRIDGE | - | - / - | - | - | - | - | zbbridge / zbbrdgpro | | | | | | | | | USE_NRF24 | - | - / - | - | - | - | - | | USE_MIBLE | - | - / - | - | - | - | - | @@ -252,4 +255,4 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_TTGO_WATCH | | / - | | | | | | USE_SONOFF_SPM | | / x | | | | | -* USE_MQTT_TLS is enabled by default in every ESP32 variants \ No newline at end of file +* USE_MQTT_TLS is enabled by default in every ESP32 variants diff --git a/CHANGELOG.md b/CHANGELOG.md index 968faedbd..e768220ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,105 @@ All notable changes to this project will be documented in this file. ## [12.1.0] 20220818 - Release Patricia +## [12.1.1.6] +### Added +- Command ``WcClock 10..200`` set webcam clock in MHz. Default is 20 + +### Changed + +### Fixed + +### Removed + +## [12.1.1.5] 20221013 +### Added +- Command ``Sunrise 0..3`` to select sunrise dawn angle between Normal, Civil, Nautical or Astronomical (#16795) + +## [12.1.1.4] 20221012 +### Added +- Support for Shelly Plus 2PM using template ``{"NAME":"Shelly Plus 2PM PCB v0.1.9","GPIO":[320,0,0,0,32,192,0,0,225,224,0,0,0,0,193,0,0,0,0,0,0,608,640,3458,0,0,0,0,0,9472,0,4736,0,0,0,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350"}`` +- Zigbee Alexa/Hue emulation, support multiple switches on separate endpoints (#16718) +- Support for QMC5883L magnetic induction sensor by Helge Scheunemann (#16714) +- LVGL/HASPmota add tiny "pixel perfect" fonts for small screens (#16758) +- HASPmota support for TTF fonts (#16759) +- Support for Modbus Energy Monitoring devices using a rule file. See ``xnrg_29_modbus.ino`` for more information + +### Changed +- ESP32 LVGL library from v8.3.0 to v8.3.2 +- Increase serial console fixed input buffer size from 520 to 800 +- Swap Shelly EM internal channels A and B to match P1 and P2 (#16486) + +## [12.1.1.3] 20221003 +### Added +- ESP32-S2 and ESP32-S3 touch button support +- Zigbee friendly names per endpoint + +### Fixed +- ESP32 touch button multi-press and hold detection (#16596) + +## [12.1.1.2] 20220927 +### Added +- Berry has persistent MQTT subscriptions: auto-subscribe at (re)connection +- Berry automated solidification of code +- Support of optional file calib.dat on ADE7953 based energy monitors like Shelly EM (#16486) +- Command ``SetOption46 0..255`` to add 0..255 * 10 milliseconds power on delay before initializing I/O (#15438) +- Zigbee support for decimal Voltage/Current/Power on power metering plugs +- Command ``UrlFetch `` to download a file to filesystem +- Zigbee basic support for Green Power +- Berry add ``introspect.setmodule(name:string, value:any) -> nil`` + +### Changed +- ESP32 Increase number of button GPIOs from 8 to 28 (#16518) +- IRremoteESP8266 library from v2.8.2 to v2.8.3 +- Tasmota Core32 from 2.0.4.1 to 2.0.5 +- IRremoteESP8266 library from v2.8.3 to v2.8.4 +- Zigbee report unprocessed attributes +- Platformio one Platform for all Tasmota frameworks Core32 2.0.5 (#16644) + +## [12.1.1.1] 20220910 +### Added +- Support for SGP40 gas and air quality sensor (#16341) +- Support for Modbus writing using ModbusBridge by JeroenSt (#16351) +- Support for Ethernet in ESP32 safeboot firmware (#16388) +- Flowrate meter flow amount/duration, show values in table format (#16385) +- Zigbee prepare for Green Power support (#16407) +- Command ``SetOption146 1`` to enable display of ESP32 internal temperature +- Support for DFRobot SEN0390 V30B ambient light sensor (#16105) +- Command ``DspSpeed 2..127`` to control message rotation speed on display of POWR3xxD and THR3xxD +- Command ``DspLine<1|2> ,,,,...`` to select message(s) on display of POWR3xxD and THR3xxD + +### Changed +- TasmotaModbus library from v3.5.0 to v3.6.0 (#16351) +- Button debouncing V3 by adopting switch debounce code (#16339) +- Thermostat max allowed temperature from 100 to 200C (#16363) +- Using command ``SerialBuffer`` raise max allowed buffer size to 2048 characters (#16374) + +### Fixed +- Removed whitespace from JSON values with no decimals (#16365) + +## [12.1.0.1] 20220825 +### Added +- Zigbee device plugin mechanism with commands ``ZbLoad``, ``ZbUnload`` and ``ZbLoadDump`` (#16252) +- ESP32-S3 support for internal temperature sensor +- Command ``StatusRetain`` (#11109) + +### Changed +- ESP32 NimBLE library from v1.3.6 to v1.4.0 + +## [Released] + +## [12.1.1] 20220825 +- Release Patricia + +### Fixed +- RTC not detected when lights are present (#16242) +- DNS lookup for .local domains (#16273) +- Button response delay regression from v12.0.2.4 (#16319) +- Lost module name in GUI regression from v12.0.2.4 - 20220803 (#16324) + +## [12.1.0] 20220818 +- Release Patricia + ## [12.0.2.4] 20220818 ### Added - Command ``SetOption45 1..250`` to change default bistable latching relay pulse length of 40 milliseconds diff --git a/I2CDEVICES.md b/I2CDEVICES.md index 59bc03065..d3b2cd418 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -6,100 +6,104 @@ Using command ``I2cDriver`` individual drivers can be enabled or disabled at run ## Supported I2C devices The following table lists the supported I2C devices -Index | Define | Driver | Device | Address(es) | Description -------|---------------------|---------|----------|-------------|----------------------------------------------- - 1 | USE_PCA9685 | xdrv_15 | PCA9685 | 0x40 - 0x47 | 16-channel 12-bit pwm driver - 2 | USE_PCF8574 | xdrv_28 | PCF8574 | 0x20 - 0x26 | 8-bit I/O expander - 2 | USE_PCF8574 | xdrv_28 | PCF8574A | 0x39 - 0x3F | 8-bit I/O expander - 3 | USE_DISPLAY_LCD | xdsp_01 | | 0x27, 0x3F | LCD display - 4 | USE_DISPLAY_SSD1306 | xdsp_02 | SSD1306 | 0x3C - 0x3D | Oled display - 5 | USE_DISPLAY_MATRIX | xdsp_03 | HT16K33 | 0x70 - 0x77 | 8x8 led matrix - 6 | USE_DISPLAY_SH1106 | xdsp_07 | SH1106 | 0x3C - 0x3D | Oled display - 7 | USE_ADE7953 | xnrg_07 | ADE7953 | 0x38 | Energy monitor - 8 | USE_SHT | xsns_07 | SHT1X | Any | Temperature and Humidity sensor - 9 | USE_HTU | xsns_08 | HTU21 | 0x40 | Temperature and Humidity sensor - 9 | USE_HTU | xsns_08 | SI7013 | 0x40 | Temperature and Humidity sensor - 9 | USE_HTU | xsns_08 | SI7020 | 0x40 | Temperature and Humidity sensor - 9 | USE_HTU | xsns_08 | SI7021 | 0x40 | Temperature and Humidity sensor - 10 | USE_BMP | xsns_09 | BMP085 | 0x76 - 0x77 | Pressure and temperature sensor - 10 | USE_BMP | xsns_09 | BMP180 | 0x76 - 0x77 | Pressure and temperature sensor - 10 | USE_BMP | xsns_09 | BMP280 | 0x76 - 0x77 | Pressure and temperature sensor - 10 | USE_BMP | xsns_09 | BME280 | 0x76 - 0x77 | Pressure, temperature and humidity sensor - 10 | USE_BMP | xsns_09 | BME680 | 0x76 - 0x77 | Pressure, temperature, humidity and gas sensor - 11 | USE_BH1750 | xsns_10 | BH1750 | 0x23, 0x5C | Ambient light intensity sensor - 12 | USE_VEML6070 | xsns_11 | VEML6070 | 0x38 - 0x39 | Ultra violet light intensity sensor - 13 | USE_ADS1115 | xsns_12 | ADS1115 | 0x48 - 0x4B | 4-channel 16-bit A/D converter - 14 | USE_INA219 | xsns_13 | INA219 | 0x40 - 0x41, 0x44 - 0x45 | Low voltage current sensor - 15 | USE_SHT3X | xsns_14 | SHT3X | 0x44 - 0x45 | Temperature and Humidity sensor - 15 | USE_SHT3X | xsns_14 | SHT4X | 0x44 - 0x45 | Temperature and Humidity sensor - 15 | USE_SHT3X | xsns_14 | SHTCX | 0x70 | Temperature and Humidity sensor - 16 | USE_TSL2561 | xsns_16 | TSL2561 | 0x29, 0x39, 0x49 | Light intensity sensor - 17 | USE_MGS | xsns_19 | Grove | 0x04 | Multichannel gas sensor - 18 | USE_SGP30 | xsns_21 | SGP30 | 0x58 | Gas (TVOC) and air quality sensor - 19 | USE_SI1145 | xsns_24 | SI1145 | 0x60 | Ultra violet index and light sensor - 19 | USE_SI1145 | xsns_24 | SI1146 | 0x60 | Ultra violet index and light sensor - 19 | USE_SI1145 | xsns_24 | SI1147 | 0x60 | Ultra violet index and light sensor - 20 | USE_LM75AD | xsns_26 | LM75AD | 0x48 - 0x4F | Temperature sensor - 21 | USE_APDS9960 | xsns_27 | APDS9960 | 0x39 | Proximity ambient light RGB and gesture sensor - 22 | USE_MCP230xx | xsns_29 | MCP23008 | 0x20 - 0x26 | 8-bit I/O expander - 22 | USE_MCP230xx | xsns_29 | MCP23017 | 0x20 - 0x26 | 16-bit I/O expander - 23 | USE_MPR121 | xsns_30 | MPR121 | 0x5A - 0x5D | Proximity capacitive touch sensor - 24 | USE_CCS811 | xsns_31 | CCS811 | 0x5A | Gas (TVOC) and air quality sensor - 25 | USE_MPU6050 | xsns_32 | MPU6050 | 0x68 - 0x69 | 3-axis gyroscope and temperature sensor - 26 | USE_DS3231 | xsns_33 | DS3231 | 0x68 | Real time clock - 27 | USE_MGC3130 | xsns_36 | MGC3130 | 0x42 | Electric field sensor - 28 | USE_MAX44009 | xsns_41 | MAX44009 | 0x4A - 0x4B | Ambient light intensity sensor - 29 | USE_SCD30 | xsns_42 | SCD30 | 0x61 | CO2 sensor - 30 | USE_SPS30 | xsns_44 | SPS30 | 0x69 | Particle sensor - 31 | USE_VL53L0X | xsns_45 | VL53L0X | 0x29 | Time-of-flight (ToF) distance sensor - 32 | USE_MLX90614 | xsns_46 | MLX90614 | 0x5A | Infra red temperature sensor - 33 | USE_CHIRP | xsns_48 | CHIRP | 0x20 | Soil moisture sensor - 34 | USE_PAJ7620 | xsns_50 | PAJ7620 | 0x73 | Gesture sensor - 35 | USE_INA226 | xsns_54 | INA226 | 0x40 - 0x41, 0x44 - 0x45 | Low voltage current sensor - 36 | USE_HIH6 | xsns_55 | HIH6130 | 0x27 | Temperature and Humidity sensor - 37 | USE_24C256 | xdrv_10 | 24C256 | 0x50 | Scripter EEPROM storage - 38 | USE_DISPLAY_ILI9488 | xdsp_08 | FT6236 | 0x38 | Touch panel controller - 39 | USE_DISPLAY_RA8876 | xdsp_10 | FT5316 | 0x38 | Touch panel controller - 40 | USE_TSL2591 | xsns_57 | TLS2591 | 0x29 | Light intensity sensor - 41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor - 42 | USE_DS1624 | xsns_59 | DS1621 | 0x48 - 0x4F | Temperature sensor - 42 | USE_DS1624 | xsns_59 | DS1624 | 0x48 - 0x4F | Temperature sensor - 43 | USE_AHT1x | xsns_63 | AHT10/15 | 0x38 - 0x39 | Temperature and humidity sensor - 43 | USE_AHT2x | xsns_63 | AHT20 | 0x38 | Temperature and humidity sensor - 43 | USE_AHT2x | xsns_63 | AM2301B | 0x38 | Temperature and humidity sensor - 44 | USE_WEMOS_MOTOR_V1 | xdrv_34 | | 0x2D - 0x30 | WEMOS motor shield v1.0.0 (6612FNG) - 45 | USE_HDC1080 | xsns_65 | HDC1080 | 0x40 | Temperature and Humidity sensor - 46 | USE_IAQ | xsns_66 | IAQ | 0x5a | Air quality sensor - 47 | USE_DISPLAY_SEVENSEG| xdsp_11 | HT16K33 | 0x70 - 0x77 | Seven segment LED - 48 | USE_AS3935 | xsns_67 | AS3935 | 0x03 | Franklin Lightning Sensor - 49 | USE_VEML6075 | xsns_70 | VEML6075 | 0x10 | UVA/UVB/UVINDEX Sensor - 50 | USE_VEML7700 | xsns_71 | VEML7700 | 0x10 | Ambient light intensity sensor - 51 | USE_MCP9808 | xsns_72 | MCP9808 | 0x18 - 0x1F | Temperature sensor - 52 | USE_HP303B | xsns_73 | HP303B | 0x76 - 0x77 | Pressure and temperature sensor - 53 | USE_MLX90640 | xdrv_43 | MLX90640 | 0x33 | IR array temperature sensor - 54 | USE_VL53L1X | xsns_77 | VL53L1X | 0x29 | Time-of-flight (ToF) distance sensor - 55 | USE_EZOPH | xsns_78 | EZOPH | 0x61 - 0x70 | pH sensor - 55 | USE_EZOORP | xsns_78 | EZOORP | 0x61 - 0x70 | ORP sensor - 55 | USE_EZORTD | xsns_78 | EZORTD | 0x61 - 0x70 | Temperature sensor - 55 | USE_EZOHUM | xsns_78 | EZOHUM | 0x61 - 0x70 | Humidity sensor - 55 | USE_EZOEC | xsns_78 | EZOEC | 0x61 - 0x70 | Electric conductivity sensor - 55 | USE_EZOCO2 | xsns_78 | EZOCO2 | 0x61 - 0x70 | CO2 sensor - 55 | USE_EZOO2 | xsns_78 | EZOO2 | 0x61 - 0x70 | O2 sensor - 55 | USE_EZOPRS | xsns_78 | EZOPRS | 0x61 - 0x70 | Pressure sensor - 55 | USE_EZOFLO | xsns_78 | EZOFLO | 0x61 - 0x70 | Flow meter sensor - 55 | USE_EZODO | xsns_78 | EZODO | 0x61 - 0x70 | Disolved Oxygen sensor - 55 | USE_EZORGB | xsns_78 | EZORGB | 0x61 - 0x70 | Color sensor - 55 | USE_EZOPMP | xsns_78 | EZOPMP | 0x61 - 0x70 | Peristaltic Pump - 56 | USE_SEESAW_SOIL | xsns_81 | SEESOIL | 0x36 - 0x39 | Adafruit seesaw soil moisture sensor - 57 | USE_TOF10120 | xsns_84 | TOF10120 | 0x52 | Time-of-flight (ToF) distance sensor - 58 | USE_MPU_ACCEL | xsns_85 | MPU_ACCEL| 0x68 | MPU6886/MPU9250 6-axis MotionTracking sensor from M5Stack - 59 | USE_BM8563 | xdrv_56 | BM8563 | 0x51 | BM8563 RTC from M5Stack - 60 | USE_AM2320 | xsns_88 | AM2320 | 0x5C | Temperature and Humidity sensor - 61 | USE_T67XX | xsns_89 | T67XX | 0x15 | CO2 sensor - 62 | USE_SCD40 | xsns_92 | SCD40 | 0x62 | CO2 sensor Sensirion SCD40/SCD41 - 63 | USE_HM330X | xsns_93 | HM330X | 0x40 | Particule sensor - 64 | USE_HDC2010 | xsns_94 | HDC2010 | 0x40 | Temperature and Humidity sensor - 65 | USE_ADE7880 | xnrg_23 | ADE7880 | 0x38 | Energy monitor - 66 | USE_PCF85363 | xsns_99 | PCF85363 | 0x51 | Real time clock - 67 | USE_DS3502 | xdrv_61 | DS3502 | 0x28 - 0x2B | Digital potentiometer - 68 | USE_HYT | xsns_97 | HYTxxx | 0x28 | Temperature and Humidity sensor +Index | Define | Driver | Device | Address(es) | Description +------|---------------------|----------|----------|-------------|----------------------------------------------- + 1 | USE_PCA9685 | xdrv_15 | PCA9685 | 0x40 - 0x47 | 16-channel 12-bit pwm driver + 2 | USE_PCF8574 | xdrv_28 | PCF8574 | 0x20 - 0x26 | 8-bit I/O expander + 2 | USE_PCF8574 | xdrv_28 | PCF8574A | 0x39 - 0x3F | 8-bit I/O expander + 3 | USE_DISPLAY_LCD | xdsp_01 | | 0x27, 0x3F | LCD display + 4 | USE_DISPLAY_SSD1306 | xdsp_02 | SSD1306 | 0x3C - 0x3D | Oled display + 5 | USE_DISPLAY_MATRIX | xdsp_03 | HT16K33 | 0x70 - 0x77 | 8x8 led matrix + 6 | USE_DISPLAY_SH1106 | xdsp_07 | SH1106 | 0x3C - 0x3D | Oled display + 7 | USE_ADE7953 | xnrg_07 | ADE7953 | 0x38 | Energy monitor + 8 | USE_SHT | xsns_07 | SHT1X | Any | Temperature and Humidity sensor + 9 | USE_HTU | xsns_08 | HTU21 | 0x40 | Temperature and Humidity sensor + 9 | USE_HTU | xsns_08 | SI7013 | 0x40 | Temperature and Humidity sensor + 9 | USE_HTU | xsns_08 | SI7020 | 0x40 | Temperature and Humidity sensor + 9 | USE_HTU | xsns_08 | SI7021 | 0x40 | Temperature and Humidity sensor + 10 | USE_BMP | xsns_09 | BMP085 | 0x76 - 0x77 | Pressure and temperature sensor + 10 | USE_BMP | xsns_09 | BMP180 | 0x76 - 0x77 | Pressure and temperature sensor + 10 | USE_BMP | xsns_09 | BMP280 | 0x76 - 0x77 | Pressure and temperature sensor + 10 | USE_BMP | xsns_09 | BME280 | 0x76 - 0x77 | Pressure, temperature and humidity sensor + 10 | USE_BMP | xsns_09 | BME680 | 0x76 - 0x77 | Pressure, temperature, humidity and gas sensor + 11 | USE_BH1750 | xsns_10 | BH1750 | 0x23, 0x5C | Ambient light intensity sensor + 12 | USE_VEML6070 | xsns_11 | VEML6070 | 0x38 - 0x39 | Ultra violet light intensity sensor + 13 | USE_ADS1115 | xsns_12 | ADS1115 | 0x48 - 0x4B | 4-channel 16-bit A/D converter + 14 | USE_INA219 | xsns_13 | INA219 | 0x40 - 0x41, 0x44 - 0x45 | Low voltage current sensor + 15 | USE_SHT3X | xsns_14 | SHT3X | 0x44 - 0x45 | Temperature and Humidity sensor + 15 | USE_SHT3X | xsns_14 | SHT4X | 0x44 - 0x45 | Temperature and Humidity sensor + 15 | USE_SHT3X | xsns_14 | SHTCX | 0x70 | Temperature and Humidity sensor + 16 | USE_TSL2561 | xsns_16 | TSL2561 | 0x29, 0x39, 0x49 | Light intensity sensor + 17 | USE_MGS | xsns_19 | Grove | 0x04 | Multichannel gas sensor + 18 | USE_SGP30 | xsns_21 | SGP30 | 0x58 | Gas (TVOC) and air quality sensor + 19 | USE_SI1145 | xsns_24 | SI1145 | 0x60 | Ultra violet index and light sensor + 19 | USE_SI1145 | xsns_24 | SI1146 | 0x60 | Ultra violet index and light sensor + 19 | USE_SI1145 | xsns_24 | SI1147 | 0x60 | Ultra violet index and light sensor + 20 | USE_LM75AD | xsns_26 | LM75AD | 0x48 - 0x4F | Temperature sensor + 21 | USE_APDS9960 | xsns_27 | APDS9960 | 0x39 | Proximity ambient light RGB and gesture sensor + 22 | USE_MCP230xx | xsns_29 | MCP23008 | 0x20 - 0x26 | 8-bit I/O expander + 22 | USE_MCP230xx | xsns_29 | MCP23017 | 0x20 - 0x26 | 16-bit I/O expander + 23 | USE_MPR121 | xsns_30 | MPR121 | 0x5A - 0x5D | Proximity capacitive touch sensor + 24 | USE_CCS811 | xsns_31 | CCS811 | 0x5A | Gas (TVOC) and air quality sensor + 25 | USE_MPU6050 | xsns_32 | MPU6050 | 0x68 - 0x69 | 3-axis gyroscope and temperature sensor + 26 | USE_DS3231 | xsns_33 | DS3231 | 0x68 | Real time clock + 27 | USE_MGC3130 | xsns_36 | MGC3130 | 0x42 | Electric field sensor + 28 | USE_MAX44009 | xsns_41 | MAX44009 | 0x4A - 0x4B | Ambient light intensity sensor + 29 | USE_SCD30 | xsns_42 | SCD30 | 0x61 | CO2 sensor + 30 | USE_SPS30 | xsns_44 | SPS30 | 0x69 | Particle sensor + 31 | USE_VL53L0X | xsns_45 | VL53L0X | 0x29 | Time-of-flight (ToF) distance sensor + 32 | USE_MLX90614 | xsns_46 | MLX90614 | 0x5A | Infra red temperature sensor + 33 | USE_CHIRP | xsns_48 | CHIRP | 0x20 | Soil moisture sensor + 34 | USE_PAJ7620 | xsns_50 | PAJ7620 | 0x73 | Gesture sensor + 35 | USE_INA226 | xsns_54 | INA226 | 0x40 - 0x41, 0x44 - 0x45 | Low voltage current sensor + 36 | USE_HIH6 | xsns_55 | HIH6130 | 0x27 | Temperature and Humidity sensor + 37 | USE_24C256 | xdrv_10 | 24C256 | 0x50 | Scripter EEPROM storage + 38 | USE_DISPLAY_ILI9488 | xdsp_08 | FT6236 | 0x38 | Touch panel controller + 39 | USE_DISPLAY_RA8876 | xdsp_10 | FT5316 | 0x38 | Touch panel controller + 40 | USE_TSL2591 | xsns_57 | TLS2591 | 0x29 | Light intensity sensor + 41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor + 42 | USE_DS1624 | xsns_59 | DS1621 | 0x48 - 0x4F | Temperature sensor + 42 | USE_DS1624 | xsns_59 | DS1624 | 0x48 - 0x4F | Temperature sensor + 43 | USE_AHT1x | xsns_63 | AHT10/15 | 0x38 - 0x39 | Temperature and humidity sensor + 43 | USE_AHT2x | xsns_63 | AHT20 | 0x38 | Temperature and humidity sensor + 43 | USE_AHT2x | xsns_63 | AM2301B | 0x38 | Temperature and humidity sensor + 44 | USE_WEMOS_MOTOR_V1 | xdrv_34 | | 0x2D - 0x30 | WEMOS motor shield v1.0.0 (6612FNG) + 45 | USE_HDC1080 | xsns_65 | HDC1080 | 0x40 | Temperature and Humidity sensor + 46 | USE_IAQ | xsns_66 | IAQ | 0x5a | Air quality sensor + 47 | USE_DISPLAY_SEVENSEG| xdsp_11 | HT16K33 | 0x70 - 0x77 | Seven segment LED + 48 | USE_AS3935 | xsns_67 | AS3935 | 0x03 | Franklin Lightning Sensor + 49 | USE_VEML6075 | xsns_70 | VEML6075 | 0x10 | UVA/UVB/UVINDEX Sensor + 50 | USE_VEML7700 | xsns_71 | VEML7700 | 0x10 | Ambient light intensity sensor + 51 | USE_MCP9808 | xsns_72 | MCP9808 | 0x18 - 0x1F | Temperature sensor + 52 | USE_HP303B | xsns_73 | HP303B | 0x76 - 0x77 | Pressure and temperature sensor + 53 | USE_MLX90640 | xdrv_43 | MLX90640 | 0x33 | IR array temperature sensor + 54 | USE_VL53L1X | xsns_77 | VL53L1X | 0x29 | Time-of-flight (ToF) distance sensor + 55 | USE_EZOPH | xsns_78 | EZOPH | 0x61 - 0x70 | pH sensor + 55 | USE_EZOORP | xsns_78 | EZOORP | 0x61 - 0x70 | ORP sensor + 55 | USE_EZORTD | xsns_78 | EZORTD | 0x61 - 0x70 | Temperature sensor + 55 | USE_EZOHUM | xsns_78 | EZOHUM | 0x61 - 0x70 | Humidity sensor + 55 | USE_EZOEC | xsns_78 | EZOEC | 0x61 - 0x70 | Electric conductivity sensor + 55 | USE_EZOCO2 | xsns_78 | EZOCO2 | 0x61 - 0x70 | CO2 sensor + 55 | USE_EZOO2 | xsns_78 | EZOO2 | 0x61 - 0x70 | O2 sensor + 55 | USE_EZOPRS | xsns_78 | EZOPRS | 0x61 - 0x70 | Pressure sensor + 55 | USE_EZOFLO | xsns_78 | EZOFLO | 0x61 - 0x70 | Flow meter sensor + 55 | USE_EZODO | xsns_78 | EZODO | 0x61 - 0x70 | Disolved Oxygen sensor + 55 | USE_EZORGB | xsns_78 | EZORGB | 0x61 - 0x70 | Color sensor + 55 | USE_EZOPMP | xsns_78 | EZOPMP | 0x61 - 0x70 | Peristaltic Pump + 56 | USE_SEESAW_SOIL | xsns_81 | SEESOIL | 0x36 - 0x39 | Adafruit seesaw soil moisture sensor + 57 | USE_TOF10120 | xsns_84 | TOF10120 | 0x52 | Time-of-flight (ToF) distance sensor + 58 | USE_MPU_ACCEL | xsns_85 | MPU_ACCEL| 0x68 | MPU6886/MPU9250 6-axis MotionTracking sensor from M5Stac k + 59 | USE_BM8563 | xdrv_56 | BM8563 | 0x51 | BM8563 RTC from M5Stack + 60 | USE_AM2320 | xsns_88 | AM2320 | 0x5C | Temperature and Humidity sensor + 61 | USE_T67XX | xsns_89 | T67XX | 0x15 | CO2 sensor + 62 | USE_SCD40 | xsns_92 | SCD40 | 0x62 | CO2 sensor Sensirion SCD40/SCD41 + 63 | USE_HM330X | xsns_93 | HM330X | 0x40 | Particule sensor + 64 | USE_HDC2010 | xsns_94 | HDC2010 | 0x40 | Temperature and Humidity sensor + 65 | USE_ADE7880 | xnrg_23 | ADE7880 | 0x38 | Energy monitor + 66 | USE_PCF85363 | xsns_99 | PCF85363 | 0x51 | Real time clock + 67 | USE_DS3502 | xdrv_61 | DS3502 | 0x28 - 0x2B | Digital potentiometer + 68 | USE_HYT | xsns_97 | HYTxxx | 0x28 | Temperature and Humidity sensor + 69 | USE_SGP40 | xsns_98 | SGP40 | 0x59 | Gas (TVOC) and air quality + 70 | USE_LUXV30B | xsns_99 | LUXV30B | 0x4A | DFRobot SEN0390 V30B lux sensor + 71 | USE_QMC5883L | xsns_33 | QMC5883L | 0x0D | Magnetic Field Sensor + 72 | USE_INA3221 | xsns_100 | INA3221 | 0x40-0x43 | 3-channels Voltage and Current sensor diff --git a/README.md b/README.md index 7d36ce522..1e6479af0 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,8 @@ You can contribute to Tasmota by ## Credits People helping to keep the show on the road: +- Sfromis providing extensive user support +- Barbudor providing user support and code fixes and additions - David Lang providing initial issue resolution and code optimizations - Heiko Krupp for his IRSend, HTU21, SI70xx and Wemo/Hue emulation drivers - Wiktor Schmidt for Travis CI implementation @@ -154,7 +156,7 @@ People helping to keep the show on the road: - Joel Stein, digiblur and Shantur Rathore for their Tuya research and driver - Frogmore42 for providing many issue answers - Jason2866 for platformio support and providing many issue answers -- Blakadder for managing the new document site and providing template management +- Blakadder for managing the document site and providing template management - Stephan Hadinger for refactoring light driver, enhancing HueEmulation, LVGL, Zigbee and Berry support - tmo for designing the official Tasmota logo - Stefan Bode for his Shutter and Deep sleep drivers diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 32b39387d..c4e874608 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -14,7 +14,7 @@ Pay attention to the following version breaks due to dynamic settings updates: 1. Migrate to **Sonoff-Tasmota 3.9.x** 2. Migrate to **Sonoff-Tasmota 4.x** -3. Migrate to **Sonoff-Tasmota 5.14** +3. Migrate to **Sonoff-Tasmota 5.14** (http://ota.tasmota.com/tasmota/release_5.14.0/sonoff.bin) - NOTICE underscore as a dash is not supported in older versions 4. Migrate to **Sonoff-Tasmota 6.7.1** (http://ota.tasmota.com/tasmota/release_6.7.1/sonoff.bin) - NOTICE underscore as a dash is not supported in older versions 5. Migrate to **Tasmota 7.2.0** (http://ota.tasmota.com/tasmota/release-7.2.0/tasmota.bin) @@ -33,9 +33,9 @@ While fallback or downgrading is common practice it was never supported due to S This release will be supported from ESP8266/Arduino library Core version **2.7.4.9** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. -This release will be supported from ESP32/Arduino library Core version **2.0.4.1**. +This release will be supported from ESP32/Arduino library Core version **2.0.5**. -Support of ESP8266 Core versions before 2.7.4.9 and ESP32 Core versions before 2.0.4.1 have been removed. +Support of ESP8266 Core versions before 2.7.4.9 and ESP32 Core versions before 2.0.5 have been removed. ## Support of TLS @@ -56,7 +56,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - **tasmota.bin** = The Tasmota version with most drivers for 1M+ flash. **RECOMMENDED RELEASE BINARY** - **tasmota4M.bin** = The Tasmota version with most drivers and filesystem for 4M+ flash. -- **tasmota-AF.bin** to **tasmota-VN.bin** = The Tasmota version in different languages for 1M+ flash. +- **tasmota-AD.bin** to **tasmota-VN.bin** = The Tasmota version in different languages for 1M+ flash. - **tasmota-lite.bin** = The Lite version without most drivers and sensors for 1M+ flash. - **tasmota-knx.bin** = The Knx version without some features but adds KNX support for 1M+ flash. - **tasmota-sensors.bin** = The Sensors version adds more useful sensors for 1M+ flash. @@ -72,18 +72,18 @@ Latest released binaries can be downloaded from - http://ota.tasmota.com/tasmota/release Historical binaries can be downloaded from -- http://ota.tasmota.com/tasmota/release-12.1.1 +- http://ota.tasmota.com/tasmota/release-12.2.0 The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin.gz`` ### ESP32, ESP32-C3, ESP32-S2 and ESP32-S3 based -The following binary downloads have been compiled with ESP32/Arduino library core version **2.0.4.1**. +The following binary downloads have been compiled with ESP32/Arduino library core version **2.0.5**. - **tasmota32.bin** = The Tasmota version with most drivers including additional sensors and KNX for 4M+ flash. **RECOMMENDED RELEASE BINARY** - **tasmota32xy.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C3/S2/S3 and 4M+ flash. - **tasmota32xycdc.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C3/S2/S3 with serial over embedded USB CDC only and 4M+ flash. - **tasmota32solo1.bin** = The Tasmota version with most drivers including additional sensors and KNX for single core ESP32 and 4M+ flash. -- **tasmota32-AF.bin** to **tasmota32-VN.bin** = The Tasmota version in different languages for 4M+ flash. +- **tasmota32-AD.bin** to **tasmota32-VN.bin** = The Tasmota version in different languages for 4M+ flash. - **tasmota32-bluetooth.bin** = The Bluetooth version adds BLE support for 4M+ flash. - **tasmota32-display.bin** = The Display version without Energy Monitoring but adds display support for 4M+ flash. - **tasmota32-ir.bin** = The InfraRed Receiver and transmitter version allowing all available protocols provided by library IRremoteESP8266 but without most other features for 4M+ flash. @@ -97,7 +97,7 @@ Latest released binaries can be downloaded from - http://ota.tasmota.com/tasmota32/release Historical binaries can be downloaded from -- http://ota.tasmota.com/tasmota32/release-12.1.1 +- http://ota.tasmota.com/tasmota32/release-12.2.0 The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota32/release/tasmota32.bin`` @@ -107,40 +107,60 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v12.1.1 Patricia +## Changelog v12.2.0 Patrick ### Added -- Command ``SetOption45 1..250`` to change default bistable latching relay pulse length of 40 milliseconds -- Command ``SetOption144 1`` includes a timestamp in zigbee `ZbReceived` messages -- Command ``GlobalTemp2 1..250`` to select Global Temperature source indexed from teleperiod occurance data [#15834](https://github.com/arendst/Tasmota/issues/15834) -- Command ``GlobalHum2 1..250`` to select Global Humidity source indexed from teleperiod occurance data [#15834](https://github.com/arendst/Tasmota/issues/15834) -- Command ``GlobalPress2 1..250`` to select Global Pressure source indexed from teleperiod occurance data [#15834](https://github.com/arendst/Tasmota/issues/15834) -- Command ``Sleep2 !`` to cancel pending one-shot speed setting [#15954](https://github.com/arendst/Tasmota/issues/15954) -- Commands ``WifiScan`` and ``WifiTest`` [#16141](https://github.com/arendst/Tasmota/issues/16141) -- Support for 5-channel light dimmer driver SM2335 used in SwitchBot Color Bulbs [#15839](https://github.com/arendst/Tasmota/issues/15839) -- Support for Sonoff POWR3xxD and THR3xxD [#15856](https://github.com/arendst/Tasmota/issues/15856) -- Support for bistable (latching) relays mixed with monostable relays using GPIO Relay_b or Relay_bi as used by Sonoff POWR320D and THR320D -- Support for Modbus bridge adding commands ``ModbusSend``, ``ModbusBaudrate`` and ``ModbusSerialConfig`` [#16013](https://github.com/arendst/Tasmota/issues/16013) -- Support for multiple ``IRsend`` GPIOs [#16138](https://github.com/arendst/Tasmota/issues/16138) -- Support for Catalan language translations by Albert Gonzalez [#16145](https://github.com/arendst/Tasmota/issues/16145) -- Zigbee added recording of when the battery was last reported [#16146](https://github.com/arendst/Tasmota/issues/16146) -- Zigbee add Battery auto-probe (can be disabled with ``SetOption143 1``) [#16148](https://github.com/arendst/Tasmota/issues/16148) -- ESP32 Support for Ultra Low Power (ULP) coprocessor via Berry by Christian Staars [#15916](https://github.com/arendst/Tasmota/issues/15916) +- Command ``SetOption46 0..255`` to add 0..255 * 10 milliseconds power on delay before initializing I/O [#15438](https://github.com/arendst/Tasmota/issues/15438) +- Command ``SetOption146 1`` to enable display of ESP32 internal temperature +- Command ``SetOption46 0..255`` to add 0..255 * 10 milliseconds power on delay before initializing I/O [#15438](https://github.com/arendst/Tasmota/issues/15438) +- Command ``StatusRetain`` [#11109](https://github.com/arendst/Tasmota/issues/11109) +- Command ``UrlFetch `` to download a file to filesystem +- Command ``DspSpeed 2..127`` to control message rotation speed on display of POWR3xxD and THR3xxD +- Command ``DspLine<1|2> ,,,,...`` to select message(s) on display of POWR3xxD and THR3xxD +- Command ``Sunrise 0..3`` to select sunrise dawn angle between Normal, Civil, Nautical or Astronomical [#16795](https://github.com/arendst/Tasmota/issues/16795) +- Command ``WcClock 10..200`` set webcam clock in MHz. Default is 20 +- Support for Shelly Plus 2PM +- Support for SGP40 gas and air quality sensor [#16341](https://github.com/arendst/Tasmota/issues/16341) +- Support for Modbus writing using ModbusBridge by JeroenSt [#16351](https://github.com/arendst/Tasmota/issues/16351) +- Support for DFRobot SEN0390 V30B ambient light sensor [#16105](https://github.com/arendst/Tasmota/issues/16105) +- Support for QMC5883L magnetic induction sensor by Helge Scheunemann [#16714](https://github.com/arendst/Tasmota/issues/16714) +- Support for Modbus Energy Monitoring devices using a rule file. See ``xnrg_29_modbus.ino`` for more information +- Zigbee device plugin mechanism with commands ``ZbLoad``, ``ZbUnload`` and ``ZbLoadDump`` [#16252](https://github.com/arendst/Tasmota/issues/16252) +- Zigbee basic support for Green Power [#16407](https://github.com/arendst/Tasmota/issues/16407) +- Zigbee friendly names per endpoint +- Zigbee Alexa/Hue emulation, support multiple switches on separate endpoints [#16718](https://github.com/arendst/Tasmota/issues/16718) +- Flowrate meter flow amount/duration, show values in table format [#16385](https://github.com/arendst/Tasmota/issues/16385) +- Support of optional file calib.dat on ADE7953 based energy monitors like Shelly EM [#16486](https://github.com/arendst/Tasmota/issues/16486) +- Support for Ethernet in ESP32 safeboot firmware [#16388](https://github.com/arendst/Tasmota/issues/16388) +- ESP32-S3 support for internal temperature sensor +- ESP32-S2 and ESP32-S3 touch button support +- Berry has persistent MQTT subscriptions: auto-subscribe at (re)connection +- Berry automated solidification of code +- LVGL/HASPmota add tiny "pixel perfect" fonts for small screens [#16758](https://github.com/arendst/Tasmota/issues/16758) +- HASPmota support for TTF fonts [#16759](https://github.com/arendst/Tasmota/issues/16759) ### Breaking Changed ### Changed -- TasmotaModbus library from v3.4.0 to v3.5.0 [#16245](https://github.com/arendst/Tasmota/issues/16245) -- ESP32 Arduino core from v2.0.3 to v2.0.4.1 [#15940](https://github.com/arendst/Tasmota/issues/15940) -- ESP32 LVGL library from v8.2.0 to v8.3.0 [#16019](https://github.com/arendst/Tasmota/issues/16019) -- Driver DHT v6 consolidation for both ESP8266 and ESP32 to support SI7021, THS01 and MS01 on ESP32 [#15856](https://github.com/arendst/Tasmota/issues/15856) +- IRremoteESP8266 library from v2.8.2 to v2.8.4 +- TasmotaModbus library from v3.5.0 to v3.6.0 [#16351](https://github.com/arendst/Tasmota/issues/16351) +- ESP32 NimBLE library from v1.3.6 to v1.4.0 +- ESP32 LVGL library from v8.3.0 to v8.3.2 +- ESP32 Tasmota Core32 from 2.0.4.1 to 2.0.5 +- Increase serial console input buffer size from 520 to 800 +- Button debouncing V3 by adopting switch debounce code [#16339](https://github.com/arendst/Tasmota/issues/16339) +- Thermostat max allowed temperature from 100 to 200C [#16363](https://github.com/arendst/Tasmota/issues/16363) +- Using command ``SerialBuffer`` raise max allowed buffer size to 2048 characters [#16374](https://github.com/arendst/Tasmota/issues/16374) +- Swap Shelly EM internal channels A and B to match P1 and P2 [#16486](https://github.com/arendst/Tasmota/issues/16486) +- Zigbee report unprocessed attributes +- ESP32 Increase number of button GPIOs from 8 to 28 [#16518](https://github.com/arendst/Tasmota/issues/16518) +- ESP32 Platformio one Platform for all Tasmota frameworks Core32 2.0.5 [#16644](https://github.com/arendst/Tasmota/issues/16644) ### Fixed -- Restore EnergyToday after using command ``restart 2`` and power cycle [#16118](https://github.com/arendst/Tasmota/issues/16118) -- ESP32 SendMail not working over ethernet [#15794](https://github.com/arendst/Tasmota/issues/15794) - RTC not detected when lights are present [#16242](https://github.com/arendst/Tasmota/issues/16242) - DNS lookup for .local domains [#16273](https://github.com/arendst/Tasmota/issues/16273) - Button response delay regression from v12.0.2.4 [#16319](https://github.com/arendst/Tasmota/issues/16319) - Lost module name in GUI regression from v12.0.2.4 - 20220803 [#16324](https://github.com/arendst/Tasmota/issues/16324) +- Removed whitespace from JSON values with no decimals [#16365](https://github.com/arendst/Tasmota/issues/16365) +- ESP32 touch button multi-press and hold detection [#16596](https://github.com/arendst/Tasmota/issues/16596) ### Removed -- Arduino IDE support diff --git a/boards/esp32-cam.json b/boards/esp32-cam.json index 20113163e..165b8ef58 100644 --- a/boards/esp32-cam.json +++ b/boards/esp32-cam.json @@ -4,10 +4,10 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DHAS_PSRAM_FIX -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M", + "extra_flags": "-DCAMERA_MODEL_AI_THINKER -DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DHAS_PSRAM_FIX -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "esp32", "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" diff --git a/boards/esp32-m5core2.json b/boards/esp32-m5core2.json index 5168ea57d..7fc157edb 100644 --- a/boards/esp32-m5core2.json +++ b/boards/esp32-m5core2.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_16M", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "qio", "mcu": "esp32", "variant": "m5stack_core2", "partitions": "partitions/esp32_partition_app2944k_fs10M.csv" diff --git a/boards/esp32-odroid.json b/boards/esp32-odroid.json index 6d155670e..f7804af4e 100644 --- a/boards/esp32-odroid.json +++ b/boards/esp32-odroid.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ODROID_ESP32 -DBOARD_HAS_PSRAM -DHAS_PSRAM_FIX -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_16M", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "odroid_esp32", "partitions": "partitions/esp32_partition_app2944k_fs10M.csv" diff --git a/boards/esp32_16M.json b/boards/esp32_16M.json index df52ebac4..c0956a642 100644 --- a/boards/esp32_16M.json +++ b/boards/esp32_16M.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_16M", "f_cpu": "80000000L", "f_flash": "40000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "esp32", "partitions": "partitions/esp32_partition_app2944k_fs10M.csv" diff --git a/boards/esp32_4M.json b/boards/esp32_4M.json index c4875e1bd..d8e39873f 100644 --- a/boards/esp32_4M.json +++ b/boards/esp32_4M.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M", "f_cpu": "80000000L", "f_flash": "40000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "esp32", "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" diff --git a/boards/esp32_4M_FS.json b/boards/esp32_4M_FS.json index bc5447ad1..c2c7fb2ef 100644 --- a/boards/esp32_4M_FS.json +++ b/boards/esp32_4M_FS.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M", "f_cpu": "80000000L", "f_flash": "40000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "esp32", "partitions": "partitions/esp32_partition_app1856k_fs1344k.csv" diff --git a/boards/esp32_4M_Legacy.json b/boards/esp32_4M_Legacy.json index 2af2b4add..fccad9d15 100644 --- a/boards/esp32_4M_Legacy.json +++ b/boards/esp32_4M_Legacy.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M", "f_cpu": "80000000L", "f_flash": "40000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "esp32", "partitions": "partitions/esp32_partition_app1856k_fs320k.csv" diff --git a/boards/esp32_8M.json b/boards/esp32_8M.json index 5a7842f75..e7a351a4d 100644 --- a/boards/esp32_8M.json +++ b/boards/esp32_8M.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_8M", "f_cpu": "80000000L", "f_flash": "40000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "esp32", "partitions": "partitions/esp32_partition_app2944k_fs2M.csv" diff --git a/boards/esp32_solo1_4M.json b/boards/esp32_solo1_4M.json index 6a7d9ed44..ebc5affe9 100644 --- a/boards/esp32_solo1_4M.json +++ b/boards/esp32_solo1_4M.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ESP32_DEV -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M -DCORE32SOLO1", "f_cpu": "80000000L", "f_flash": "40000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "esp32", "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" diff --git a/boards/esp32c3.json b/boards/esp32c3.json index c1fceed9a..955589dd3 100644 --- a/boards/esp32c3.json +++ b/boards/esp32c3.json @@ -7,13 +7,14 @@ "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M -DESP32C3", "f_cpu": "160000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32c3", "variant": "esp32c3", "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" }, "connectivity": [ - "wifi" + "wifi", + "bluetooth" ], "debug": { "openocd_target": "esp32c3.cfg" diff --git a/boards/esp32c3cdc.json b/boards/esp32c3cdc.json index ccd2da9d1..648fce5ec 100644 --- a/boards/esp32c3cdc.json +++ b/boards/esp32c3cdc.json @@ -7,13 +7,14 @@ "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M -DESP32C3 -DUSE_USB_CDC_CONSOLE", "f_cpu": "160000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32c3", "variant": "esp32c3", "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" }, "connectivity": [ - "wifi" + "wifi", + "bluetooth" ], "debug": { "openocd_target": "esp32c3.cfg" diff --git a/boards/esp32c3cdc_Legacy.json b/boards/esp32c3cdc_Legacy.json new file mode 100644 index 000000000..8a5d88804 --- /dev/null +++ b/boards/esp32c3cdc_Legacy.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M -DESP32C3 -DUSE_USB_CDC_CONSOLE", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32c3", + "variant": "esp32c3", + "partitions": "partitions/esp32_partition_app1856k_fs320k.csv" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif Generic ESP32-C3 4M Flash, Tasmota 1856k Code/OTA, 320k FS", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "before_reset": "usb_reset", + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html", + "vendor": "Espressif" + } diff --git a/boards/esp32s2.json b/boards/esp32s2.json index 4077ee33d..1fd5f0768 100644 --- a/boards/esp32s2.json +++ b/boards/esp32s2.json @@ -7,7 +7,7 @@ "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DESP32_4M -DESP32S2", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32s2", "variant": "esp32s2", "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" diff --git a/boards/esp32s2_Legacy.json b/boards/esp32s2_Legacy.json new file mode 100644 index 000000000..9bbae7b88 --- /dev/null +++ b/boards/esp32s2_Legacy.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DESP32_4M -DESP32S2", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32s2", + "variant": "esp32s2", + "partitions": "partitions/esp32_partition_app1856k_fs320k.csv" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "espidf", + "arduino" + ], + "name": "Espressif Generic ESP32-S2 4M Flash, Tasmota 1856k Code/OTA, 320k FS", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html", + "vendor": "Espressif" +} diff --git a/boards/esp32s2cdc.json b/boards/esp32s2cdc.json index b480113b7..e71bdbdf6 100644 --- a/boards/esp32s2cdc.json +++ b/boards/esp32s2cdc.json @@ -7,7 +7,7 @@ "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DUSE_USB_CDC_CONSOLE -DESP32_4M -DESP32S2", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32s2", "variant": "esp32s2", "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" @@ -37,6 +37,7 @@ "maximum_size": 4194304, "require_upload_port": true, "before_reset": "usb_reset", + "after_reset": "no_reset", "speed": 460800 }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html", diff --git a/boards/esp32s3.json b/boards/esp32s3.json index a498eb851..df9527c2c 100644 --- a/boards/esp32s3.json +++ b/boards/esp32s3.json @@ -1,13 +1,14 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld" + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DESP32_4M -DESP32S3", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s3", "variant": "esp32s3", "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" diff --git a/boards/esp32s3_8M.json b/boards/esp32s3_8M.json index 27000194c..46dea18ba 100644 --- a/boards/esp32s3_8M.json +++ b/boards/esp32s3_8M.json @@ -1,13 +1,14 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld" + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DESP32_8M -DESP32S3", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s3", "variant": "esp32s3", "partitions": "partitions/esp32_partition_app2944k_fs2M.csv" diff --git a/boards/esp32s3cdc-box.json b/boards/esp32s3cdc-box.json index cbeafdc39..5388523be 100644 --- a/boards/esp32s3cdc-box.json +++ b/boards/esp32s3cdc-box.json @@ -8,7 +8,7 @@ "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DUSE_USB_CDC_CONSOLE -DESP32_16M -DESP32S3", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s3", "variant": "esp32s3", "partitions": "partitions/esp32_partition_app2944k_fs10M.csv" diff --git a/boards/esp32s3cdc-cam.json b/boards/esp32s3cdc-cam.json new file mode 100644 index 000000000..761236e61 --- /dev/null +++ b/boards/esp32s3cdc-cam.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": "-DCAMERA_MODEL_TTGO_T_CAM_SIM -DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DUSE_USB_CDC_CONSOLE -DESP32_16M -DESP32S3", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3", + "partitions": "partitions/esp32_partition_app2944k_fs10M.csv" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "espidf", + "arduino" + ], + "name": "LilyGo T-SIMCAM ESP32-S3 16M Flash 8MB OPI PSRAM, Tasmota 2944k Code/OTA, 10M FS", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "before_reset": "usb_reset", + "speed": 460800 + }, + "url": "https://github.com/Xinyuan-LilyGO/LilyGo-Camera-Series", + "vendor": "LilyGo" +} diff --git a/boards/esp32s3cdc-eye.json b/boards/esp32s3cdc-eye.json new file mode 100644 index 000000000..3254a45df --- /dev/null +++ b/boards/esp32s3cdc-eye.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": "-DCAMERA_MODEL_ESP32S3_EYE -DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DUSE_USB_CDC_CONSOLE -DESP32_8M -DESP32S3", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3", + "partitions": "partitions/esp32_partition_app2944k_fs2M.csv" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "espidf", + "arduino" + ], + "name": "ESP32-S3-EYE 8M Flash 8MB OPI PSRAM, Tasmota 2944k Code/OTA, 2M FS", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "before_reset": "usb_reset", + "speed": 460800 + }, + "url": "https://github.com/espressif/esp-who/blob/master/docs/en/get-started/ESP32-S3-EYE_Getting_Started_Guide.md", + "vendor": "Espressif" +} diff --git a/boards/esp32s3cdc.json b/boards/esp32s3cdc.json index a5280fb9d..f4cb53cde 100644 --- a/boards/esp32s3cdc.json +++ b/boards/esp32s3cdc.json @@ -1,13 +1,14 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld" + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DUSE_USB_CDC_CONSOLE -DESP32_4M -DESP32S3", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s3", "variant": "esp32s3", "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" diff --git a/boards/esp32s3cdc_Legacy.json b/boards/esp32s3cdc_Legacy.json new file mode 100644 index 000000000..2fe80ff44 --- /dev/null +++ b/boards/esp32s3cdc_Legacy.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DUSE_USB_CDC_CONSOLE -DESP32_4M -DESP32S3", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s3", + "variant": "esp32s3", + "partitions": "partitions/esp32_partition_app1856k_fs320k.csv" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "espidf", + "arduino" + ], + "name": "Espressif Generic ESP32-S3 4M Flash, Tasmota 1856k Code/OTA, 320k FS", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "before_reset": "usb_reset", + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", + "vendor": "Espressif" +} diff --git a/boards/esp32s3cdc_LilyTDisp.json b/boards/esp32s3cdc_LilyTDisp.json new file mode 100644 index 000000000..f9a7c0702 --- /dev/null +++ b/boards/esp32s3cdc_LilyTDisp.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DUSE_USB_CDC_CONSOLE -DESP32_8M -DESP32S3", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3", + "partitions": "partitions/esp32_partition_app2944k_fs10M.csv" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": "esp-builtin", + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "espidf", + "arduino" + ], + "name": "LilyGo T-Display-S3 16M Flash 8MB OPI PSRAM, Tasmota 2944k Code/OTA, 10M FS", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "before_reset": "usb_reset", + "speed": 460800 + }, + "url": "https://github.com/Xinyuan-LilyGO/T-Display-S3", + "vendor": "LilyGo" + } diff --git a/boards/esp8266_1M.json b/boards/esp8266_1M.json index 7cd01ec90..6c3327ae7 100644 --- a/boards/esp8266_1M.json +++ b/boards/esp8266_1M.json @@ -15,9 +15,7 @@ "wifi" ], "frameworks": [ - "arduino", - "esp8266-rtos-sdk", - "esp8266-nonos-sdk" + "arduino" ], "name": "Espressif Generic ESP8266 Tasmota 1M sketch NO FS", "upload": { diff --git a/boards/esp8266_2M1M.json b/boards/esp8266_2M1M.json index afe54a343..3f34da721 100644 --- a/boards/esp8266_2M1M.json +++ b/boards/esp8266_2M1M.json @@ -15,9 +15,7 @@ "wifi" ], "frameworks": [ - "arduino", - "esp8266-rtos-sdk", - "esp8266-nonos-sdk" + "arduino" ], "name": "Espressif Generic ESP8266 Tasmota 1M sketch 1M FS", "upload": { diff --git a/boards/esp8266_2M256.json b/boards/esp8266_2M256.json index 335b84ade..5ef9e86ae 100644 --- a/boards/esp8266_2M256.json +++ b/boards/esp8266_2M256.json @@ -15,9 +15,7 @@ "wifi" ], "frameworks": [ - "arduino", - "esp8266-rtos-sdk", - "esp8266-nonos-sdk" + "arduino" ], "name": "Espressif Generic ESP8266 Tasmota 1M sketch 772k OTA 256k FS", "upload": { diff --git a/boards/esp8266_4M2M.json b/boards/esp8266_4M2M.json index 7b0e0c364..9708b2621 100644 --- a/boards/esp8266_4M2M.json +++ b/boards/esp8266_4M2M.json @@ -15,9 +15,7 @@ "wifi" ], "frameworks": [ - "arduino", - "esp8266-rtos-sdk", - "esp8266-nonos-sdk" + "arduino" ], "name": "Espressif Generic ESP8266 Tasmota 1M sketch 1M OTA 2M FS", "upload": { diff --git a/boards/esp8266_4M3M.json b/boards/esp8266_4M3M.json index fec296cf0..d1fe7e459 100644 --- a/boards/esp8266_4M3M.json +++ b/boards/esp8266_4M3M.json @@ -15,9 +15,7 @@ "wifi" ], "frameworks": [ - "arduino", - "esp8266-rtos-sdk", - "esp8266-nonos-sdk" + "arduino" ], "name": "Espressif Generic ESP8266 Tasmota 1M sketch 3M FS", "upload": { diff --git a/boards/esp8266_zbbridge.json b/boards/esp8266_zbbridge.json index dbc229004..726b71de3 100644 --- a/boards/esp8266_zbbridge.json +++ b/boards/esp8266_zbbridge.json @@ -15,9 +15,7 @@ "wifi" ], "frameworks": [ - "arduino", - "esp8266-rtos-sdk", - "esp8266-nonos-sdk" + "arduino" ], "name": "Sonoff ZbBridge Tasmota 1M sketch 772k OTA 256k FS", "upload": { diff --git a/lib/default/Ext-printf/src/SBuffer.hpp b/lib/default/Ext-printf/src/SBuffer.hpp index 9c545add0..b336a1d7b 100644 --- a/lib/default/Ext-printf/src/SBuffer.hpp +++ b/lib/default/Ext-printf/src/SBuffer.hpp @@ -79,6 +79,12 @@ public: _buf->buf[offset] = data; } } + void set16(const size_t offset, const uint16_t data) { + if (offset + 1 < _buf->len) { + _buf->buf[offset] = data & 0xFF; + _buf->buf[offset+1] = (data >> 8) & 0xFF; + } + } size_t add8(const uint8_t data) { // append 8 bits value if (_buf->len < _buf->size) { // do we have room for 1 byte diff --git a/lib/default/Ext-printf/src/ext_printf.cpp b/lib/default/Ext-printf/src/ext_printf.cpp index cb2e4d0d8..d15f4bcee 100644 --- a/lib/default/Ext-printf/src/ext_printf.cpp +++ b/lib/default/Ext-printf/src/ext_printf.cpp @@ -335,7 +335,8 @@ int32_t ext_vsnprintf_P(char * out_buf, size_t buf_len, const char * fmt_P, va_l if (isnan(number) || isinf(number)) { new_val_str = "null"; } else { - dtostrf(*(float*)cur_val, (decimals + 2), decimals, hex); + uint32_t len = (decimals) ? decimals +2 : 1; + dtostrf(*(float*)cur_val, len, decimals, hex); if (truncate) { uint32_t last = strlen(hex) - 1; diff --git a/lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp b/lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp index 41b79c868..0668faa1a 100644 --- a/lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp +++ b/lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp @@ -408,6 +408,8 @@ void JsonParser::parse(char * json_in) { // TODO error checking if (_token_len >= 0) { postProcess(json_len); + } else { + this->free(); // invalid JSON } } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md index e9d16eddd..b15ef1abe 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md @@ -10,8 +10,8 @@ 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.8.2 Now Available -Version 2.8.2 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. +## v2.8.4 Now Available +Version 2.8.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/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md index 50dbab2cb..51c18c482 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md @@ -11,8 +11,8 @@ Diese Programmbibliothek ermöglicht das **Senden _und_ Empfangen** von Infrarotsignalen mit [ESP8266](https://github.com/esp8266/Arduino)- und [ESP32](https://github.com/espressif/arduino-esp32)-Mikrocontrollern mithilfe des [Arduino-Frameworks](https://www.arduino.cc/) und handelsüblichen 940nm Infrarot-LEDs undIR-Empfängermodulen, wie zum Beispiel TSOP{17,22,24,36,38,44,48}*-Demodulatoren. -## v2.8.2 jetzt verfügbar -Version 2.8.2 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen. +## v2.8.4 jetzt verfügbar +Version 2.8.4 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen. #### Hinweis für Nutzer von Versionen vor v2.0 Die Benutzung der Bibliothek hat sich mit Version 2.0 leicht geändert. Einige Anpassungen im aufrufenden Code werden nötig sein, um mit Version ab 2.0 korrekt zu funktionieren. Mehr zu den Anpassungen finden sich auf unserer [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0)-Seite. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md index 71f4d4abc..71e436fc3 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md @@ -10,8 +10,8 @@ Cette librairie vous permetra de **recevoir et d'envoyer des signaux** infrarouge sur le protocole [ESP8266](https://github.com/esp8266/Arduino) ou sur le protocole [ESP32](https://github.com/espressif/arduino-esp32) en utilisant le [Arduino framework](https://www.arduino.cc/) qui utilise la norme 940nm IR LEDs et le module basique de reception d'onde IR. Exemple : TSOP{17,22,24,36,38,44,48}* modules etc. -## v2.8.2 disponible -Version 2.8.2 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. +## v2.8.4 disponible +Version 2.8.4 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. #### mise à jour depuis pre-v2.0 L'utilisation de la librairie à un peu changer depuis la version in v2.0. Si vous voulez l'utiliser vous devrez changer votre utilisation aussi. Vous pouvez vous renseigner sur les précondition d'utilisation ici : [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md index 5fd04c726..0370c91a6 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md @@ -1,5 +1,54 @@ # Release Notes +## _v2.8.4 (20220918)_ + +**[Bug Fixes]** + - [Bugfix] Handle gcc unsupported __VA_OPT___ macro (#1880 #1881) + + +## _v2.8.3 (20220915)_ + +**[Bug Fixes]** +- Fix `#if` for DECODE_COOLIX48 (#1796) +- Add missing `prev`s to `decodeToState()` (#1783) + +**[Features]** +- Add `pause()` function to ESP32 when receiving. (#1871) +- ARGO: Argo add `sendSensorTemp()` (#1858 #1859) +- HAIER_AC160: Experimental detail support. (#1852 #1804) +- BOSCH144: Add IRac class support (#1841) +- Mitsubishi_AC: update left vane in `IRac` class (#1837) +- Basic support for Daikin 312bit/39byte A/C protocol. (#1836 #1829) +- Experimental basic support for Sanyo AC 152 bit protocol. (#1828 #1826) +- GREE: Add model support for `YX1FSF`/Soleus Air Windown A/C (#1823 #1821) +- Experimental basic support for Bosch 144bit protocol. (#1822 #1787) +- Experimental basic support for TCL AC 96 bit protocol. (#1820 #1810) +- Add basic support for clima-butler (52bit) RCS-SD43UWI (#1815 #1812) +- TOTO: An experimental _(s)wipe_ at support for Toto Toilets. (#1811 #1806) +- CARRIER_AC128: Experimental Basic support for Carrier AC 128bit protocol. (#1798 #1797) +- HAIER_AC160: Add basic support for Haier 160bit protocol. (#1805 #1804) +- DAIKIN: Add basic support for 200-bit Daikin protocol. (#1803 #1802) +- FUJITSU: Improve handling of 10C Heat mode. (#1788 #1780) +- FUJITSU: Improve handling of short (command only) messages. (#1784 #1780) + +**[Misc]** +- Improve the `_IRREMOTEESP8266_VERSION_VAL` macro (#1875 #1870) +- SONY: Update supported devices. (#1872) +- SAMSUNG: Update supported devices (#1873) +- NEC: Update supported devices (#1874) +- Give IRmacros.h smaller scope to avoid impacting projects using IRremoteESP8266 (#1857 #1853 #1851) +- Inhibit protocol names for not-included protocols (#1853 #1851) +- Test out codeql static analysis (#1842) +- Remove pylint disable=no-self-use (#1817) +- Fujitsu General: update supported devices (#1813) +- DAIKIN: Update supported devices (#1808 #1807) +- Fujitsu: Update supported remote info. (#1801 #1794) +- DAIKIN128: Update supported devices (#1754) +- Voltas: Add link to manual for 122LZF A/C. (#1800 #1799 #1238) +- Daikin128: Additional unit test. (#1795 #1754) +- MIDEA: Update supported devices (#1791 #1790) + + ## _v2.8.2 (20220314)_ **[Bug Fixes]** diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md index 509e7cd50..422a5bf2d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md @@ -1,6 +1,6 @@ + Last generated: Thu 15 Sep 2022 12:54:42 +0000 ---> # IR Protocols supported by this library | Protocol | Brand | Model | A/C Model | Detailed A/C Support | @@ -11,8 +11,11 @@ | [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
TAC-444 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 | | [Arris](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Arris.cpp) | **Arris** | 120A V1.0 A18 remote
VIP1113M Set-top box | | - | +| [Bosch](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Bosch.cpp) | **[Bosch](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Bosch.h)** | CL3000i-Set 26 E A/C
RG10A(G2S)BGEF remote | | Yes | | [Bose](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Bose.cpp) | **Bose** | Bose TV Speaker | | - | +| [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **[Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.h)** | 40GKX0E2006 remote (CARRIER_AC128) | | Yes | | [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **[Carrier/Surrey](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.h)** | 42QG5A55970 remote
53NGK009/012 Inverter
619EGX0090E0 A/C
619EGX0120E0 A/C
619EGX0180E0 A/C
619EGX0220E0 A/C | | Yes | +| [ClimaButler](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_ClimaButler.cpp) | **Clima-Butler** | AR-715 remote
RCS-SD43UWI A/C | | - | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RC08B remote | | Yes | | [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
RG57K7(B)/BGEF Remote | | Yes | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Bosch](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | B1ZAI2441W/B1ZAO2441W A/C
RG36B4/BGE remote | | Yes | @@ -22,7 +25,7 @@ | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Tokio](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | AATOEMF17-12CHR1SW split-type RG51\|50/BGE Remote | | Yes | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RAS-4M27YAV-E A/C
RAS-M10YKV-E A/C
RAS-M13YKV-E A/C
WH-E1YE remote | | Yes | | [Corona](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Corona.cpp) | **[Corona](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Corona.h)** | AR-01 remote
CSH-N2211 A/C
CSH-N2511 A/C
CSH-N2811 A/C
CSH-N4011 A/C | | 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 FTXB09AXVJU A/C (DAIKIN128)
17 Series FTXB12AXVJU A/C (DAIKIN128)
17 Series FTXB24AXVJU A/C (NOT SUPPORTED)
ARC423A5 remote (DAIKIN160)
ARC433** remote (DAIKIN)
ARC433B69 remote (DAIKIN216)
ARC466A33 remote (DAIKIN)
ARC477A1 remote (DAIKIN2)
ARC480A5 remote (DAIKIN152)
ARC484A4 remote (DAIKIN216)
BRC4C151 remote (DAIKIN176)
BRC4C153 remote (DAIKIN176)
BRC52B63 remote (DAIKIN128)
DGS01 remote (DAIKIN64)
FFN-C/FCN-F Series A/C (DAIKIN64)
FFQ35B8V1B A/C (DAIKIN176)
FTE12HV2S A/C
FTQ60TV16U2 A/C (DAIKIN216)
FTWX35AXV1 A/C (DAIKIN64)
FTXM-M A/C (DAIKIN)
FTXZ25NV1B A/C (DAIKIN2)
FTXZ35NV1B A/C (DAIKIN2)
FTXZ50NV1B A/C (DAIKIN2)
M Series A/C (DAIKIN) | | 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 FTXB09AXVJU A/C (DAIKIN128)
17 Series FTXB12AXVJU A/C (DAIKIN128)
17 Series FTXB24AXVJU A/C (DAIKIN128)
ARC423A5 remote (DAIKIN160)
ARC433** remote (DAIKIN)
ARC433B69 remote (DAIKIN216)
ARC466A12 remote (DAIKIN)
ARC466A33 remote (DAIKIN)
ARC466A67 remote (DAIKIN312)
ARC477A1 remote (DAIKIN2)
ARC480A5 remote (DAIKIN152)
ARC484A4 remote (DAIKIN216)
BRC4C151 remote (DAIKIN176)
BRC4C153 remote (DAIKIN176)
BRC4M150W16 remote (DAIKIN200)
BRC52B63 remote (DAIKIN128)
DGS01 remote (DAIKIN64)
FFN-C/FCN-F Series A/C (DAIKIN64)
FFQ35B8V1B A/C (DAIKIN176)
FTE12HV2S A/C
FTQ60TV16U2 A/C (DAIKIN216)
FTWX35AXV1 A/C (DAIKIN64)
FTXM-M A/C (DAIKIN)
FTXM20R5V1B A/C (DAIKIN312)
FTXZ25NV1B A/C (DAIKIN2)
FTXZ35NV1B A/C (DAIKIN2)
FTXZ50NV1B A/C (DAIKIN2)
M Series A/C (DAIKIN) | | Yes | | [Delonghi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Delonghi.cpp) | **[Delonghi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Delonghi.h)** | PAC A95 | | Yes | | [Denon](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Denon.cpp) | **Denon** | AVR-3801 A/V Receiver (probably) | | - | | [Dish](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Dish.cpp) | **DISH NETWORK** | echostar 301 | | - | @@ -37,21 +40,23 @@ | [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Elite Screens** | CineTension2 / CineTension3 series
Home2 / Home3 series
Spectrum series
VMAX Plus4 series
VMAX2 / VMAX2 Plus series
ZSP-IR-B / ZSP-IR-W remote | | - | | [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Lumene Screens** | Embassy | | - | | [Epson](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Epson.cpp) | **Epson** | EN-TW9100W Projector
EX3220 Projector
EX5220 Projector
EX5230 Projector
EX6220 Projector
EX7220 Projector
VS230 Projector
VS330 Projector | | - | -| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C (ARRAH2E)
AR-DB1 remote (ARDB1)
AR-DL10 remote (ARDB1)
AR-RAC1E remote (ARRAH2E)
AR-RAE1E remote (ARRAH2E)
AR-RAH1U remote (ARREB1E)
AR-RAH2E remote (ARRAH2E)
AR-REB1E remote (ARREB1E)
AR-REB4E remote (ARREB1E)
AR-REW1E remote (ARREW4E)
AR-REW4E remote (ARREW4E)
AR-RY4 remote (ARRY4)
AST9RSGCW A/C (ARDB1)
ASTB09LBC A/C (ARRY4)
ASTG09K A/C (ARREW4E)
ASTG18K A/C (ARREW4E)
ASU12RLF A/C (ARREB1E)
ASU30C1 A/C (ARDB1)
ASYG09KETA-B A/C (ARREW4E)
ASYG30LFCA A/C (ARRAH2E)
ASYG7LMCA A/C (ARREB1E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | 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)** | AOHG09LLC A/C (ARRAH2E)
AR-JW2 remote (ARJW2)
AR-RCE1E remote (ARRAH2E)
ASHG09LLCA A/C (ARRAH2E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | 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)** | AGTV14LAC A/C (ARRAH2E)
AR-DB1 remote (ARDB1)
AR-DL10 remote (ARDB1)
AR-RAC1E remote (ARRAH2E)
AR-RAE1E remote (ARRAH2E)
AR-RAH1U remote (ARREB1E)
AR-RAH2E remote (ARRAH2E)
AR-RAH2U remote (ARRAH2E)
AR-REB1E remote (ARREB1E)
AR-REB4E remote (ARREB1E)
AR-REG1U remote (ARRAH2E)
AR-REW1E remote (ARREW4E)
AR-REW4E remote (ARREW4E)
AR-RY4 remote (ARRY4)
AST9RSGCW A/C (ARDB1)
ASTB09LBC A/C (ARRY4)
ASTG09K A/C (ARREW4E)
ASTG18K A/C (ARREW4E)
ASU12RLF A/C (ARREB1E)
ASU30C1 A/C (ARDB1)
ASYG09KETA-B A/C (ARREW4E)
ASYG30LFCA A/C (ARRAH2E)
ASYG7LMCA A/C (ARREB1E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | 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)** | AOHG09LLC A/C (ARRAH2E)
AR-JW17 remote (ARDB1)
AR-JW2 remote (ARJW2)
AR-RCE1E remote (ARRAH2E)
ASHG09LLCA A/C (ARRAH2E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | Yes | +| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[OGeneral](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-RCL1E remote (ARRAH2E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | Yes | | [GICable](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **G.I. Cable** | XRC-200 remote | | - | | [GlobalCache](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GlobalCache.cpp) | **Global Cache** | Control Tower IR DB | | - | | [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) | **[Amana](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | PBC093G00CC A/C
YX1FF remote | YAW1F
YBOFB | Yes | -| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Cooper & Hunter](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | CH-S09FTXG A/C
YB1F2 remote | YAW1F
YBOFB | 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) | **[Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VIR09HP115V1AH A/C
VIR12HP230V1AH A/C
YAA1FBF remote
YAN1F1 remote
YB1F2F remote | 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 | -| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Vailland](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VAI5-035WNI A/C
YACIFB remote | YAW1F
YBOFB | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Amana](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | PBC093G00CC A/C
YX1FF remote | YAW1F
YBOFB
YX1FSF | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Cooper & Hunter](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | CH-S09FTXG A/C
YB1F2 remote | YAW1F
YBOFB
YX1FSF | 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
YX1FSF | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VIR09HP115V1AH A/C
VIR12HP230V1AH A/C
YAA1FBF remote
YAN1F1 remote
YB1F2F remote
YX1F2F remote (YX1FSF) | YAW1F
YBOFB
YX1FSF | 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
YX1FSF | 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
YX1FSF | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Soleus Air](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | window A/C (YX1FSF) | YAW1F
YBOFB
YX1FSF | 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
YX1FSF | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Vailland](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VAI5-035WNI A/C
YACIFB remote | YAW1F
YBOFB
YX1FSF | Yes | | [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Daichi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | D-H A/C (HAIER_AC176) | | 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 (HAIER_AC_YRW02)
HSU07-HEA03 remote (HAIER_AC)
V9014557 M47 8D remote (HAIER_AC176)
YR-W02 remote (HAIER_AC_YRW02) | | 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 (HAIER_AC_YRW02)
HSU07-HEA03 remote (HAIER_AC)
KFR-26GW/83@UI-Ge A/C (HAIER_AC160)
V9014557 M47 8D remote (HAIER_AC176)
YR-W02 remote (HAIER_AC_YRW02) | | Yes | | [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Mabe](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | MMI18HDBWCA6MI8 A/C (HAIER_AC176)
V12843 HJ200223 remote (HAIER_AC176) | | 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)** | KAZE-312KSDP A/C (HITACHI_AC1)
LT0541-HTA remote (HITACHI_AC1)
PC-LH3B (HITACHI_AC3)
R-LT0541-HTA/Y.K.1.1-1 V2.3 remote (HITACHI_AC1)
RAK-25NH5 A/C (HITACHI_AC264)
RAR-2P2 remote (HITACHI_AC264)
RAR-3U3 remote (HITACHI_AC296)
RAR-8P2 remote (HITACHI_AC424)
RAS-22NK A/C (HITACHI_AC344)
RAS-35THA6 remote
RAS-70YHA3 A/C (HITACHI_AC296)
RAS-AJ25H A/C (HITACHI_AC424)
RF11T1 remote (HITACHI_AC344)
Series VI A/C (Circa 2007) (HITACHI_AC1) | | Yes | | [Inax](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Inax.cpp) | **Lixil** | Inax DT-BA283 Toilet | | - | @@ -78,7 +83,7 @@ | [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | FS40-7AR Stand Fan (MIDEA24) | | Yes | | [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[MrCool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57A6/BGEFU1 remote (MIDEA) | | 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)** | RG66B6(B)/BGEFU1 remote (MIDEA)
RUBO18GMFILCAD A/C (18K BTU) (MIDEA)
RYBO12GMFILCAD A/C (12K BTU) (MIDEA)
UB018GMFILCFHD A/C (12K BTU) (MIDEA)
WS012GMFI22HLD A/C (12K BTU) (MIDEA)
WS018GMFI22HLD A/C (12K BTU) (MIDEA) | | Yes | -| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57H(B)/BGE remote (MIDEA)
TROTEC PAC 3900 X (MIDEA) | | Yes | +| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57H(B)/BGE remote (MIDEA)
RG57H3(B)/BGCEF-M remote (MIDEA)
TROTEC PAC 2100 X (MIDEA)
TROTEC PAC 3900 X (MIDEA) | | Yes | | [MilesTag2](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MilesTag2.cpp) | **Milestag2** | Various | | - | | [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Maxell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | KKG9A-C1 remote
MX-CH18CF A/C | KKG29AC1
KKG9AC1 | Yes | | [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | VLU series A/C | KKG29AC1
KKG9AC1 | Yes | @@ -88,8 +93,10 @@ | [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 (88 bit)
RLA502A700B remote (152 bit)
SRKxxZJ-S A/C (88 bit)
SRKxxZM-S A/C (152 bit)
SRKxxZMXA-S A/C (152 bit) | | Yes | | [Multibrackets](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Multibrackets.cpp) | **Multibrackets** | Motorized Swing mount large - 4500 | | - | | [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Aloka](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | SleepyLights LED Lamp | | - | +| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[BBK](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | SP550S 5.1 sound system | | - | | [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Duux](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | Blizzard Smart 10K / DXMA04 A/C
YJ-A081 TR Remote | | - | | [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Silan Microelectronics](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | SC6121-001 IC | | - | +| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Tanix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | TX3 mini Android TV Box | | - | | [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | 42TL838 LCD TV | | - | | [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 | | - | | [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
ZH/TY-01 remote | | Yes | @@ -101,11 +108,11 @@ | [RC5_RC6](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp) | **Philips** | RC-5X (RC5X)
Standard RC-5 (RC5)
Standard RC-6 (RC6) | | - | | [RCMM](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RCMM.cpp) | **Microsoft** | XBOX 360 | | - | | [Rhoss](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Rhoss.cpp) | **[Rhoss](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Rhoss.h)** | Idrowall MPCV 20-30-35-40 | | Yes | -| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AH59-02692E Soundbar remote (SAMSUNG36)
AK59-00167A Bluray remote (SAMSUNG36)
AR09FSSDAWKNFA A/C (SAMSUNG_AC)
AR09HSFSBWKN A/C (SAMSUNG_AC)
AR12HSSDBWKNEU A/C (SAMSUNG_AC)
AR12KSFPEWQNET A/C (SAMSUNG_AC)
AR12NXCXAWKXEU A/C (SAMSUNG_AC)
AR12TXEAAWKNEU A/C (SAMSUNG_AC)
BN59-01178B TV remote (SAMSUNG)
DB63-03556X003 remote
DB93-14195A remote (SAMSUNG_AC)
DB93-16761C remote
DB96-24901C remote (SAMSUNG_AC)
HW-J551 Soundbar (SAMSUNG36)
IEC-R03 remote
UA55H6300 TV (SAMSUNG) | | Yes | -| [Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **[Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.h)** | LC7461 transmitter IC (SANYO_LC7461)
RCS-2HS4E remote (SANYO_AC)
RCS-2S4E remote (SANYO_AC)
SA 8650B - disabled
SAP-K121AHA A/C (SANYO_AC)
SAP-K242AH A/C (SANYO_AC) | | Yes | +| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AH59-02692E Soundbar remote (SAMSUNG36)
AK59-00167A Bluray remote (SAMSUNG36)
AR09FSSDAWKNFA A/C (SAMSUNG_AC)
AR09HSFSBWKN A/C (SAMSUNG_AC)
AR12HSSDBWKNEU A/C (SAMSUNG_AC)
AR12KSFPEWQNET A/C (SAMSUNG_AC)
AR12NXCXAWKXEU A/C (SAMSUNG_AC)
AR12TXEAAWKNEU A/C (SAMSUNG_AC)
BN59-01178B TV remote (SAMSUNG)
DB63-03556X003 remote
DB93-14195A remote (SAMSUNG_AC)
DB93-16761C remote
DB96-24901C remote (SAMSUNG_AC)
HW-J551 Soundbar (SAMSUNG36)
IEC-R03 remote
UA55H6300 TV (SAMSUNG)
UE40K5510AUXRU TV (SAMSUNG) | | Yes | +| [Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **[Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.h)** | LC7461 transmitter IC (SANYO_LC7461)
RCS-2HS4E remote (SANYO_AC)
RCS-2S4E remote (SANYO_AC)
RCS-4MHVPIS4EE remote (SANYO_AC152)
SA 8650B - disabled
SAP-K121AHA A/C (SANYO_AC)
SAP-K242AH A/C (SANYO_AC)
SAP-KMRV124EHE A/C (SANYO_AC152) | | Yes | | [Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AH-A12REVP-1 A/C (A903)
AH-AxSAY A/C (A907)
AH-PR13-GL A/C (A903)
AH-XP10NRY A/C (A903)
AY-ZP40KR A/C (A907)
CRMC-820 JBEZ remote (A903)
CRMC-A705 JBEZ remote (A705)
CRMC-A863 JBEZ remote (A903)
CRMC-A903JBEZ remote (A903)
CRMC-A907 JBEZ remote (A907)
CRMC-A950 JBEZ (A907)
LC-52D62U TV | A705
A903
A907 | 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) | **Sony** | HT-CT380 Soundbar (Uses 38kHz & 3 repeats) | | - | +| [Sony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sony.cpp) | **Sony** | HT-CT380 Soundbar (Uses 38kHz & 3 repeats)
HT-SF150 Soundbar (Uses 38kHz & 3 repeats) | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Blyss** | Owen-SW-5 3 Fan
WP-YK8 090218 remote | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **SamHop** | SM3015 Fan Remote Control
SM5021 Encoder chip
SM5032 Decoder chip | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Satellite Electronic** | ID6 Remote
JY199I Fan driver
JY199I-L Fan driver | | - | @@ -114,13 +121,14 @@ | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Westinghouse** | 78095 Remote
Ceiling fan | | - | | [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Daewoo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | DSB-F0934ELH-V A/C
GYKQ-52E remote | GZ055BE1
TAC09CHSD | Yes | | [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 (TAC09CHSD) | GZ055BE1
TAC09CHSD | Yes | -| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[TCL](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | TAC-09CHSD/XA31I A/C (TAC09CHSD) | GZ055BE1
TAC09CHSD | Yes | +| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[TCL](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | GYKQ-58(XM) remote (TCL96AC)
TAC-09CHSD/XA31I A/C (TAC09CHSD) | GZ055BE1
TAC09CHSD | Yes | | [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | Allegro SSA-09H A/C (GZ055BE1)
GZ-055B-E1 remote (GZ055BE1) | GZ055BE1
TAC09CHSD | Yes | | [Technibel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Technibel.cpp) | **[Technibel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Technibel.h)** | IRO PLUS | | 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 | | [Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teknopoint.cpp) | **Teknopoint** | Allegro SSA-09H A/C
GZ-055B-E1 remote
GZ01-BEJ0-000 remote | | - | | [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | 42NQV025M2 / 38NYV025M2 A/C
42NQV035M2 / 38NYV035M2 A/C
42NQV050M2 / 38NYV050M2 A/C
42NQV060M2 / 38NYV060M2 A/C | | 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-2558V A/C
RAS-25SKVP2-ND A/C
RAS-B13N3KV2
RAS-B13N3KVP-E
WC-L03SE
WH-TA01JE remote
WH-TA04NE
WH-UB03NJ remote | | Yes | +| [Toto](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toto.cpp) | **Toto** | Washlet Toilet NJ | | - | | [Transcold](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Transcold.cpp) | **[Transcold](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Transcold.h)** | M1-F-NO-6 A/C | | Yes | | [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Duux](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | Blizzard Smart 10K / DXMA04 A/C (TROTEC) | | Yes | | [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | PAC 3200 A/C (TROTEC)
PAC 3550 Pro A/C (TROTEC_3550) | | Yes | @@ -150,10 +158,13 @@ - AMCOR - ARGO - ARRIS +- BOSCH144 - BOSE - CARRIER_AC +- CARRIER_AC128 - CARRIER_AC40 - CARRIER_AC64 +- CLIMABUTLER - COOLIX - COOLIX48 - CORONA_AC @@ -163,7 +174,9 @@ - DAIKIN160 - DAIKIN176 - DAIKIN2 +- DAIKIN200 - DAIKIN216 +- DAIKIN312 - DAIKIN64 - DELONGHI_AC - DENON @@ -178,6 +191,7 @@ - GOODWEATHER - GREE - HAIER_AC +- HAIER_AC160 - HAIER_AC176 - HAIER_AC_YRW02 - HITACHI_AC @@ -231,6 +245,7 @@ - SAMSUNG_AC - SANYO - SANYO_AC +- SANYO_AC152 - SANYO_AC88 - SANYO_LC7461 - SHARP @@ -238,10 +253,12 @@ - SONY - SYMPHONY - TCL112AC +- TCL96AC - TECHNIBEL_AC - TECO - TEKNOPOINT - TOSHIBA_AC +- TOTO - TRANSCOLD - TROTEC - TROTEC_3550 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt index bab1f5d5e..a562d2451 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt @@ -25,6 +25,7 @@ IRAirtonAc KEYWORD1 IRAirwellAc KEYWORD1 IRAmcorAc KEYWORD1 IRArgoAC KEYWORD1 +IRBosch144AC KEYWORD1 IRCarrierAc64 KEYWORD1 IRCoolixAC KEYWORD1 IRCoronaAc KEYWORD1 @@ -43,6 +44,7 @@ IRFujitsuAC KEYWORD1 IRGoodweatherAc KEYWORD1 IRGreeAC KEYWORD1 IRHaierAC KEYWORD1 +IRHaierAC160 KEYWORD1 IRHaierAC176 KEYWORD1 IRHaierACYRW02 KEYWORD1 IRHitachiAc KEYWORD1 @@ -159,6 +161,7 @@ argo KEYWORD2 bcdToUint8 KEYWORD2 begin KEYWORD2 boolToString KEYWORD2 +bosch144 KEYWORD2 buildFromState KEYWORD2 calcBlockChecksum KEYWORD2 calcChecksum KEYWORD2 @@ -213,11 +216,14 @@ decodeAiwaRCT501 KEYWORD2 decodeAmcor KEYWORD2 decodeArgo KEYWORD2 decodeArris KEYWORD2 +decodeBosch144 KEYWORD2 decodeBose KEYWORD2 decodeCOOLIX KEYWORD2 decodeCarrierAC KEYWORD2 +decodeCarrierAC128 KEYWORD2 decodeCarrierAC40 KEYWORD2 decodeCarrierAC64 KEYWORD2 +decodeClimaButler KEYWORD2 decodeCoolix48 KEYWORD2 decodeCoronaAc KEYWORD2 decodeDISH KEYWORD2 @@ -227,7 +233,9 @@ decodeDaikin152 KEYWORD2 decodeDaikin160 KEYWORD2 decodeDaikin176 KEYWORD2 decodeDaikin2 KEYWORD2 +decodeDaikin200 KEYWORD2 decodeDaikin216 KEYWORD2 +decodeDaikin312 KEYWORD2 decodeDaikin64 KEYWORD2 decodeDelonghiAc KEYWORD2 decodeDenon KEYWORD2 @@ -241,6 +249,7 @@ decodeGICable KEYWORD2 decodeGoodweather KEYWORD2 decodeGree KEYWORD2 decodeHaierAC KEYWORD2 +decodeHaierAC160 KEYWORD2 decodeHaierAC176 KEYWORD2 decodeHaierACYRW02 KEYWORD2 decodeHash KEYWORD2 @@ -287,17 +296,20 @@ decodeSamsung36 KEYWORD2 decodeSamsungAC KEYWORD2 decodeSanyo KEYWORD2 decodeSanyoAc KEYWORD2 +decodeSanyoAc152 KEYWORD2 decodeSanyoAc88 KEYWORD2 decodeSanyoLC7461 KEYWORD2 decodeSharp KEYWORD2 decodeSharpAc KEYWORD2 decodeSony KEYWORD2 decodeSymphony KEYWORD2 +decodeTcl96Ac KEYWORD2 decodeTechnibelAc KEYWORD2 decodeTeco KEYWORD2 decodeTeknopoint KEYWORD2 decodeToState KEYWORD2 decodeToshibaAC KEYWORD2 +decodeToto KEYWORD2 decodeTranscold KEYWORD2 decodeTrotec KEYWORD2 decodeTrotec3550 KEYWORD2 @@ -351,6 +363,7 @@ get3D KEYWORD2 get8CHeat KEYWORD2 get8CHeatToggle KEYWORD2 getAbsenseDetect KEYWORD2 +getAuxHeating KEYWORD2 getBeep KEYWORD2 getBit KEYWORD2 getBoost KEYWORD2 @@ -490,6 +503,7 @@ getiFeel KEYWORD2 goodweather KEYWORD2 gree KEYWORD2 haier KEYWORD2 +haier160 KEYWORD2 haier176 KEYWORD2 haierYrwo2 KEYWORD2 handleSpecialState KEYWORD2 @@ -511,6 +525,7 @@ is8CHeatToggle KEYWORD2 isCleanToggle KEYWORD2 isEconoToggle KEYWORD2 isLightToggle KEYWORD2 +isLongCode KEYWORD2 isOffCommand KEYWORD2 isOffTimerActive KEYWORD2 isOffTimerEnabled KEYWORD2 @@ -569,6 +584,7 @@ on KEYWORD2 opmodeToString KEYWORD2 panasonic KEYWORD2 panasonic32 KEYWORD2 +pause KEYWORD2 recoverSavedState KEYWORD2 reset KEYWORD2 resultAcToString KEYWORD2 @@ -591,11 +607,14 @@ sendAiwaRCT501 KEYWORD2 sendAmcor KEYWORD2 sendArgo KEYWORD2 sendArris KEYWORD2 +sendBosch144 KEYWORD2 sendBose KEYWORD2 sendCOOLIX KEYWORD2 sendCarrierAC KEYWORD2 +sendCarrierAC128 KEYWORD2 sendCarrierAC40 KEYWORD2 sendCarrierAC64 KEYWORD2 +sendClimaButler KEYWORD2 sendCoolix48 KEYWORD2 sendCoronaAc KEYWORD2 sendDISH KEYWORD2 @@ -605,7 +624,9 @@ sendDaikin152 KEYWORD2 sendDaikin160 KEYWORD2 sendDaikin176 KEYWORD2 sendDaikin2 KEYWORD2 +sendDaikin200 KEYWORD2 sendDaikin216 KEYWORD2 +sendDaikin312 KEYWORD2 sendDaikin64 KEYWORD2 sendData KEYWORD2 sendDelonghiAc KEYWORD2 @@ -623,6 +644,7 @@ sendGeneric KEYWORD2 sendGoodweather KEYWORD2 sendGree KEYWORD2 sendHaierAC KEYWORD2 +sendHaierAC160 KEYWORD2 sendHaierAC176 KEYWORD2 sendHaierACYRW02 KEYWORD2 sendHitachiAC KEYWORD2 @@ -680,8 +702,10 @@ sendSAMSUNG KEYWORD2 sendSamsung36 KEYWORD2 sendSamsungAC KEYWORD2 sendSanyoAc KEYWORD2 +sendSanyoAc152 KEYWORD2 sendSanyoAc88 KEYWORD2 sendSanyoLC7461 KEYWORD2 +sendSensorTemp KEYWORD2 sendSharp KEYWORD2 sendSharpAc KEYWORD2 sendSharpRaw KEYWORD2 @@ -690,10 +714,12 @@ sendSony KEYWORD2 sendSony38 KEYWORD2 sendSymphony KEYWORD2 sendTcl112Ac KEYWORD2 +sendTcl96Ac KEYWORD2 sendTechnibelAc KEYWORD2 sendTeco KEYWORD2 sendTeknopoint KEYWORD2 sendToshibaAC KEYWORD2 +sendToto KEYWORD2 sendTranscold KEYWORD2 sendTrotec KEYWORD2 sendTrotec3550 KEYWORD2 @@ -711,6 +737,7 @@ set8CHeat KEYWORD2 set8CHeatToggle KEYWORD2 setAbsenseDetect KEYWORD2 setAuto KEYWORD2 +setAuxHeating KEYWORD2 setBeep KEYWORD2 setBit KEYWORD2 setBits KEYWORD2 @@ -718,6 +745,7 @@ setBoost KEYWORD2 setBreeze KEYWORD2 setButton KEYWORD2 setCelsius KEYWORD2 +setCheckSumS3 KEYWORD2 setClean KEYWORD2 setCleanToggle KEYWORD2 setClock KEYWORD2 @@ -753,6 +781,7 @@ setIFeel KEYWORD2 setISave10C KEYWORD2 setISee KEYWORD2 setId KEYWORD2 +setInvertBytes KEYWORD2 setInvertedStates KEYWORD2 setIon KEYWORD2 setIonFilter KEYWORD2 @@ -927,11 +956,14 @@ ARREB1E LITERAL1 ARREW4E LITERAL1 ARRIS LITERAL1 ARRY4 LITERAL1 +BOSCH144 LITERAL1 BOSE LITERAL1 CARRIER_AC LITERAL1 +CARRIER_AC128 LITERAL1 CARRIER_AC40 LITERAL1 CARRIER_AC64 LITERAL1 CARRIER_AC_BITS LITERAL1 +CLIMABUTLER LITERAL1 COOLIX LITERAL1 COOLIX48 LITERAL1 COOLIX_BITS LITERAL1 @@ -942,7 +974,9 @@ DAIKIN152 LITERAL1 DAIKIN160 LITERAL1 DAIKIN176 LITERAL1 DAIKIN2 LITERAL1 +DAIKIN200 LITERAL1 DAIKIN216 LITERAL1 +DAIKIN312 LITERAL1 DAIKIN64 LITERAL1 DAIKIN_AUTO LITERAL1 DAIKIN_COMMAND_LENGTH LITERAL1 @@ -963,10 +997,13 @@ DECODE_AIWA_RC_T501 LITERAL1 DECODE_AMCOR LITERAL1 DECODE_ARGO LITERAL1 DECODE_ARRIS LITERAL1 +DECODE_BOSCH144 LITERAL1 DECODE_BOSE LITERAL1 DECODE_CARRIER_AC LITERAL1 +DECODE_CARRIER_AC128 LITERAL1 DECODE_CARRIER_AC40 LITERAL1 DECODE_CARRIER_AC64 LITERAL1 +DECODE_CLIMABUTLER LITERAL1 DECODE_COOLIX LITERAL1 DECODE_COOLIX48 LITERAL1 DECODE_CORONA_AC LITERAL1 @@ -976,7 +1013,9 @@ DECODE_DAIKIN152 LITERAL1 DECODE_DAIKIN160 LITERAL1 DECODE_DAIKIN176 LITERAL1 DECODE_DAIKIN2 LITERAL1 +DECODE_DAIKIN200 LITERAL1 DECODE_DAIKIN216 LITERAL1 +DECODE_DAIKIN312 LITERAL1 DECODE_DAIKIN64 LITERAL1 DECODE_DELONGHI_AC LITERAL1 DECODE_DENON LITERAL1 @@ -992,6 +1031,7 @@ DECODE_GLOBALCACHE LITERAL1 DECODE_GOODWEATHER LITERAL1 DECODE_GREE LITERAL1 DECODE_HAIER_AC LITERAL1 +DECODE_HAIER_AC160 LITERAL1 DECODE_HAIER_AC176 LITERAL1 DECODE_HAIER_AC_YRW02 LITERAL1 DECODE_HASH LITERAL1 @@ -1043,6 +1083,7 @@ DECODE_SAMSUNG36 LITERAL1 DECODE_SAMSUNG_AC LITERAL1 DECODE_SANYO LITERAL1 DECODE_SANYO_AC LITERAL1 +DECODE_SANYO_AC152 LITERAL1 DECODE_SANYO_AC88 LITERAL1 DECODE_SHARP LITERAL1 DECODE_SHARP_AC LITERAL1 @@ -1050,10 +1091,12 @@ DECODE_SHERWOOD LITERAL1 DECODE_SONY LITERAL1 DECODE_SYMPHONY LITERAL1 DECODE_TCL112AC LITERAL1 +DECODE_TCL96AC LITERAL1 DECODE_TECHNIBEL_AC LITERAL1 DECODE_TECO LITERAL1 DECODE_TEKNOPOINT LITERAL1 DECODE_TOSHIBA_AC LITERAL1 +DECODE_TOTO LITERAL1 DECODE_TRANSCOLD LITERAL1 DECODE_TROTEC LITERAL1 DECODE_TROTEC_3550 LITERAL1 @@ -1133,6 +1176,7 @@ GREE_SWING_UP LITERAL1 GREE_SWING_UP_AUTO LITERAL1 GZ055BE1 LITERAL1 HAIER_AC LITERAL1 +HAIER_AC160 LITERAL1 HAIER_AC176 LITERAL1 HAIER_AC_AUTO LITERAL1 HAIER_AC_CMD_FAN LITERAL1 @@ -1289,6 +1333,7 @@ NEC_LIKE LITERAL1 NEOCLIMA LITERAL1 NIKAI LITERAL1 NIKAI_BITS LITERAL1 +NOTHING LITERAL1 ONCE LITERAL1 PANASONIC LITERAL1 PANASONIC_AC LITERAL1 @@ -1317,6 +1362,7 @@ SAMSUNG_AC LITERAL1 SAMSUNG_BITS LITERAL1 SANYO LITERAL1 SANYO_AC LITERAL1 +SANYO_AC152 LITERAL1 SANYO_AC88 LITERAL1 SANYO_LC7461 LITERAL1 SANYO_LC7461_BITS LITERAL1 @@ -1327,10 +1373,13 @@ SEND_AIWA_RC_T501 LITERAL1 SEND_AMCOR LITERAL1 SEND_ARGO LITERAL1 SEND_ARRIS LITERAL1 +SEND_BOSCH144 LITERAL1 SEND_BOSE LITERAL1 SEND_CARRIER_AC LITERAL1 +SEND_CARRIER_AC128 LITERAL1 SEND_CARRIER_AC40 LITERAL1 SEND_CARRIER_AC64 LITERAL1 +SEND_CLIMABUTLER LITERAL1 SEND_COOLIX LITERAL1 SEND_COOLIX48 LITERAL1 SEND_CORONA_AC LITERAL1 @@ -1340,7 +1389,9 @@ SEND_DAIKIN152 LITERAL1 SEND_DAIKIN160 LITERAL1 SEND_DAIKIN176 LITERAL1 SEND_DAIKIN2 LITERAL1 +SEND_DAIKIN200 LITERAL1 SEND_DAIKIN216 LITERAL1 +SEND_DAIKIN312 LITERAL1 SEND_DAIKIN64 LITERAL1 SEND_DELONGHI_AC LITERAL1 SEND_DENON LITERAL1 @@ -1356,6 +1407,7 @@ SEND_GLOBALCACHE LITERAL1 SEND_GOODWEATHER LITERAL1 SEND_GREE LITERAL1 SEND_HAIER_AC LITERAL1 +SEND_HAIER_AC160 LITERAL1 SEND_HAIER_AC176 LITERAL1 SEND_HAIER_AC_YRW02 LITERAL1 SEND_HITACHI_AC LITERAL1 @@ -1407,6 +1459,7 @@ SEND_SAMSUNG36 LITERAL1 SEND_SAMSUNG_AC LITERAL1 SEND_SANYO LITERAL1 SEND_SANYO_AC LITERAL1 +SEND_SANYO_AC152 LITERAL1 SEND_SANYO_AC88 LITERAL1 SEND_SHARP LITERAL1 SEND_SHARP_AC LITERAL1 @@ -1414,10 +1467,12 @@ SEND_SHERWOOD LITERAL1 SEND_SONY LITERAL1 SEND_SYMPHONY LITERAL1 SEND_TCL112AC LITERAL1 +SEND_TCL96AC LITERAL1 SEND_TECHNIBEL_AC LITERAL1 SEND_TECO LITERAL1 SEND_TEKNOPOINT LITERAL1 SEND_TOSHIBA_AC LITERAL1 +SEND_TOTO LITERAL1 SEND_TRANSCOLD LITERAL1 SEND_TROTEC LITERAL1 SEND_TROTEC_3550 LITERAL1 @@ -1441,6 +1496,7 @@ SONY_38K LITERAL1 SYMPHONY LITERAL1 TAC09CHSD LITERAL1 TCL112AC LITERAL1 +TCL96AC LITERAL1 TECHNIBEL_AC LITERAL1 TECO LITERAL1 TEKNOPOINT LITERAL1 @@ -1456,6 +1512,7 @@ TOSHIBA_AC_MAX_TEMP LITERAL1 TOSHIBA_AC_MIN_TEMP LITERAL1 TOSHIBA_AC_POWER LITERAL1 TOSHIBA_AC_STATE_LENGTH LITERAL1 +TOTO LITERAL1 TRANSCOLD LITERAL1 TROTEC LITERAL1 TROTEC_3550 LITERAL1 @@ -1484,6 +1541,7 @@ WHYNTER_BITS LITERAL1 XMP LITERAL1 YAW1F LITERAL1 YBOFB LITERAL1 +YX1FSF LITERAL1 ZEPEAL LITERAL1 k0Str LITERAL1 k10CHeatStr LITERAL1 @@ -1644,6 +1702,35 @@ kAutoStr LITERAL1 kAutomaticStr LITERAL1 kBeepStr LITERAL1 kBitsStr LITERAL1 +kBosch144Auto LITERAL1 +kBosch144Bits LITERAL1 +kBosch144BytesPerSection LITERAL1 +kBosch144Cool LITERAL1 +kBosch144DefaultState LITERAL1 +kBosch144Dry LITERAL1 +kBosch144Fan LITERAL1 +kBosch144Fan100 LITERAL1 +kBosch144Fan20 LITERAL1 +kBosch144Fan40 LITERAL1 +kBosch144Fan60 LITERAL1 +kBosch144Fan80 LITERAL1 +kBosch144FanAuto LITERAL1 +kBosch144FanAuto0 LITERAL1 +kBosch144Heat LITERAL1 +kBosch144NrOfSections LITERAL1 +kBosch144Off LITERAL1 +kBosch144StateLength LITERAL1 +kBosch144TempMap LITERAL1 +kBosch144TempMax LITERAL1 +kBosch144TempMin LITERAL1 +kBosch144TempRange LITERAL1 +kBoschBitMark LITERAL1 +kBoschFooterSpace LITERAL1 +kBoschFreq LITERAL1 +kBoschHdrMark LITERAL1 +kBoschHdrSpace LITERAL1 +kBoschOneSpace LITERAL1 +kBoschZeroSpace LITERAL1 kBoseBitMark LITERAL1 kBoseBits LITERAL1 kBoseFreq LITERAL1 @@ -1656,6 +1743,19 @@ kBottomStr LITERAL1 kBreezeStr LITERAL1 kButtonStr LITERAL1 kCancelStr LITERAL1 +kCarrierAc128BitMark LITERAL1 +kCarrierAc128Bits LITERAL1 +kCarrierAc128Hdr2Mark LITERAL1 +kCarrierAc128Hdr2Space LITERAL1 +kCarrierAc128HdrMark LITERAL1 +kCarrierAc128HdrSpace LITERAL1 +kCarrierAc128InterSpace LITERAL1 +kCarrierAc128MinRepeat LITERAL1 +kCarrierAc128OneSpace LITERAL1 +kCarrierAc128SectionBits LITERAL1 +kCarrierAc128SectionGap LITERAL1 +kCarrierAc128StateLength LITERAL1 +kCarrierAc128ZeroSpace LITERAL1 kCarrierAc40BitMark LITERAL1 kCarrierAc40Bits LITERAL1 kCarrierAc40Gap LITERAL1 @@ -1702,6 +1802,14 @@ kChangeStr LITERAL1 kCirculateStr LITERAL1 kCkpStr LITERAL1 kCleanStr LITERAL1 +kClimaButlerBitMark LITERAL1 +kClimaButlerBits LITERAL1 +kClimaButlerFreq LITERAL1 +kClimaButlerGap LITERAL1 +kClimaButlerHdrMark LITERAL1 +kClimaButlerHdrSpace LITERAL1 +kClimaButlerOneSpace LITERAL1 +kClimaButlerZeroSpace LITERAL1 kClockStr LITERAL1 kCodeStr LITERAL1 kColonSpaceStr LITERAL1 @@ -1880,6 +1988,19 @@ kDaikin176StateLength LITERAL1 kDaikin176SwingHAuto LITERAL1 kDaikin176SwingHOff LITERAL1 kDaikin176ZeroSpace LITERAL1 +kDaikin200BitMark LITERAL1 +kDaikin200Bits LITERAL1 +kDaikin200DefaultRepeat LITERAL1 +kDaikin200Freq LITERAL1 +kDaikin200Gap LITERAL1 +kDaikin200HdrMark LITERAL1 +kDaikin200HdrSpace LITERAL1 +kDaikin200OneSpace LITERAL1 +kDaikin200Section1Length LITERAL1 +kDaikin200Section2Length LITERAL1 +kDaikin200Sections LITERAL1 +kDaikin200StateLength LITERAL1 +kDaikin200ZeroSpace LITERAL1 kDaikin216BitMark LITERAL1 kDaikin216Bits LITERAL1 kDaikin216DefaultRepeat LITERAL1 @@ -1940,6 +2061,19 @@ kDaikin2SwingVSwing LITERAL1 kDaikin2SwingVUpperMiddle LITERAL1 kDaikin2Tolerance LITERAL1 kDaikin2ZeroSpace LITERAL1 +kDaikin312BitMark LITERAL1 +kDaikin312Bits LITERAL1 +kDaikin312DefaultRepeat LITERAL1 +kDaikin312HdrGap LITERAL1 +kDaikin312HdrMark LITERAL1 +kDaikin312HdrSpace LITERAL1 +kDaikin312OneSpace LITERAL1 +kDaikin312Section1Length LITERAL1 +kDaikin312Section2Length LITERAL1 +kDaikin312SectionGap LITERAL1 +kDaikin312Sections LITERAL1 +kDaikin312StateLength LITERAL1 +kDaikin312ZeroSpace LITERAL1 kDaikin64BitMark LITERAL1 kDaikin64Bits LITERAL1 kDaikin64ChecksumOffset LITERAL1 @@ -2202,6 +2336,8 @@ kFujitsuAcMaxTemp LITERAL1 kFujitsuAcMaxTempF LITERAL1 kFujitsuAcMinBits LITERAL1 kFujitsuAcMinGap LITERAL1 +kFujitsuAcMinHeat LITERAL1 +kFujitsuAcMinHeatF LITERAL1 kFujitsuAcMinRepeat LITERAL1 kFujitsuAcMinTemp LITERAL1 kFujitsuAcMinTempF LITERAL1 @@ -2290,6 +2426,7 @@ kGreeDisplayTempOff LITERAL1 kGreeDisplayTempOutside LITERAL1 kGreeDisplayTempSet LITERAL1 kGreeDry LITERAL1 +kGreeEcono LITERAL1 kGreeFan LITERAL1 kGreeFanAuto LITERAL1 kGreeFanMax LITERAL1 @@ -2325,12 +2462,27 @@ kGreeSwingUpAuto LITERAL1 kGreeTimerMax LITERAL1 kGreeZeroSpace LITERAL1 kGz055be1Str LITERAL1 +kHaierAC160Bits LITERAL1 +kHaierAC160StateLength LITERAL1 kHaierAC176Bits LITERAL1 kHaierAC176StateLength LITERAL1 kHaierACBits LITERAL1 kHaierACStateLength LITERAL1 kHaierACYRW02Bits LITERAL1 kHaierACYRW02StateLength LITERAL1 +kHaierAc160ButtonAuxHeating LITERAL1 +kHaierAc160ButtonClean LITERAL1 +kHaierAc160ButtonLight LITERAL1 +kHaierAc160DefaultRepeat LITERAL1 +kHaierAc160Prefix LITERAL1 +kHaierAc160SwingVAuto LITERAL1 +kHaierAc160SwingVHigh LITERAL1 +kHaierAc160SwingVHighest LITERAL1 +kHaierAc160SwingVLow LITERAL1 +kHaierAc160SwingVLowest LITERAL1 +kHaierAc160SwingVMiddle LITERAL1 +kHaierAc160SwingVOff LITERAL1 +kHaierAc160SwingVTop LITERAL1 kHaierAc176DefaultRepeat LITERAL1 kHaierAc176Prefix LITERAL1 kHaierAcAuto LITERAL1 @@ -3538,6 +3690,16 @@ kSamsungRptSpaceTicks LITERAL1 kSamsungTick LITERAL1 kSamsungZeroSpace LITERAL1 kSamsungZeroSpaceTicks LITERAL1 +kSanyoAc152BitMark LITERAL1 +kSanyoAc152Bits LITERAL1 +kSanyoAc152ExtraTolerance LITERAL1 +kSanyoAc152Freq LITERAL1 +kSanyoAc152HdrMark LITERAL1 +kSanyoAc152HdrSpace LITERAL1 +kSanyoAc152MinRepeat LITERAL1 +kSanyoAc152OneSpace LITERAL1 +kSanyoAc152StateLength LITERAL1 +kSanyoAc152ZeroSpace LITERAL1 kSanyoAc88Auto LITERAL1 kSanyoAc88BitMark LITERAL1 kSanyoAc88Bits LITERAL1 @@ -3770,6 +3932,15 @@ kTcl112AcTimerMax LITERAL1 kTcl112AcTimerResolution LITERAL1 kTcl112AcTolerance LITERAL1 kTcl112AcZeroSpace LITERAL1 +kTcl96AcBitMark LITERAL1 +kTcl96AcBitSpaces LITERAL1 +kTcl96AcBits LITERAL1 +kTcl96AcDefaultRepeat LITERAL1 +kTcl96AcGap LITERAL1 +kTcl96AcHdrMark LITERAL1 +kTcl96AcHdrSpace LITERAL1 +kTcl96AcSpaceCount LITERAL1 +kTcl96AcStateLength LITERAL1 kTechnibelAcBitMark LITERAL1 kTechnibelAcBits LITERAL1 kTechnibelAcCool LITERAL1 @@ -3871,6 +4042,19 @@ kToshibaAcSwingToggle LITERAL1 kToshibaAcTurboOn LITERAL1 kToshibaAcUsualGap LITERAL1 kToshibaAcZeroSpace LITERAL1 +kTotoBitMark LITERAL1 +kTotoBits LITERAL1 +kTotoDefaultRepeat LITERAL1 +kTotoGap LITERAL1 +kTotoHdrMark LITERAL1 +kTotoHdrSpace LITERAL1 +kTotoLongBits LITERAL1 +kTotoOneSpace LITERAL1 +kTotoPrefix LITERAL1 +kTotoPrefixBits LITERAL1 +kTotoShortBits LITERAL1 +kTotoSpecialGap LITERAL1 +kTotoZeroSpace LITERAL1 kTranscoldAuto LITERAL1 kTranscoldBitMark LITERAL1 kTranscoldBits LITERAL1 @@ -4090,6 +4274,7 @@ kXmpWordSize LITERAL1 kYaw1fStr LITERAL1 kYbofbStr LITERAL1 kYesStr LITERAL1 +kYx1fsfStr LITERAL1 kZepealBits LITERAL1 kZepealCommandOffOn LITERAL1 kZepealCommandOffTimer LITERAL1 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json index 948ae48fa..10a428ad0 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.8.2", + "version": "2.8.4", "keywords": "infrared, ir, remote, esp8266, esp32", "description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)", "repository": diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties index d776853f2..801fcab6e 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties @@ -1,5 +1,5 @@ name=IRremoteESP8266 -version=2.8.2 +version=2.8.4 author=David Conran, Sebastien Warin, Mark Szabo, Ken Shirriff maintainer=David Conran, Mark Szabo, Sebastien Warin, Roi Dayan, Massimiliano Pinto, Christian Nilsson sentence=Send and receive infrared signals with multiple protocols (ESP8266/ESP32) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp index de07bf964..af6beb30b 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp @@ -20,6 +20,7 @@ #include "ir_Airwell.h" #include "ir_Amcor.h" #include "ir_Argo.h" +#include "ir_Bosch.h" #include "ir_Carrier.h" #include "ir_Coolix.h" #include "ir_Corona.h" @@ -161,6 +162,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_ARGO case decode_type_t::ARGO: #endif +#if SEND_BOSCH144 + case decode_type_t::BOSCH144: +#endif #if SEND_CARRIER_AC64 case decode_type_t::CARRIER_AC64: #endif // SEND_CARRIER_AC64 @@ -215,6 +219,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_HAIER_AC case decode_type_t::HAIER_AC: #endif +#if SEND_HAIER_AC160 + case decode_type_t::HAIER_AC160: +#endif // SEND_HAIER_AC160 #if SEND_HAIER_AC176 case decode_type_t::HAIER_AC176: #endif // SEND_HAIER_AC176 @@ -459,6 +466,47 @@ void IRac::argo(IRArgoAC *ac, } #endif // SEND_ARGO +#if SEND_BOSCH144 +/// Send a Bosch144 A/C message with the supplied settings. +/// @note May result in multiple messages being sent. +/// @param[in, out] ac A Ptr to an IRBosch144AC object to use. +/// @param[in] on The power setting. +/// @param[in] mode The operation mode setting. +/// @param[in] degrees The temperature setting in degrees. +/// @param[in] fan The speed setting for the fan. +/// @param[in] quiet Run the device in quiet/silent mode. +/// @note -1 is Off, >= 0 is on. +void IRac::bosch144(IRBosch144AC *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const bool quiet) { + ac->begin(); + ac->setPower(on); + if (!on) { + // after turn off AC no more commands should + // be accepted + ac->send(); + return; + } + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setMode(ac->convertMode(mode)); + ac->setQuiet(quiet); + ac->send(); // Send the state, which will also power on the unit. + // The following are all options/settings that create their own special + // messages. Often they only make sense to be sent after the unit is turned + // on. For instance, assuming a person wants to have the a/c on and in turbo + // mode. If we send the turbo message, it is ignored if the unit is off. + // Hence we send the special mode/setting messages after a normal message + // which will turn on the device. + // No Filter setting available. + // No Beep setting available. + // No Clock setting available. + // No Econo setting available. + // No Sleep setting available. +} +#endif // SEND_BOSCH144 + #if SEND_CARRIER_AC64 /// Send a Carrier 64-bit A/C message with the supplied settings. /// @param[in, out] ac A Ptr to an IRCarrierAc64 object to use. @@ -1155,6 +1203,52 @@ void IRac::haier(IRHaierAC *ac, } #endif // SEND_HAIER_AC +#if SEND_HAIER_AC160 +/// Send a Haier 160 bit A/C message with the supplied settings. +/// @param[in, out] ac A Ptr to an IRHaierAC160 object to use. +/// @param[in] on The power setting. +/// @param[in] mode The operation mode setting. +/// @param[in] celsius Temperature units. True is Celsius, False is Fahrenheit. +/// @param[in] degrees The temperature setting in degrees. +/// @param[in] fan The speed setting for the fan. +/// @param[in] swingv The vertical swing setting. +/// @param[in] turbo Run the device in turbo/powerful mode. +/// @param[in] quiet Run the device in quiet mode. +/// @param[in] filter Turn on the (ion/pollen/etc) filter mode. +/// @param[in] clean Turn on the clean mode. +/// @param[in] light Turn on the LED/Display mode. +/// @param[in] prevlight Previous LED/Display mode. +/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on. +void IRac::haier160(IRHaierAC160 *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 bool turbo, const bool quiet, const bool filter, + const bool clean, const bool light, const bool prevlight, + const int16_t sleep) { + ac->begin(); + // No Model setting available. + ac->setMode(ac->convertMode(mode)); + ac->setUseFahrenheit(!celsius); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingV(ac->convertSwingV(swingv)); + // No Horizontal Swing setting available. + ac->setQuiet(quiet); + ac->setTurbo(turbo); + ac->setHealth(filter); + ac->setClean(clean); + // 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); + // Light needs to be sent last as the "button" value seems to control it. + ac->setLightToggle(light ^ prevlight); + ac->send(); +} +#endif // SEND_HAIER_AC160 + #if SEND_HAIER_AC176 /// Send a Haier 176 bit A/C message with the supplied settings. /// @param[in, out] ac A Ptr to an IRHaierAC176 object to use. @@ -1642,6 +1736,7 @@ void IRac::mitsubishi(IRMitsubishiAC *ac, ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setVane(ac->convertSwingV(swingv)); + ac->setVaneLeft(ac->convertSwingV(swingv)); ac->setWideVane(ac->convertSwingH(swingh)); if (quiet) ac->setFan(kMitsubishiAcFanSilent); ac->setISave10C(false); @@ -2718,6 +2813,9 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { const stdAc::swingv_t prev_swingv = (prev != NULL) ? prev->swingv : stdAc::swingv_t::kOff; #endif // (SEND_LG || SEND_SHARP_AC) +#if (SEND_HAIER_AC160) + const bool prev_light = (prev != NULL) ? prev->light : !send.light; +#endif // (SEND_HAIER_AC160) #if SEND_MIDEA const bool prev_quiet = (prev != NULL) ? prev->quiet : !send.quiet; #endif // SEND_MIDEA @@ -2758,6 +2856,14 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { break; } #endif // SEND_ARGO +#if SEND_BOSCH144 + case BOSCH144: + { + IRBosch144AC ac(_pin, _inverted, _modulation); + bosch144(&ac, send.power, send.mode, degC, send.fanspeed, send.quiet); + break; + } +#endif // SEND_BOSCH144 #if SEND_CARRIER_AC64 case CARRIER_AC64: { @@ -2924,6 +3030,16 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { break; } #endif // SEND_HAIER_AC +#if SEND_HAIER_AC160 + case HAIER_AC160: + { + IRHaierAC160 ac(_pin, _inverted, _modulation); + haier160(&ac, send.power, send.mode, send.celsius, send.degrees, + send.fanspeed, send.swingv, send.turbo, send.filter, send.clean, + send.light, prev_light, send.sleep); + break; + } +#endif // SEND_HAIER_AC160 #if SEND_HAIER_AC176 case HAIER_AC176: { @@ -3472,6 +3588,8 @@ int16_t IRac::strToModel(const char *str, const int16_t def) { return gree_ac_remote_model_t::YAW1F; } else if (!STRCASECMP(str, kYbofbStr)) { return gree_ac_remote_model_t::YBOFB; + } else if (!STRCASECMP(str, kYx1fsfStr)) { + return gree_ac_remote_model_t::YX1FSF; // Haier models } else if (!STRCASECMP(str, kV9014557AStr)) { return haier_ac176_remote_model_t::V9014557_A; @@ -3683,6 +3801,13 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_ARGO +#if DECODE_BOSCH144 + case decode_type_t::BOSCH144: { + IRBosch144AC ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_BOSCH144 #if DECODE_CARRIER_AC64 case decode_type_t::CARRIER_AC64: { IRCarrierAc64 ac(kGpioUnused); @@ -3813,6 +3938,13 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_HAIER_AC +#if DECODE_HAIER_AC160 + case decode_type_t::HAIER_AC160: { + IRHaierAC160 ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_HAIER_AC160 #if DECODE_HAIER_AC176 case decode_type_t::HAIER_AC176: { IRHaierAC176 ac(kGpioUnused); @@ -4132,6 +4264,14 @@ namespace IRAcUtils { break; } #endif // DECODE_ARGO +#if DECODE_BOSCH144 + case decode_type_t::BOSCH144: { + IRBosch144AC ac(kGpioUnused); + ac.setRaw(decode->state); + *result = ac.toCommon(); + break; + } +#endif // DECODE_BOSCH144 #if DECODE_CARRIER_AC64 case decode_type_t::CARRIER_AC64: { IRCarrierAc64 ac(kGpioUnused); @@ -4168,7 +4308,7 @@ namespace IRAcUtils { case decode_type_t::DAIKIN128: { IRDaikin128 ac(kGpioUnused); ac.setRaw(decode->state); - *result = ac.toCommon(); + *result = ac.toCommon(prev); break; } #endif // DECODE_DAIKIN128 @@ -4252,7 +4392,7 @@ namespace IRAcUtils { case decode_type_t::FUJITSU_AC: { IRFujitsuAC ac(kGpioUnused); ac.setRaw(decode->state, decode->bits / 8); - *result = ac.toCommon(); + *result = ac.toCommon(prev); break; } #endif // DECODE_FUJITSU_AC @@ -4280,6 +4420,14 @@ namespace IRAcUtils { break; } #endif // DECODE_HAIER_AC +#if DECODE_HAIER_AC160 + case decode_type_t::HAIER_AC160: { + IRHaierAC160 ac(kGpioUnused); + ac.setRaw(decode->state); + *result = ac.toCommon(prev); + break; + } +#endif // DECODE_HAIER_AC160 #if DECODE_HAIER_AC176 case decode_type_t::HAIER_AC176: { IRHaierAC176 ac(kGpioUnused); @@ -4348,7 +4496,7 @@ namespace IRAcUtils { case decode_type_t::KELON: { IRKelonAc ac(kGpioUnused); ac.setRaw(decode->value); - *result = ac.toCommon(); + *result = ac.toCommon(prev); break; } #endif // DECODE_KELON diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h index 8e3ef7582..9193a531d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h @@ -11,6 +11,7 @@ #include "ir_Airwell.h" #include "ir_Amcor.h" #include "ir_Argo.h" +#include "ir_Bosch.h" #include "ir_Carrier.h" #include "ir_Coolix.h" #include "ir_Corona.h" @@ -134,6 +135,12 @@ class IRac { const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const int16_t sleep = -1); #endif // SEND_ARGO +#if SEND_BOSCH144 + void bosch144(IRBosch144AC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, + const bool quiet); +#endif // SEND_COOLIX #if SEND_CARRIER_AC64 void carrier64(IRCarrierAc64 *ac, const bool on, const stdAc::opmode_t mode, @@ -268,6 +275,15 @@ void electra(IRElectraAc *ac, const bool filter, const int16_t sleep = -1, const int16_t clock = -1); #endif // SEND_HAIER_AC +#if SEND_HAIER_AC160 + void haier160(IRHaierAC160 *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 bool turbo, const bool quiet, const bool filter, + const bool clean, const bool light, const bool prevlight, + const int16_t sleep = -1); +#endif // SEND_HAIER_AC160 #if SEND_HAIER_AC176 void haier176(IRHaierAC176 *ac, const haier_ac176_remote_model_t model, const bool on, diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRmacros.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRmacros.h new file mode 100644 index 000000000..2c2ad7d94 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRmacros.h @@ -0,0 +1,53 @@ +#ifndef IRMACROS_H_ +#define IRMACROS_H_ +/**************************************************************** + * Copyright 2022 IRremoteESP8266 project and others + */ +/// @file IRmacros.h + +/** + * VA_OPT_SUPPORTED macro to check if __VA_OPT__ is supported + * Source: https://stackoverflow.com/a/48045656 + */ +/// @cond TEST +#define PP_THIRD_ARG(a, b, c, ...) c +#define VA_OPT_SUPPORTED_I(...) \ + PP_THIRD_ARG(__VA_OPT__(, false), true, false, false) +#define VA_OPT_SUPPORTED VA_OPT_SUPPORTED_I(?) +/// @endcond +/** + * VA_OPT_SUPPORTED end + */ + +/** + * COND() Set of macros to facilitate single-line conditional compilation + * argument checking. + * Found here: https://www.reddit.com/r/C_Programming/comments/ud3xrv/ + * conditional_preprocessor_macro_anyone/ + * + * Usage: + * COND([||/&&...], , ) + * + * NB: If __VA_OPT__ macro not supported, the will be expanded! + */ +/// @cond TEST +#if !VA_OPT_SUPPORTED +// #pragma message("Compiler without __VA_OPT__ support") +#define COND(cond, a, b) a +#else +#define NOTHING +#define EXPAND(...) __VA_ARGS__ +#define STUFF_P(a, ...) __VA_OPT__(a) +#define STUFF(...) STUFF_P(__VA_ARGS__) +#define VA_TEST_P(a, ...) __VA_OPT__(NO)##THING +#define VA_TEST(...) VA_TEST_P(__VA_ARGS__) +#define NEGATE(a) VA_TEST(a, a) +#define COND_P(cond, a, b) STUFF(a, cond)STUFF(b, NEGATE(cond)) +#define COND(cond, a, b) EXPAND(COND_P(cond, a, b)) +#endif +/// @endcond +/** + * end of COND() set of macros + */ + +#endif // IRMACROS_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp index fc4113d81..95f7c2af9 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp @@ -741,6 +741,11 @@ bool IRrecv::decode(decode_results *results, irparams_t *save, DPRINTLN("Attempting Sharp decode"); if (decodeSharp(results, offset)) return true; #endif +#if DECODE_BOSCH144 + DPRINTLN("Attempting Bosch 144-bit decode"); + // Bosch is similar to Coolix, so it must be attempted before decodeCOOLIX. + if (decodeBosch144(results, offset)) return true; +#endif // DECODE_BOSCH144 #if DECODE_COOLIX DPRINTLN("Attempting Coolix 24-bit decode"); if (decodeCOOLIX(results, offset)) return true; @@ -1114,6 +1119,39 @@ bool IRrecv::decode(decode_results *results, irparams_t *save, DPRINTLN("Attempting Coolix 48-bit decode"); if (decodeCoolix48(results, offset)) return true; #endif // DECODE_COOLIX48 +#if DECODE_DAIKIN200 + DPRINTLN("Attempting Daikin 200-bit decode"); + if (decodeDaikin200(results, offset)) return true; +#endif // DECODE_DAIKIN200 +#if DECODE_HAIER_AC160 + DPRINTLN("Attempting Haier AC 160 bit decode"); + if (decodeHaierAC160(results, offset)) return true; +#endif // DECODE_HAIER_AC160 +#if DECODE_CARRIER_AC128 + DPRINTLN("Attempting Carrier AC 128-bit decode"); + if (decodeCarrierAC128(results, offset)) return true; +#endif // DECODE_CARRIER_AC128 +#if DECODE_TOTO + DPRINTLN("Attempting Toto 48/24-bit decode"); + if (decodeToto(results, offset, kTotoLongBits) || // Long needs to be first + decodeToto(results, offset, kTotoShortBits)) return true; +#endif // DECODE_TOTO +#if DECODE_CLIMABUTLER + DPRINTLN("Attempting ClimaButler decode"); + if (decodeClimaButler(results)) return true; +#endif // DECODE_CLIMABUTLER +#if DECODE_TCL96AC + DPRINTLN("Attempting TCL AC 96-bit decode"); + if (decodeTcl96Ac(results, offset)) return true; +#endif // DECODE_TCL96AC +#if DECODE_SANYO_AC152 + DPRINTLN("Attempting Sanyo AC 152-bit decode"); + if (decodeSanyoAc152(results, offset)) return true; +#endif // DECODE_SANYO_AC152 +#if DECODE_DAIKIN312 + DPRINTLN("Attempting Daikin 312-bit decode"); + if (decodeDaikin312(results, offset)) return true; +#endif // DECODE_DAIKIN312 // Typically new protocols are added above this line. } #if DECODE_HASH @@ -1128,7 +1166,7 @@ bool IRrecv::decode(decode_results *results, irparams_t *save, if (!resumed) // Check if we have already resumed. resume(); return false; -} +} // NOLINT(readability/fn_size) /// Convert the tolerance percentage into something valid. /// @param[in] percentage An integer percentage. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h index 9b833f704..ad09f6d35 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h @@ -326,6 +326,12 @@ class IRrecv { const uint16_t nbits = kSanyoAc88Bits, const bool strict = true); #endif // DECODE_SANYO_AC88 +#if DECODE_SANYO_AC152 + bool decodeSanyoAc152(decode_results *results, + uint16_t offset = kStartOffset, + const uint16_t nbits = kSanyoAc152Bits, + const bool strict = true); +#endif // DECODE_SANYO_AC152 #if DECODE_MITSUBISHI bool decodeMitsubishi(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kMitsubishiBits, @@ -508,11 +514,21 @@ class IRrecv { const uint16_t nbits = kDaikin2Bits, const bool strict = true); #endif +#if DECODE_DAIKIN200 + bool decodeDaikin200(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kDaikin200Bits, + const bool strict = true); +#endif // DECODE_DAIKIN200 #if DECODE_DAIKIN216 bool decodeDaikin216(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kDaikin216Bits, const bool strict = true); -#endif +#endif // DECODE_DAIKIN216 +#if DECODE_DAIKIN312 + bool decodeDaikin312(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kDaikin312Bits, + const bool strict = true); +#endif // DECODE_DAIKIN312 #if DECODE_TOSHIBA_AC bool decodeToshibaAC(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kToshibaACBits, @@ -570,6 +586,12 @@ class IRrecv { const uint16_t nbits = kCarrierAc64Bits, const bool strict = true); #endif // DECODE_CARRIER_AC64 +#if DECODE_CARRIER_AC128 + bool decodeCarrierAC128(decode_results *results, + uint16_t offset = kStartOffset, + const uint16_t nbits = kCarrierAc128Bits, + const bool strict = true); +#endif // DECODE_CARRIER_AC128 #if DECODE_GOODWEATHER bool decodeGoodweather(decode_results *results, uint16_t offset = kStartOffset, @@ -581,7 +603,8 @@ class IRrecv { const uint16_t nbits = kGreeBits, const bool strict = true); #endif -#if (DECODE_HAIER_AC | DECODE_HAIER_AC_YRW02) +#if (DECODE_HAIER_AC | DECODE_HAIER_AC_YRW02 || DECODE_HAIER_AC160 || \ + DECODE_HAIER_AC176) bool decodeHaierAC(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kHaierACBits, const bool strict = true); @@ -592,6 +615,12 @@ class IRrecv { const uint16_t nbits = kHaierACYRW02Bits, const bool strict = true); #endif +#if DECODE_HAIER_AC160 + bool decodeHaierAC160(decode_results *results, + uint16_t offset = kStartOffset, + const uint16_t nbits = kHaierAC160Bits, + const bool strict = true); +#endif // DECODE_HAIER_AC160 #if DECODE_HAIER_AC176 bool decodeHaierAC176(decode_results *results, uint16_t offset = kStartOffset, @@ -805,6 +834,29 @@ class IRrecv { const uint16_t nbits = kAirtonBits, const bool strict = true); #endif // DECODE_AIRTON +#if DECODE_TOTO + bool decodeToto(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kTotoBits, + const bool strict = true); +#endif // DECODE_TOTO +#if DECODE_CLIMABUTLER + bool decodeClimaButler(decode_results *results, + uint16_t offset = kStartOffset, + const uint16_t nbits = kClimaButlerBits, + const bool strict = true); +#endif // DECODE_CLIMABUTLER +#if DECODE_TCL96AC + bool decodeTcl96Ac(decode_results *results, + uint16_t offset = kStartOffset, + const uint16_t nbits = kTcl96AcBits, + const bool strict = true); +#endif // DECODE_TCL96AC +#if DECODE_BOSCH144 + bool decodeBosch144(decode_results *results, + uint16_t offset = kStartOffset, + const uint16_t nbits = kBosch144Bits, + const bool strict = true); +#endif // DECODE_BOSCH144 }; #endif // IRRECV_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h index 574b01d3d..09e5d045b 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h @@ -58,10 +58,10 @@ // Minor version number (x.X.x) #define _IRREMOTEESP8266_VERSION_MINOR 8 // Patch version number (x.x.X) -#define _IRREMOTEESP8266_VERSION_PATCH 2 +#define _IRREMOTEESP8266_VERSION_PATCH 4 // Macro to convert version info into an integer #define _IRREMOTEESP8266_VERSION_VAL(major, minor, patch) \ - ((major << 16) | (minor << 8) | (patch)) + (((major) << 16) | ((minor) << 8) | (patch)) // Macro to convert literal into a string #define MKSTR_HELPER(x) #x #define MKSTR(x) MKSTR_HELPER(x) @@ -238,6 +238,13 @@ #define SEND_SANYO_AC88 _IR_ENABLE_DEFAULT_ #endif // SEND_SANYO_AC88 +#ifndef DECODE_SANYO_AC152 +#define DECODE_SANYO_AC152 _IR_ENABLE_DEFAULT_ +#endif // DECODE_SANYO_AC152 +#ifndef SEND_SANYO_AC152 +#define SEND_SANYO_AC152 _IR_ENABLE_DEFAULT_ +#endif // SEND_SANYO_AC152 + #ifndef DECODE_MITSUBISHI #define DECODE_MITSUBISHI _IR_ENABLE_DEFAULT_ #endif // DECODE_MITSUBISHI @@ -455,6 +462,13 @@ #define SEND_CARRIER_AC64 _IR_ENABLE_DEFAULT_ #endif // SEND_CARRIER_AC64 +#ifndef DECODE_CARRIER_AC128 +#define DECODE_CARRIER_AC128 _IR_ENABLE_DEFAULT_ +#endif // DECODE_CARRIER_AC128 +#ifndef SEND_CARRIER_AC128 +#define SEND_CARRIER_AC128 _IR_ENABLE_DEFAULT_ +#endif // SEND_CARRIER_AC128 + #ifndef DECODE_HAIER_AC #define DECODE_HAIER_AC _IR_ENABLE_DEFAULT_ #endif // DECODE_HAIER_AC @@ -602,6 +616,13 @@ #define SEND_TECO _IR_ENABLE_DEFAULT_ #endif // SEND_TECO +#ifndef DECODE_TCL96AC +#define DECODE_TCL96AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_TCL96AC +#ifndef SEND_TCL96AC +#define SEND_TCL96AC _IR_ENABLE_DEFAULT_ +#endif // SEND_TCL96AC + #ifndef DECODE_TCL112AC #define DECODE_TCL112AC _IR_ENABLE_DEFAULT_ #endif // DECODE_TCL112AC @@ -861,6 +882,48 @@ #define SEND_KELON168 _IR_ENABLE_DEFAULT_ #endif // SEND_KELON168 +#ifndef DECODE_DAIKIN200 +#define DECODE_DAIKIN200 _IR_ENABLE_DEFAULT_ +#endif // DECODE_DAIKIN200 +#ifndef SEND_DAIKIN200 +#define SEND_DAIKIN200 _IR_ENABLE_DEFAULT_ +#endif // SEND_DAIKIN200 + +#ifndef DECODE_HAIER_AC160 +#define DECODE_HAIER_AC160 _IR_ENABLE_DEFAULT_ +#endif // DECODE_HAIER_AC160 +#ifndef SEND_HAIER_AC160 +#define SEND_HAIER_AC160 _IR_ENABLE_DEFAULT_ +#endif // SEND_HAIER_AC160 + +#ifndef DECODE_TOTO +#define DECODE_TOTO _IR_ENABLE_DEFAULT_ +#endif // DECODE_TOTO +#ifndef SEND_TOTO +#define SEND_TOTO _IR_ENABLE_DEFAULT_ +#endif // SEND_TOTO + +#ifndef DECODE_CLIMABUTLER +#define DECODE_CLIMABUTLER _IR_ENABLE_DEFAULT_ +#endif // DECODE_CLIMABUTLER +#ifndef SEND_CLIMABUTLER +#define SEND_CLIMABUTLER _IR_ENABLE_DEFAULT_ +#endif // SEND_CLIMABUTLER + +#ifndef DECODE_BOSCH144 +#define DECODE_BOSCH144 _IR_ENABLE_DEFAULT_ +#endif // DECODE_BOSCH144 +#ifndef SEND_BOSCH144 +#define SEND_BOSCH144 _IR_ENABLE_DEFAULT_ +#endif // SEND_BOSCH144 + +#ifndef DECODE_DAIKIN312 +#define DECODE_DAIKIN312 _IR_ENABLE_DEFAULT_ +#endif // DECODE_DAIKIN312 +#ifndef SEND_DAIKIN312 +#define SEND_DAIKIN312 _IR_ENABLE_DEFAULT_ +#endif // SEND_DAIKIN312 + #if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \ DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \ DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \ @@ -876,7 +939,9 @@ DECODE_VOLTAS || DECODE_MIRAGE || DECODE_HAIER_AC176 || \ DECODE_TEKNOPOINT || DECODE_KELON || DECODE_TROTEC_3550 || \ DECODE_SANYO_AC88 || DECODE_RHOSS || DECODE_HITACHI_AC264 || \ - DECODE_KELON168 || DECODE_HITACHI_AC296 || \ + DECODE_KELON168 || DECODE_HITACHI_AC296 || DECODE_CARRIER_AC128 || \ + DECODE_DAIKIN200 || DECODE_HAIER_AC160 || DECODE_TCL96AC || \ + DECODE_BOSCH144 || DECODE_SANYO_AC152 || DECODE_DAIKIN312 || \ false) // Add any DECODE to the above if it uses result->state (see kStateSizeMax) // you might also want to add the protocol to hasACState function @@ -1030,8 +1095,17 @@ enum decode_type_t { HITACHI_AC264, KELON168, HITACHI_AC296, + DAIKIN200, + HAIER_AC160, // 115 + CARRIER_AC128, + TOTO, + CLIMABUTLER, + TCL96AC, + BOSCH144, // 120 + SANYO_AC152, + DAIKIN312, // Add new entries before this one, and update it to point to the last entry. - kLastDecodeType = HITACHI_AC296, + kLastDecodeType = DAIKIN312, }; // Message lengths & required repeat values @@ -1052,6 +1126,8 @@ const uint16_t kArgoStateLength = 12; const uint16_t kArgoBits = kArgoStateLength * 8; const uint16_t kArgoDefaultRepeat = kNoRepeat; const uint16_t kArrisBits = 32; +const uint16_t kBosch144StateLength = 18; +const uint16_t kBosch144Bits = kBosch144StateLength * 8; const uint16_t kCoolixBits = 24; const uint16_t kCoolix48Bits = kCoolixBits * 2; const uint16_t kCoolixDefaultRepeat = kSingleRepeat; @@ -1061,6 +1137,9 @@ const uint16_t kCarrierAc40Bits = 40; const uint16_t kCarrierAc40MinRepeat = 2; const uint16_t kCarrierAc64Bits = 64; const uint16_t kCarrierAc64MinRepeat = kNoRepeat; +const uint16_t kCarrierAc128StateLength = 16; +const uint16_t kCarrierAc128Bits = kCarrierAc128StateLength * 8; +const uint16_t kCarrierAc128MinRepeat = kNoRepeat; const uint16_t kCoronaAcStateLengthShort = 7; const uint16_t kCoronaAcStateLength = kCoronaAcStateLengthShort * 3; const uint16_t kCoronaAcBitsShort = kCoronaAcStateLengthShort * 8; @@ -1087,9 +1166,15 @@ const uint16_t kDaikin152DefaultRepeat = kNoRepeat; const uint16_t kDaikin176StateLength = 22; const uint16_t kDaikin176Bits = kDaikin176StateLength * 8; const uint16_t kDaikin176DefaultRepeat = kNoRepeat; +const uint16_t kDaikin200StateLength = 25; +const uint16_t kDaikin200Bits = kDaikin200StateLength * 8; +const uint16_t kDaikin200DefaultRepeat = kNoRepeat; const uint16_t kDaikin216StateLength = 27; const uint16_t kDaikin216Bits = kDaikin216StateLength * 8; const uint16_t kDaikin216DefaultRepeat = kNoRepeat; +const uint16_t kDaikin312StateLength = 39; +const uint16_t kDaikin312Bits = kDaikin312StateLength * 8; +const uint16_t kDaikin312DefaultRepeat = kNoRepeat; const uint16_t kDelonghiAcBits = 64; const uint16_t kDelonghiAcDefaultRepeat = kNoRepeat; const uint16_t kTechnibelAcBits = 56; @@ -1127,6 +1212,9 @@ const uint16_t kHaierAcDefaultRepeat = kNoRepeat; const uint16_t kHaierACYRW02StateLength = 14; const uint16_t kHaierACYRW02Bits = kHaierACYRW02StateLength * 8; const uint16_t kHaierAcYrw02DefaultRepeat = kNoRepeat; +const uint16_t kHaierAC160StateLength = 20; +const uint16_t kHaierAC160Bits = kHaierAC160StateLength * 8; +const uint16_t kHaierAc160DefaultRepeat = kNoRepeat; const uint16_t kHaierAC176StateLength = 22; const uint16_t kHaierAC176Bits = kHaierAC176StateLength * 8; const uint16_t kHaierAc176DefaultRepeat = kNoRepeat; @@ -1230,6 +1318,9 @@ const uint16_t kSanyoAcBits = kSanyoAcStateLength * 8; const uint16_t kSanyoAc88StateLength = 11; const uint16_t kSanyoAc88Bits = kSanyoAc88StateLength * 8; const uint16_t kSanyoAc88MinRepeat = 2; +const uint16_t kSanyoAc152StateLength = 19; +const uint16_t kSanyoAc152Bits = kSanyoAc152StateLength * 8; +const uint16_t kSanyoAc152MinRepeat = kNoRepeat; const uint16_t kSanyoSA8650BBits = 12; const uint16_t kSanyoLC7461AddressBits = 13; const uint16_t kSanyoLC7461CommandBits = 8; @@ -1250,6 +1341,9 @@ const uint16_t kSonyMinBits = 12; const uint16_t kSonyMinRepeat = 2; const uint16_t kSymphonyBits = 12; const uint16_t kSymphonyDefaultRepeat = 3; +const uint16_t kTcl96AcStateLength = 12; +const uint16_t kTcl96AcBits = kTcl96AcStateLength * 8; +const uint16_t kTcl96AcDefaultRepeat = kNoRepeat; const uint16_t kTcl112AcStateLength = 14; const uint16_t kTcl112AcBits = kTcl112AcStateLength * 8; const uint16_t kTcl112AcDefaultRepeat = kNoRepeat; @@ -1264,6 +1358,10 @@ const uint16_t kToshibaACStateLengthShort = kToshibaACStateLength - 2; const uint16_t kToshibaACBitsShort = kToshibaACStateLengthShort * 8; const uint16_t kToshibaACStateLengthLong = kToshibaACStateLength + 1; const uint16_t kToshibaACBitsLong = kToshibaACStateLengthLong * 8; +const uint16_t kTotoBits = 24; +const uint16_t kTotoShortBits = kTotoBits; +const uint16_t kTotoLongBits = kTotoShortBits * 2; +const uint16_t kTotoDefaultRepeat = kSingleRepeat; const uint16_t kTranscoldBits = 24; const uint16_t kTranscoldDefaultRepeat = kNoRepeat; const uint16_t kTrotecStateLength = 9; @@ -1287,6 +1385,7 @@ const uint16_t kBoseBits = 16; const uint16_t kRhossStateLength = 12; const uint16_t kRhossBits = kRhossStateLength * 8; const uint16_t kRhossDefaultRepeat = 0; +const uint16_t kClimaButlerBits = 52; // Legacy defines. (Deprecated) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp index d80b4bbf6..1fb1339c5 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp @@ -571,6 +571,7 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) { case MULTIBRACKETS: case SHERWOOD: case TOSHIBA_AC: + case TOTO: return kSingleRepeat; // Special case AIRWELL: @@ -633,6 +634,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { case MIDEA24: case NIKAI: case RCMM: + case TOTO: case TRANSCOLD: return 24; case LG: @@ -668,6 +670,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { case MIDEA: case PANASONIC: return 48; + case CLIMABUTLER: + return kClimaButlerBits; // 52 case AIRTON: case ECOCLIM: case MAGIQUEST: @@ -682,8 +686,12 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { return 64; case ARGO: return kArgoBits; + case BOSCH144: + return kBosch144Bits; case CORONA_AC: return kCoronaAcBits; + case CARRIER_AC128: + return kCarrierAc128Bits; case DAIKIN: return kDaikinBits; case DAIKIN128: @@ -696,8 +704,12 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { return kDaikin176Bits; case DAIKIN2: return kDaikin2Bits; + case DAIKIN200: + return kDaikin200Bits; case DAIKIN216: return kDaikin216Bits; + case DAIKIN312: + return kDaikin312Bits; case DAIKIN64: return kDaikin64Bits; case ELECTRA_AC: @@ -708,6 +720,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { return kHaierACBits; case HAIER_AC_YRW02: return kHaierACYRW02Bits; + case HAIER_AC160: + return kHaierAC160Bits; case HAIER_AC176: return kHaierAC176Bits; case HITACHI_AC: @@ -756,8 +770,12 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { return kSanyoAcBits; case SANYO_AC88: return kSanyoAc88Bits; + case SANYO_AC152: + return kSanyoAc152Bits; case SHARP_AC: return kSharpAcBits; + case TCL96AC: + return kTcl96AcBits; case TCL112AC: return kTcl112AcBits; case TEKNOPOINT: @@ -833,6 +851,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data, sendCarrierAC64(data, nbits, min_repeat); break; #endif // SEND_CARRIER_AC64 +#if SEND_CLIMABUTLER + case CLIMABUTLER: + sendClimaButler(data, nbits, min_repeat); + break; +#endif // SEND_CLIMABUTLER #if SEND_COOLIX case COOLIX: sendCOOLIX(data, nbits, min_repeat); @@ -1066,6 +1089,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data, sendTeco(data, nbits, min_repeat); break; #endif // SEND_TECO +#if SEND_TOTO + case TOTO: + sendToto(data, nbits, min_repeat); + break; +#endif // SEND_TOTO #if SEND_TRANSCOLD case TRANSCOLD: sendTranscold(data, nbits, min_repeat); @@ -1126,6 +1154,16 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state, sendArgo(state, nbytes); break; #endif // SEND_ARGO +#if SEND_BOSCH144 + case BOSCH144: + sendBosch144(state, nbytes); + break; +#endif // SEND_BOSCH144 +#if SEND_CARRIER_AC128 + case CARRIER_AC128: + sendCarrierAC128(state, nbytes); + break; +#endif // SEND_CARRIER_AC128 #if SEND_CORONA_AC case CORONA_AC: sendCoronaAc(state, nbytes); @@ -1161,11 +1199,21 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state, sendDaikin2(state, nbytes); break; #endif // SEND_DAIKIN2 +#if SEND_DAIKIN200 + case DAIKIN200: + sendDaikin200(state, nbytes); + break; +#endif // SEND_DAIKIN200 #if SEND_DAIKIN216 case DAIKIN216: sendDaikin216(state, nbytes); break; #endif // SEND_DAIKIN216 +#if SEND_DAIKIN312 + case DAIKIN312: + sendDaikin312(state, nbytes); + break; +#endif // SEND_DAIKIN312 #if SEND_ELECTRA_AC case ELECTRA_AC: sendElectraAC(state, nbytes); @@ -1191,6 +1239,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state, sendHaierACYRW02(state, nbytes); break; #endif // SEND_HAIER_AC_YRW02 +#if SEND_HAIER_AC160 + case HAIER_AC160: + sendHaierAC160(state, nbytes); + break; +#endif // SEND_HAIER_AC160 #if SEND_HAIER_AC176 case HAIER_AC176: sendHaierAC176(state, nbytes); @@ -1309,11 +1362,21 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state, sendSanyoAc88(state, nbytes); break; #endif // SEND_SANYO_AC88 +#if SEND_SANYO_AC152 + case SANYO_AC152: + sendSanyoAc152(state, nbytes); + break; +#endif // SEND_SANYO_AC152 #if SEND_SHARP_AC case SHARP_AC: sendSharpAc(state, nbytes); break; #endif // SEND_SHARP_AC +#if SEND_TCL96AC + case TCL96AC: + sendTcl96Ac(state, nbytes); + break; +#endif // SEND_TCL96AC #if SEND_TCL112AC case TCL112AC: sendTcl112Ac(state, nbytes); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h index 06d168375..02f2c939e 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h @@ -118,7 +118,8 @@ struct state_t { /// Fujitsu A/C model numbers enum fujitsu_ac_remote_model_t { - ARRAH2E = 1, ///< (1) AR-RAH2E, AR-RAC1E, AR-RAE1E, AR-RCE1E (Default) + ARRAH2E = 1, ///< (1) AR-RAH2E, AR-RAC1E, AR-RAE1E, AR-RCE1E, AR-RAH2U, + ///< AR-REG1U (Default) ///< Warning: Use on incorrect models can cause the A/C to lock ///< up, requring the A/C to be physically powered off to fix. ///< e.g. AR-RAH1U may lock up with a Swing command. @@ -133,7 +134,9 @@ enum fujitsu_ac_remote_model_t { /// Gree A/C model numbers enum gree_ac_remote_model_t { YAW1F = 1, // (1) Ultimate, EKOKAI, RusClimate (Default) - YBOFB, // (2) Green, YBOFB2, YAPOF3 + YBOFB, // (2) Green, YBOFB2, YAPOF3 + YX1FSF, // (3) Soleus Air window unit (Similar to YAW1F, but with an + // Operation mode of Energy Saver (Econo)) }; /// HAIER_AC176 A/C model numbers @@ -343,6 +346,11 @@ class IRsend { const uint16_t nbytes = kSanyoAc88StateLength, const uint16_t repeat = kSanyoAc88MinRepeat); #endif // SEND_SANYO_AC88 +#if SEND_SANYO_AC152 + void sendSanyoAc152(const uint8_t *data, + const uint16_t nbytes = kSanyoAc152StateLength, + const uint16_t repeat = kSanyoAc152MinRepeat); +#endif // SEND_SANYO_AC152 #if SEND_DISH // sendDISH() should typically be called with repeat=3 as DISH devices // expect the code to be sent at least 4 times. (code + 3 repeats = 4 codes) @@ -481,11 +489,21 @@ class IRsend { const uint16_t nbytes = kDaikin2StateLength, const uint16_t repeat = kDaikin2DefaultRepeat); #endif +#if SEND_DAIKIN200 + void sendDaikin200(const unsigned char data[], + const uint16_t nbytes = kDaikin200StateLength, + const uint16_t repeat = kDaikin200DefaultRepeat); +#endif // SEND_DAIKIN200 #if SEND_DAIKIN216 void sendDaikin216(const unsigned char data[], const uint16_t nbytes = kDaikin216StateLength, const uint16_t repeat = kDaikin216DefaultRepeat); -#endif +#endif // SEND_DAIKIN216 +#if SEND_DAIKIN312 + void sendDaikin312(const unsigned char data[], + const uint16_t nbytes = kDaikin312StateLength, + const uint16_t repeat = kDaikin312DefaultRepeat); +#endif // SEND_DAIKIN312 #if SEND_AIWA_RC_T501 void sendAiwaRCT501(uint64_t data, uint16_t nbits = kAiwaRcT501Bits, uint16_t repeat = kAiwaRcT501MinRepeats); @@ -557,6 +575,11 @@ class IRsend { void sendCarrierAC64(uint64_t data, uint16_t nbits = kCarrierAc64Bits, uint16_t repeat = kCarrierAc64MinRepeat); #endif +#if SEND_CARRIER_AC128 + void sendCarrierAC128(const uint8_t data[], + uint16_t nbytes = kCarrierAc128StateLength, + uint16_t repeat = kCarrierAc128MinRepeat); +#endif // SEND_CARRIER_AC128 #if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02 || SEND_HAIER_AC176) void sendHaierAC(const unsigned char data[], const uint16_t nbytes = kHaierACStateLength, @@ -567,6 +590,11 @@ class IRsend { const uint16_t nbytes = kHaierACYRW02StateLength, const uint16_t repeat = kHaierAcYrw02DefaultRepeat); #endif // SEND_HAIER_AC_YRW02 +#if SEND_HAIER_AC160 + void sendHaierAC160(const unsigned char data[], + const uint16_t nbytes = kHaierAC160StateLength, + const uint16_t repeat = kHaierAc160DefaultRepeat); +#endif // SEND_HAIER_AC160 #if SEND_HAIER_AC176 void sendHaierAC176(const unsigned char data[], const uint16_t nbytes = kHaierAC176StateLength, @@ -654,11 +682,16 @@ class IRsend { void sendVestelAc(const uint64_t data, const uint16_t nbits = kVestelAcBits, const uint16_t repeat = kNoRepeat); #endif +#if SEND_TCL96AC + void sendTcl96Ac(const unsigned char data[], + const uint16_t nbytes = kTcl96AcStateLength, + const uint16_t repeat = kTcl96AcDefaultRepeat); +#endif // SEND_TCL96AC #if SEND_TCL112AC void sendTcl112Ac(const unsigned char data[], const uint16_t nbytes = kTcl112AcStateLength, const uint16_t repeat = kTcl112AcDefaultRepeat); -#endif +#endif // SEND_TCL112AC #if SEND_TECO void sendTeco(const uint64_t data, const uint16_t nbits = kTecoBits, const uint16_t repeat = kNoRepeat); @@ -790,6 +823,20 @@ class IRsend { void sendAirton(const uint64_t data, const uint16_t nbits = kAirtonBits, const uint16_t repeat = kAirtonDefaultRepeat); #endif // SEND_AIRTON +#if SEND_TOTO + void sendToto(const uint64_t data, const uint16_t nbits = kTotoBits, + const uint16_t repeat = kTotoDefaultRepeat); +#endif // SEND_TOTO +#if SEND_CLIMABUTLER + void sendClimaButler(const uint64_t data, + const uint16_t nbits = kClimaButlerBits, + const uint16_t repeat = kNoRepeat); +#endif // SEND_CLIMABUTLER +#if SEND_BOSCH144 + void sendBosch144(const unsigned char data[], + const uint16_t nbytes = kBosch144StateLength, + const uint16_t repeat = kNoRepeat); +#endif // SEND_BOSCH144 protected: #ifdef UNIT_TEST diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp index 9c649f916..5bd25ed95 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp @@ -11,6 +11,8 @@ #include "IRremoteESP8266.h" #include "i18n.h" +#include "IRmacros.h" + #ifndef PROGMEM #define PROGMEM // Pretend we have the PROGMEM macro even if we really don't. #endif @@ -236,6 +238,7 @@ IRTEXT_CONST_STRING(kBitsStr, D_STR_BITS); ///< "Bits" // Model Names IRTEXT_CONST_STRING(kYaw1fStr, D_STR_YAW1F); ///< "YAW1F" IRTEXT_CONST_STRING(kYbofbStr, D_STR_YBOFB); ///< "YBOFB" +IRTEXT_CONST_STRING(kYx1fsfStr, D_STR_YX1FSF); ///< "YX1FSF" IRTEXT_CONST_STRING(kV9014557AStr, D_STR_V9014557_A); ///< "V9014557-A" IRTEXT_CONST_STRING(kV9014557BStr, D_STR_V9014557_B); ///< "V9014557-B" IRTEXT_CONST_STRING(kRlt0541htaaStr, D_STR_RLT0541HTA_A); ///< "R-LT0541-HTA-A" @@ -279,125 +282,258 @@ IRTEXT_CONST_STRING(kDg11j13aStr, D_STR_DG11J13A); ///< "DG11J13A" IRTEXT_CONST_STRING(kDg11j104Str, D_STR_DG11J104); ///< "DG11J104" IRTEXT_CONST_STRING(kDg11j191Str, D_STR_DG11J191); ///< "DG11J191" +#define D_STR_UNSUPPORTED "?" // Unsupported protocols will be showing as + // a question mark, check for length > 1 + // to show only currently included protocols // Protocol Names // Needs to be in decode_type_t order. IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) { D_STR_UNUSED "\x0" - D_STR_RC5 "\x0" - D_STR_RC6 "\x0" - D_STR_NEC "\x0" - D_STR_SONY "\x0" - D_STR_PANASONIC "\x0" - D_STR_JVC "\x0" - D_STR_SAMSUNG "\x0" - D_STR_WHYNTER "\x0" - D_STR_AIWA_RC_T501 "\x0" - D_STR_LG "\x0" - D_STR_SANYO "\x0" - D_STR_MITSUBISHI "\x0" - D_STR_DISH "\x0" - D_STR_SHARP "\x0" - D_STR_COOLIX "\x0" - D_STR_DAIKIN "\x0" - D_STR_DENON "\x0" - D_STR_KELVINATOR "\x0" - D_STR_SHERWOOD "\x0" - D_STR_MITSUBISHI_AC "\x0" - D_STR_RCMM "\x0" - D_STR_SANYO_LC7461 "\x0" - D_STR_RC5X "\x0" - D_STR_GREE "\x0" - D_STR_PRONTO "\x0" - D_STR_NEC_LIKE "\x0" - D_STR_ARGO "\x0" - D_STR_TROTEC "\x0" - D_STR_NIKAI "\x0" - D_STR_RAW "\x0" - D_STR_GLOBALCACHE "\x0" - D_STR_TOSHIBA_AC "\x0" - D_STR_FUJITSU_AC "\x0" - D_STR_MIDEA "\x0" - D_STR_MAGIQUEST "\x0" - D_STR_LASERTAG "\x0" - D_STR_CARRIER_AC "\x0" - D_STR_HAIER_AC "\x0" - D_STR_MITSUBISHI2 "\x0" - D_STR_HITACHI_AC "\x0" - D_STR_HITACHI_AC1 "\x0" - D_STR_HITACHI_AC2 "\x0" - D_STR_GICABLE "\x0" - D_STR_HAIER_AC_YRW02 "\x0" - D_STR_WHIRLPOOL_AC "\x0" - D_STR_SAMSUNG_AC "\x0" - D_STR_LUTRON "\x0" - D_STR_ELECTRA_AC "\x0" - D_STR_PANASONIC_AC "\x0" - D_STR_PIONEER "\x0" - D_STR_LG2 "\x0" - D_STR_MWM "\x0" - D_STR_DAIKIN2 "\x0" - D_STR_VESTEL_AC "\x0" - D_STR_TECO "\x0" - D_STR_SAMSUNG36 "\x0" - D_STR_TCL112AC "\x0" - D_STR_LEGOPF "\x0" - D_STR_MITSUBISHI_HEAVY_88 "\x0" - D_STR_MITSUBISHI_HEAVY_152 "\x0" - D_STR_DAIKIN216 "\x0" - D_STR_SHARP_AC "\x0" - D_STR_GOODWEATHER "\x0" - D_STR_INAX "\x0" - D_STR_DAIKIN160 "\x0" - D_STR_NEOCLIMA "\x0" - D_STR_DAIKIN176 "\x0" - D_STR_DAIKIN128 "\x0" - D_STR_AMCOR "\x0" - D_STR_DAIKIN152 "\x0" - D_STR_MITSUBISHI136 "\x0" - D_STR_MITSUBISHI112 "\x0" - D_STR_HITACHI_AC424 "\x0" - D_STR_SONY_38K "\x0" - D_STR_EPSON "\x0" - D_STR_SYMPHONY "\x0" - D_STR_HITACHI_AC3 "\x0" - D_STR_DAIKIN64 "\x0" - D_STR_AIRWELL "\x0" - D_STR_DELONGHI_AC "\x0" - D_STR_DOSHISHA "\x0" - D_STR_MULTIBRACKETS "\x0" - D_STR_CARRIER_AC40 "\x0" - D_STR_CARRIER_AC64 "\x0" - D_STR_HITACHI_AC344 "\x0" - D_STR_CORONA_AC "\x0" - D_STR_MIDEA24 "\x0" - D_STR_ZEPEAL "\x0" - D_STR_SANYO_AC "\x0" - D_STR_VOLTAS "\x0" - D_STR_METZ "\x0" - D_STR_TRANSCOLD "\x0" - D_STR_TECHNIBEL_AC "\x0" - D_STR_MIRAGE "\x0" - D_STR_ELITESCREENS "\x0" - D_STR_PANASONIC_AC32 "\x0" - D_STR_MILESTAG2 "\x0" - D_STR_ECOCLIM "\x0" - D_STR_XMP "\x0" - D_STR_TRUMA "\x0" - D_STR_HAIER_AC176 "\x0" - D_STR_TEKNOPOINT "\x0" - D_STR_KELON "\x0" - D_STR_TROTEC_3550 "\x0" - D_STR_SANYO_AC88 "\x0" - D_STR_BOSE "\x0" - D_STR_ARRIS "\x0" - D_STR_RHOSS "\x0" - D_STR_AIRTON "\x0" - D_STR_COOLIX48 "\x0" - D_STR_HITACHI_AC264 "\x0" - D_STR_KELON168 "\x0" - D_STR_HITACHI_AC296 "\x0" - ///< New protocol strings should be added just above this line. + COND(DECODE_RC5 || SEND_RC5, + D_STR_RC5, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_RC6 || SEND_RC6, + D_STR_RC6, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_NEC || SEND_NEC, + D_STR_NEC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SONY || SEND_SONY, + D_STR_SONY, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_PANASONIC || SEND_PANASONIC, + D_STR_PANASONIC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_JVC || SEND_JVC, + D_STR_JVC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SAMSUNG || SEND_SAMSUNG, + D_STR_SAMSUNG, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_WHYNTER || SEND_WHYNTER, + D_STR_WHYNTER, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_AIWA_RC_T501 || SEND_AIWA_RC_T501, + D_STR_AIWA_RC_T501, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_LG || SEND_LG, + D_STR_LG, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SANYO || SEND_SANYO, + D_STR_SANYO, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MITSUBISHI || SEND_MITSUBISHI, + D_STR_MITSUBISHI, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DISH || SEND_DISH, + D_STR_DISH, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SHARP || SEND_SHARP, + D_STR_SHARP, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_COOLIX || SEND_COOLIX, + D_STR_COOLIX, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN || SEND_DAIKIN, + D_STR_DAIKIN, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DENON || SEND_DENON, + D_STR_DENON, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_KELVINATOR || SEND_KELVINATOR, + D_STR_KELVINATOR, D_STR_UNSUPPORTED) "\x0" + COND(SEND_SHERWOOD, + D_STR_SHERWOOD, D_STR_UNSUPPORTED) "\x0" // SEND-ONLY + COND(DECODE_MITSUBISHI_AC || SEND_MITSUBISHI_AC, + D_STR_MITSUBISHI_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_RCMM || SEND_RCMM, + D_STR_RCMM, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SANYO || SEND_SANYO, + D_STR_SANYO_LC7461, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_RC5 || SEND_RC5, + D_STR_RC5X, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_GREE || SEND_GREE, + D_STR_GREE, D_STR_UNSUPPORTED) "\x0" + COND(SEND_PRONTO, + D_STR_PRONTO, D_STR_UNSUPPORTED) "\x0" // SEND-ONLY + COND(DECODE_NEC || SEND_NEC, + D_STR_NEC_LIKE, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_ARGO || SEND_ARGO, + D_STR_ARGO, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TROTEC || SEND_TROTEC, + D_STR_TROTEC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_NIKAI || SEND_NIKAI, + D_STR_NIKAI, D_STR_UNSUPPORTED) "\x0" + COND(SEND_RAW, + D_STR_RAW, D_STR_UNSUPPORTED) "\x0" // SEND-ONLY + COND(SEND_GLOBALCACHE, + D_STR_GLOBALCACHE, D_STR_UNSUPPORTED) "\x0" // SEND + COND(DECODE_TOSHIBA_AC || SEND_TOSHIBA_AC, + D_STR_TOSHIBA_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_FUJITSU_AC || SEND_FUJITSU_AC, + D_STR_FUJITSU_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MIDEA || SEND_MIDEA, + D_STR_MIDEA, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MAGIQUEST || SEND_MAGIQUEST, + D_STR_MAGIQUEST, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_LASERTAG || SEND_LASERTAG, + D_STR_LASERTAG, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_CARRIER_AC || SEND_CARRIER_AC, + D_STR_CARRIER_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HAIER_AC || SEND_HAIER_AC, + D_STR_HAIER_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MITSUBISHI2 || SEND_MITSUBISHI2, + D_STR_MITSUBISHI2, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HITACHI_AC || SEND_HITACHI_AC, + D_STR_HITACHI_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HITACHI_AC1 || SEND_HITACHI_AC1, + D_STR_HITACHI_AC1, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HITACHI_AC2 || SEND_HITACHI_AC2, + D_STR_HITACHI_AC2, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_GICABLE || SEND_GICABLE, + D_STR_GICABLE, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HAIER_AC_YRW02 || SEND_HAIER_AC_YRW02, + D_STR_HAIER_AC_YRW02, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_WHIRLPOOL_AC || SEND_WHIRLPOOL_AC, + D_STR_WHIRLPOOL_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SAMSUNG_AC || SEND_SAMSUNG_AC, + D_STR_SAMSUNG_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_LUTRON || SEND_LUTRON, + D_STR_LUTRON, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_ELECTRA_AC || SEND_ELECTRA_AC, + D_STR_ELECTRA_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_PANASONIC_AC || SEND_PANASONIC_AC, + D_STR_PANASONIC_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_PIONEER || SEND_PIONEER, + D_STR_PIONEER, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_LG || SEND_LG, + D_STR_LG2, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MWM || SEND_MWM, + D_STR_MWM, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN2 || SEND_DAIKIN2, + D_STR_DAIKIN2, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_VESTEL_AC || SEND_VESTEL_AC, + D_STR_VESTEL_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TECO || SEND_TECO, + D_STR_TECO, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SAMSUNG36 || SEND_SAMSUNG36, + D_STR_SAMSUNG36, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TCL112AC || SEND_TCL112AC, + D_STR_TCL112AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_LEGOPF || SEND_LEGOPF, + D_STR_LEGOPF, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MITSUBISHIHEAVY || SEND_MITSUBISHIHEAVY, + D_STR_MITSUBISHI_HEAVY_88, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MITSUBISHIHEAVY || SEND_MITSUBISHIHEAVY, + D_STR_MITSUBISHI_HEAVY_152, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN216 || SEND_DAIKIN216, + D_STR_DAIKIN216, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SHARP_AC || SEND_SHARP_AC, + D_STR_SHARP_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_GOODWEATHER || SEND_GOODWEATHER, + D_STR_GOODWEATHER, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_INAX || SEND_INAX, + D_STR_INAX, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN160 || SEND_DAIKIN160, + D_STR_DAIKIN160, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_NEOCLIMA || SEND_NEOCLIMA, + D_STR_NEOCLIMA, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN176 || SEND_DAIKIN176, + D_STR_DAIKIN176, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN128 || SEND_DAIKIN128, + D_STR_DAIKIN128, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_AMCOR || SEND_AMCOR, + D_STR_AMCOR, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN152 || SEND_DAIKIN152, + D_STR_DAIKIN152, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MITSUBISHI136 || SEND_MITSUBISHI136, + D_STR_MITSUBISHI136, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MITSUBISHI112 || SEND_MITSUBISHI112, + D_STR_MITSUBISHI112, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HITACHI_AC424 || SEND_HITACHI_AC424, + D_STR_HITACHI_AC424, D_STR_UNSUPPORTED) "\x0" + COND(SEND_SONY, + D_STR_SONY_38K, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_EPSON || SEND_EPSON, + D_STR_EPSON, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SYMPHONY || SEND_SYMPHONY, + D_STR_SYMPHONY, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HITACHI_AC3 || SEND_HITACHI_AC3, + D_STR_HITACHI_AC3, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN64 || SEND_DAIKIN64, + D_STR_DAIKIN64, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_AIRWELL || SEND_AIRWELL, + D_STR_AIRWELL, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DELONGHI_AC || SEND_DELONGHI_AC, + D_STR_DELONGHI_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DOSHISHA || SEND_DOSHISHA, + D_STR_DOSHISHA, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MULTIBRACKETS || SEND_MULTIBRACKETS, + D_STR_MULTIBRACKETS, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_CARRIER_AC40 || SEND_CARRIER_AC40, + D_STR_CARRIER_AC40, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_CARRIER_AC64 || SEND_CARRIER_AC64, + D_STR_CARRIER_AC64, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HITACHI_AC344 || SEND_HITACHI_AC344, + D_STR_HITACHI_AC344, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_CORONA_AC || SEND_CORONA_AC, + D_STR_CORONA_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MIDEA24 || SEND_MIDEA24, + D_STR_MIDEA24, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_ZEPEAL || SEND_ZEPEAL, + D_STR_ZEPEAL, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SANYO_AC || SEND_SANYO_AC, + D_STR_SANYO_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_VOLTAS || SEND_VOLTAS, + D_STR_VOLTAS, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_METZ || SEND_METZ, + D_STR_METZ, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TRANSCOLD || SEND_TRANSCOLD, + D_STR_TRANSCOLD, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TECHNIBEL_AC || SEND_TECHNIBEL_AC, + D_STR_TECHNIBEL_AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MIRAGE || SEND_MIRAGE, + D_STR_MIRAGE, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_ELITESCREENS || SEND_ELITESCREENS, + D_STR_ELITESCREENS, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_PANASONIC_AC32 || SEND_PANASONIC_AC32, + D_STR_PANASONIC_AC32, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_MILESTAG2 || SEND_MILESTAG2, + D_STR_MILESTAG2, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_ECOCLIM || SEND_ECOCLIM, + D_STR_ECOCLIM, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_XMP || SEND_XMP, + D_STR_XMP, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TRUMA || SEND_TRUMA, + D_STR_TRUMA, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HAIER_AC176 || SEND_HAIER_AC176, + D_STR_HAIER_AC176, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TEKNOPOINT || SEND_TEKNOPOINT, + D_STR_TEKNOPOINT, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_KELON || SEND_KELON, + D_STR_KELON, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TROTEC_3550 || SEND_TROTEC_3550, + D_STR_TROTEC_3550, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SANYO_AC88 || SEND_SANYO_AC88, + D_STR_SANYO_AC88, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_BOSE || SEND_BOSE, + D_STR_BOSE, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_ARRIS || SEND_ARRIS, + D_STR_ARRIS, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_RHOSS || SEND_RHOSS, + D_STR_RHOSS, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_AIRTON || SEND_AIRTON, + D_STR_AIRTON, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_COOLIX48 || SEND_COOLIX48, + D_STR_COOLIX48, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HITACHI_AC264 || SEND_HITACHI_AC264, + D_STR_HITACHI_AC264, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_KELON168 || SEND_KELON168, + D_STR_KELON168, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HITACHI_AC296 || SEND_HITACHI_AC296, + D_STR_HITACHI_AC296, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN200 || SEND_DAIKIN200, + D_STR_DAIKIN200, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_HAIER_AC160 || SEND_HAIER_AC160, + D_STR_HAIER_AC160, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_CARRIER_AC128 || SEND_CARRIER_AC128, + D_STR_CARRIER_AC128, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TOTO || SEND_TOTO, + D_STR_TOTO, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_CLIMABUTLER || SEND_CLIMABUTLER, + D_STR_CLIMABUTLER, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_TCL96AC || SEND_TCL96AC, + D_STR_TCL96AC, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_BOSCH144 || SEND_BOSCH144, + D_STR_BOSCH144, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_SANYO_AC152 || SEND_SANYO_AC152, + D_STR_SANYO_AC152, D_STR_UNSUPPORTED) "\x0" + COND(DECODE_DAIKIN312 || SEND_DAIKIN312, + D_STR_DAIKIN312, D_STR_UNSUPPORTED) "\x0" + ///< New protocol (macro) strings should be added just above this line. "\x0" ///< This string requires double null termination. }; - IRTEXT_CONST_BLOB_PTR(kAllProtocolNamesStr); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h index aab671314..7bd4fbed3 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h @@ -44,8 +44,8 @@ extern IRTEXT_CONST_PTR(kArrah2eStr); extern IRTEXT_CONST_PTR(kArreb1eStr); extern IRTEXT_CONST_PTR(kArrew4eStr); extern IRTEXT_CONST_PTR(kArry4Str); -extern IRTEXT_CONST_PTR(kAutomaticStr); extern IRTEXT_CONST_PTR(kAutoStr); +extern IRTEXT_CONST_PTR(kAutomaticStr); extern IRTEXT_CONST_PTR(kBeepStr); extern IRTEXT_CONST_PTR(kBitsStr); extern IRTEXT_CONST_PTR(kBottomStr); @@ -64,13 +64,13 @@ extern IRTEXT_CONST_PTR(kClockStr); extern IRTEXT_CONST_PTR(kCodeStr); extern IRTEXT_CONST_PTR(kColonSpaceStr); extern IRTEXT_CONST_PTR(kComfortStr); -extern IRTEXT_CONST_PTR(kCommandStr); extern IRTEXT_CONST_PTR(kCommaSpaceStr); -extern IRTEXT_CONST_PTR(kCoolingStr); +extern IRTEXT_CONST_PTR(kCommandStr); extern IRTEXT_CONST_PTR(kCoolStr); +extern IRTEXT_CONST_PTR(kCoolingStr); extern IRTEXT_CONST_PTR(kDashStr); -extern IRTEXT_CONST_PTR(kDaysStr); extern IRTEXT_CONST_PTR(kDayStr); +extern IRTEXT_CONST_PTR(kDaysStr); extern IRTEXT_CONST_PTR(kDehumidifyStr); extern IRTEXT_CONST_PTR(kDg11j104Str); extern IRTEXT_CONST_PTR(kDg11j13aStr); @@ -80,18 +80,18 @@ extern IRTEXT_CONST_PTR(kDirectStr); extern IRTEXT_CONST_PTR(kDisplayTempStr); extern IRTEXT_CONST_PTR(kDkeStr); extern IRTEXT_CONST_PTR(kDownStr); -extern IRTEXT_CONST_PTR(kDryingStr); extern IRTEXT_CONST_PTR(kDryStr); +extern IRTEXT_CONST_PTR(kDryingStr); extern IRTEXT_CONST_PTR(kEconoStr); extern IRTEXT_CONST_PTR(kEconoToggleStr); extern IRTEXT_CONST_PTR(kEyeAutoStr); extern IRTEXT_CONST_PTR(kEyeStr); extern IRTEXT_CONST_PTR(kFalseStr); extern IRTEXT_CONST_PTR(kFanOnlyNoSpaceStr); -extern IRTEXT_CONST_PTR(kFan_OnlyStr); extern IRTEXT_CONST_PTR(kFanOnlyStr); extern IRTEXT_CONST_PTR(kFanOnlyWithSpaceStr); extern IRTEXT_CONST_PTR(kFanStr); +extern IRTEXT_CONST_PTR(kFan_OnlyStr); extern IRTEXT_CONST_PTR(kFastStr); extern IRTEXT_CONST_PTR(kFilterStr); extern IRTEXT_CONST_PTR(kFixedStr); @@ -100,21 +100,21 @@ extern IRTEXT_CONST_PTR(kFreshStr); extern IRTEXT_CONST_PTR(kGe6711ar2853mStr); extern IRTEXT_CONST_PTR(kGz055be1Str); extern IRTEXT_CONST_PTR(kHealthStr); -extern IRTEXT_CONST_PTR(kHeatingStr); extern IRTEXT_CONST_PTR(kHeatStr); -extern IRTEXT_CONST_PTR(kHighestStr); -extern IRTEXT_CONST_PTR(kHighStr); +extern IRTEXT_CONST_PTR(kHeatingStr); extern IRTEXT_CONST_PTR(kHiStr); +extern IRTEXT_CONST_PTR(kHighStr); +extern IRTEXT_CONST_PTR(kHighestStr); extern IRTEXT_CONST_PTR(kHoldStr); -extern IRTEXT_CONST_PTR(kHoursStr); extern IRTEXT_CONST_PTR(kHourStr); +extern IRTEXT_CONST_PTR(kHoursStr); extern IRTEXT_CONST_PTR(kHumidStr); -extern IRTEXT_CONST_PTR(kIdStr); extern IRTEXT_CONST_PTR(kIFeelStr); +extern IRTEXT_CONST_PTR(kISeeStr); +extern IRTEXT_CONST_PTR(kIdStr); extern IRTEXT_CONST_PTR(kIndirectStr); extern IRTEXT_CONST_PTR(kInsideStr); extern IRTEXT_CONST_PTR(kIonStr); -extern IRTEXT_CONST_PTR(kISeeStr); extern IRTEXT_CONST_PTR(kJkeStr); extern IRTEXT_CONST_PTR(kKkg29ac1Str); extern IRTEXT_CONST_PTR(kKkg9ac1Str); @@ -126,29 +126,29 @@ extern IRTEXT_CONST_PTR(kLg6711a20083vStr); extern IRTEXT_CONST_PTR(kLightStr); extern IRTEXT_CONST_PTR(kLightToggleStr); extern IRTEXT_CONST_PTR(kLkeStr); -extern IRTEXT_CONST_PTR(kLockStr); extern IRTEXT_CONST_PTR(kLoStr); +extern IRTEXT_CONST_PTR(kLockStr); extern IRTEXT_CONST_PTR(kLoudStr); +extern IRTEXT_CONST_PTR(kLowStr); extern IRTEXT_CONST_PTR(kLowerStr); extern IRTEXT_CONST_PTR(kLowestStr); -extern IRTEXT_CONST_PTR(kLowStr); extern IRTEXT_CONST_PTR(kManualStr); -extern IRTEXT_CONST_PTR(kMaximumStr); extern IRTEXT_CONST_PTR(kMaxLeftNoSpaceStr); extern IRTEXT_CONST_PTR(kMaxLeftStr); extern IRTEXT_CONST_PTR(kMaxRightNoSpaceStr); extern IRTEXT_CONST_PTR(kMaxRightStr); extern IRTEXT_CONST_PTR(kMaxStr); -extern IRTEXT_CONST_PTR(kMediumStr); +extern IRTEXT_CONST_PTR(kMaximumStr); extern IRTEXT_CONST_PTR(kMedStr); -extern IRTEXT_CONST_PTR(kMiddleStr); +extern IRTEXT_CONST_PTR(kMediumStr); extern IRTEXT_CONST_PTR(kMidStr); -extern IRTEXT_CONST_PTR(kMinimumStr); +extern IRTEXT_CONST_PTR(kMiddleStr); extern IRTEXT_CONST_PTR(kMinStr); -extern IRTEXT_CONST_PTR(kMinutesStr); +extern IRTEXT_CONST_PTR(kMinimumStr); extern IRTEXT_CONST_PTR(kMinuteStr); -extern IRTEXT_CONST_PTR(kModelStr); +extern IRTEXT_CONST_PTR(kMinutesStr); extern IRTEXT_CONST_PTR(kModeStr); +extern IRTEXT_CONST_PTR(kModelStr); extern IRTEXT_CONST_PTR(kMouldStr); extern IRTEXT_CONST_PTR(kMoveStr); extern IRTEXT_CONST_PTR(kNAStr); @@ -171,9 +171,9 @@ extern IRTEXT_CONST_PTR(kPanasonicPkrStr); extern IRTEXT_CONST_PTR(kPanasonicRkrStr); extern IRTEXT_CONST_PTR(kPkrStr); extern IRTEXT_CONST_PTR(kPowerButtonStr); -extern IRTEXT_CONST_PTR(kPowerfulStr); extern IRTEXT_CONST_PTR(kPowerStr); extern IRTEXT_CONST_PTR(kPowerToggleStr); +extern IRTEXT_CONST_PTR(kPowerfulStr); extern IRTEXT_CONST_PTR(kPreviousPowerStr); extern IRTEXT_CONST_PTR(kProtocolStr); extern IRTEXT_CONST_PTR(kPurifyStr); @@ -188,8 +188,8 @@ extern IRTEXT_CONST_PTR(kRlt0541htaaStr); extern IRTEXT_CONST_PTR(kRlt0541htabStr); extern IRTEXT_CONST_PTR(kRoomStr); extern IRTEXT_CONST_PTR(kSaveStr); -extern IRTEXT_CONST_PTR(kSecondsStr); extern IRTEXT_CONST_PTR(kSecondStr); +extern IRTEXT_CONST_PTR(kSecondsStr); extern IRTEXT_CONST_PTR(kSensorStr); extern IRTEXT_CONST_PTR(kSensorTempStr); extern IRTEXT_CONST_PTR(kSetStr); @@ -222,8 +222,8 @@ extern IRTEXT_CONST_PTR(kTurboStr); extern IRTEXT_CONST_PTR(kTurboToggleStr); extern IRTEXT_CONST_PTR(kTypeStr); extern IRTEXT_CONST_PTR(kUnknownStr); -extern IRTEXT_CONST_PTR(kUpperStr); extern IRTEXT_CONST_PTR(kUpStr); +extern IRTEXT_CONST_PTR(kUpperStr); extern IRTEXT_CONST_PTR(kV9014557AStr); extern IRTEXT_CONST_PTR(kV9014557BStr); extern IRTEXT_CONST_PTR(kVaneStr); @@ -235,6 +235,7 @@ extern IRTEXT_CONST_PTR(kXFanStr); extern IRTEXT_CONST_PTR(kYaw1fStr); extern IRTEXT_CONST_PTR(kYbofbStr); extern IRTEXT_CONST_PTR(kYesStr); +extern IRTEXT_CONST_PTR(kYx1fsfStr); extern IRTEXT_CONST_PTR(kZoneFollowStr); extern IRTEXT_CONST_PTR(kAllProtocolNamesStr); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp index b284a4129..7c59228c0 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp @@ -172,6 +172,8 @@ bool hasACState(const decode_type_t protocol) { // This is kept sorted by name case AMCOR: case ARGO: + case BOSCH144: + case CARRIER_AC128: case CORONA_AC: case DAIKIN: case DAIKIN128: @@ -179,12 +181,15 @@ bool hasACState(const decode_type_t protocol) { case DAIKIN160: case DAIKIN176: case DAIKIN2: + case DAIKIN200: case DAIKIN216: + case DAIKIN312: case ELECTRA_AC: case FUJITSU_AC: case GREE: case HAIER_AC: case HAIER_AC_YRW02: + case HAIER_AC160: case HAIER_AC176: case HITACHI_AC: case HITACHI_AC1: @@ -209,7 +214,9 @@ bool hasACState(const decode_type_t protocol) { case SAMSUNG_AC: case SANYO_AC: case SANYO_AC88: + case SANYO_AC152: case SHARP_AC: + case TCL96AC: case TCL112AC: case TEKNOPOINT: case TOSHIBA_AC: @@ -605,9 +612,10 @@ namespace irutils { break; case decode_type_t::GREE: switch (model) { - case gree_ac_remote_model_t::YAW1F: return kYaw1fStr; - case gree_ac_remote_model_t::YBOFB: return kYbofbStr; - default: return kUnknownStr; + case gree_ac_remote_model_t::YAW1F: return kYaw1fStr; + case gree_ac_remote_model_t::YBOFB: return kYbofbStr; + case gree_ac_remote_model_t::YX1FSF: return kYx1fsfStr; + default: return kUnknownStr; } break; case decode_type_t::HAIER_AC176: diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Argo.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Argo.cpp index 04cde67ed..680178ceb 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Argo.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Argo.cpp @@ -63,6 +63,28 @@ void IRArgoAC::begin(void) { _irsend.begin(); } void IRArgoAC::send(const uint16_t repeat) { _irsend.sendArgo(getRaw(), kArgoStateLength, repeat); } + +/// Send current room temperature for the iFeel feature as a silent IR +/// message (no acknowledgement from the device). +/// @param[in] temp The temperature in degrees celsius. +/// @param[in] repeat Nr. of times the message will be repeated. +void IRArgoAC::sendSensorTemp(const uint8_t temp, const uint16_t repeat) { + uint8_t tempc = temp - kArgoTempDelta; + uint8_t check = 52 + tempc; + uint8_t end = 0b011; + + ArgoProtocol data; + data.raw[0] = 0b10101100; + data.raw[1] = 0b11110101; + data.raw[2] = (tempc << 3) | (check >> 5); + data.raw[3] = (check << 3) | end; + for (uint8_t i = 4; i < kArgoStateLength; i++) data.raw[i] = 0x0; + uint8_t sum = IRArgoAC::calcChecksum(data.raw, kArgoStateLength); + data.raw[10] = 0b00000010; + data.Sum = sum; + + _irsend.sendArgo(data.raw, kArgoStateLength, repeat); +} #endif // SEND_ARGO /// Verify the checksum is valid for a given state. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Argo.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Argo.h index 6ceb58e42..8ef7bb386 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Argo.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Argo.h @@ -131,6 +131,8 @@ class IRArgoAC { #if SEND_ARGO void send(const uint16_t repeat = kArgoDefaultRepeat); + void sendSensorTemp(const uint8_t temp, + const uint16_t repeat = kArgoDefaultRepeat); /// Run the calibration to calculate uSec timing offsets for this platform. /// @return The uSec timing offset needed per modulation of the IR Led. /// @note This will produce a 65ms IR signal pulse at 38kHz. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Bosch.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Bosch.cpp new file mode 100644 index 000000000..56e9d2b99 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Bosch.cpp @@ -0,0 +1,331 @@ +// Copyright 2022 David Conran +// Copyright 2022 Nico Thien +/// @file +/// @brief Support for the Bosch A/C / heatpump protocol +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 + +#include "ir_Bosch.h" + +#if SEND_BOSCH144 +/// Send a Bosch 144-bit / 18-byte message (96-bit message are also possible) +/// Status: BETA / Probably Working. +/// @param[in] data The message to be sent. +/// @param[in] nbytes The number of bytes of message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +void IRsend::sendBosch144(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + // nbytes is required to be a multiple of kBosch144BytesPerSection. + if (nbytes % kBosch144BytesPerSection != 0)return; + // Set IR carrier frequency + enableIROut(kBoschFreq); + + for (uint16_t r = 0; r <= repeat; r++) { + for (uint16_t offset=0; offset < nbytes; offset += kBosch144BytesPerSection) + // Section Header + Data + Footer + sendGeneric(kBoschHdrMark, kBoschHdrSpace, + kBoschBitMark, kBoschOneSpace, + kBoschBitMark, kBoschZeroSpace, + kBoschBitMark, kBoschFooterSpace, + data + offset, kBosch144BytesPerSection, + kBoschFreq, true, 0, kDutyDefault); + space(kDefaultMessageGap); // Complete guess + } +} + +#endif // SEND_BOSCH144 + +/// Class constructor. +/// @param[in] pin GPIO to be used when sending. +/// @param[in] inverted Is the output signal to be inverted? +/// @param[in] use_modulation Is frequency modulation to be used? +IRBosch144AC::IRBosch144AC(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { stateReset(); } + +/// Reset the internal state to a fixed known good state. +void IRBosch144AC::stateReset(void) { + setRaw(kBosch144DefaultState, kBosch144StateLength); + setPower(true); +} + +/// Set up hardware to be able to send a message. +void IRBosch144AC::begin(void) { _irsend.begin(); } + +#if SEND_BOSCH144 +/// Send the current internal state as an IR message. +/// @param[in] repeat Nr. of times the message will be repeated. +void IRBosch144AC::send(const uint16_t repeat) { + if (!powerFlag) { // "Off" is a 96bit message + _irsend.sendBosch144(kBosch144Off, sizeof(kBosch144Off), repeat); + } else { + _irsend.sendBosch144(getRaw(), kBosch144StateLength, repeat); + } // other 96bit messages are not yet supported +} +#endif // SEND_BOSCH144 + +/// Get a copy of the internal state as a valid code for this protocol. +/// @return A valid code for this protocol based on the current internal state. +unsigned char* IRBosch144AC::getRaw(void) { + setInvertBytes(); + setCheckSumS3(); + return _.raw; +} + +/// Set the internal state from a valid code for this protocol. +/// @param[in] new_code A valid code for this protocol. +/// @param[in] length Size of the array being passed in in bytes. +void IRBosch144AC::setRaw(const uint8_t new_code[], const uint16_t length) { + const uint16_t len = min(length, kBosch144StateLength); + const uint16_t lenOff = sizeof(kBosch144Off); +// Is it an off message? + if (memcmp(kBosch144Off, new_code, min(lenOff, len)) == 0) + setPower(false); // It is. + else + setPower(true); + memcpy(_.raw, new_code, len); +} + +void IRBosch144AC::setPower(const bool on) { + powerFlag = on; +} + +bool IRBosch144AC::getPower(void) const { + return powerFlag; +} + +void IRBosch144AC::setTempRaw(const uint8_t code) { + _.TempS1 = _.TempS2 = code >> 1; // save 4 bits in S1 and S2 + _.TempS3 = code & 1; // save 1 bit in Section3 +} + +/// Set the temperature. +/// @param[in] degrees The temperature in degrees celsius. +void IRBosch144AC::setTemp(const uint8_t degrees) { + uint8_t temp = max(kBosch144TempMin, degrees); + temp = min(kBosch144TempMax, temp); + setTempRaw(kBosch144TempMap[temp - kBosch144TempMin]); +} + +uint8_t IRBosch144AC::getTemp(void) const { + uint8_t temp = (_.TempS1 << 1) + _.TempS3; + uint8_t retemp = 25; + for (uint8_t i = 0; i < kBosch144TempRange; i++) { + if (temp == kBosch144TempMap[i]) { + retemp = kBosch144TempMin + i; + } + } + return retemp; +} + +/// Set the speed of the fan. +/// @param[in] speed The desired setting. +void IRBosch144AC::setFan(const uint16_t speed) { + _.FanS1 = _.FanS2 = speed >> 6; // save 3 bits in S1 and S2 + _.FanS3 = speed & 0b111111; // save 6 bits in Section3 +} + +uint16_t IRBosch144AC::getFan(void) const { + return (_.FanS1 << 6) + _.FanS3; +} + +/// Set the desired operation mode. +/// @param[in] mode The desired operation mode. +void IRBosch144AC::setMode(const uint8_t mode) { + _.ModeS1 = _.ModeS2 = mode >> 1; // save 2 bits in S1 and S2 + _.ModeS3 = mode & 0b1; // save 1 bit in Section3 + if (mode == kBosch144Auto || mode == kBosch144Dry) { + _.FanS1 = _.FanS2 = 0b000; // save 3 bits in S1 and S2 + _.FanS3 = kBosch144FanAuto0; // save 6 bits in Section3 + } +} + +uint8_t IRBosch144AC::getMode(void) const { + return (_.ModeS1 << 1) + _.ModeS3; +} + +/// Set the Quiet mode of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRBosch144AC::setQuiet(const bool on) { + _.Quiet = on; // save 1 bit in Section3 + setFan(kBosch144FanAuto); // set Fan -> Auto +} + +/// Get the Quiet mode of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRBosch144AC::getQuiet(void) const { return _.Quiet; } + +/// Convert a stdAc::opmode_t enum into its native mode. +/// @param[in] mode The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRBosch144AC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kBosch144Cool; + case stdAc::opmode_t::kHeat: + return kBosch144Heat; + case stdAc::opmode_t::kDry: + return kBosch144Dry; + case stdAc::opmode_t::kFan: + return kBosch144Fan; + default: + return kBosch144Auto; + } +} + +/// Convert a stdAc::fanspeed_t enum into it's native speed. +/// @param[in] speed The enum to be converted. +/// @return The native equivalent of the enum. +uint16_t IRBosch144AC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kBosch144Fan20; + case stdAc::fanspeed_t::kLow: + return kBosch144Fan40; + case stdAc::fanspeed_t::kMedium: + return kBosch144Fan60; + case stdAc::fanspeed_t::kHigh: + return kBosch144Fan80; + case stdAc::fanspeed_t::kMax: + return kBosch144Fan100; + default: + return kBosch144FanAuto; + } +} + +/// Convert a native mode into its stdAc equivalent. +/// @param[in] mode The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::opmode_t IRBosch144AC::toCommonMode(const uint8_t mode) { + switch (mode) { + case kBosch144Cool: return stdAc::opmode_t::kCool; + case kBosch144Heat: return stdAc::opmode_t::kHeat; + case kBosch144Dry: return stdAc::opmode_t::kDry; + case kBosch144Fan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; + } +} + +/// Convert a native fan speed into its stdAc equivalent. +/// @param[in] speed The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::fanspeed_t IRBosch144AC::toCommonFanSpeed(const uint16_t speed) { + switch (speed) { + case kBosch144Fan100: return stdAc::fanspeed_t::kMax; + case kBosch144Fan80: return stdAc::fanspeed_t::kHigh; + case kBosch144Fan60: return stdAc::fanspeed_t::kMedium; + case kBosch144Fan40: return stdAc::fanspeed_t::kLow; + case kBosch144Fan20: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; + } +} + +/// Convert the current internal state into its stdAc::state_t equivalent. +/// @return The stdAc equivalent of the native settings. +stdAc::state_t IRBosch144AC::toCommon(void) const { + stdAc::state_t result{}; + result.protocol = decode_type_t::BOSCH144; + result.power = getPower(); + result.mode = toCommonMode(getMode()); + result.celsius = true; + result.degrees = getTemp(); + result.fanspeed = toCommonFanSpeed(getFan()); + result.quiet = getQuiet(); + // 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.clean = false; + result.beep = false; + result.clock = -1; + result.sleep = -1; + return result; +} + +/// Convert the current internal state into a human readable string. +/// @return A human readable string. +String IRBosch144AC::toString(void) const { + uint8_t mode = getMode(); + uint8_t fan = static_cast(toCommonFanSpeed(getFan())); + String result = ""; + result.reserve(70); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(mode, kBosch144Auto, kBosch144Cool, + kBosch144Heat, kBosch144Dry, kBosch144Fan); + result += addFanToString(fan, static_cast(stdAc::fanspeed_t::kMax), + static_cast(stdAc::fanspeed_t::kMin), + static_cast(stdAc::fanspeed_t::kAuto), + static_cast(stdAc::fanspeed_t::kAuto), + static_cast(stdAc::fanspeed_t::kMedium)); + result += addTempToString(getTemp()); + result += addBoolToString(_.Quiet, kQuietStr); + return result; +} + +void IRBosch144AC::setInvertBytes() { + for (uint8_t i = 0; i <= 10; i += 2) { + _.raw[i + 1] = ~_.raw[i]; + } +} + +void IRBosch144AC::setCheckSumS3() { + _.ChecksumS3 = sumBytes(&(_.raw[12]), 5); +} + +#if DECODE_BOSCH144 +/// Decode the supplied Bosch 144-bit / 18-byte A/C message. +/// Status: STABLE / Confirmed Working. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// result. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +bool IRrecv::decodeBosch144(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * nbits + + kBosch144NrOfSections * (kHeader + kFooter) - + 1 + offset) + return false; // Can't possibly be a valid BOSCH144 message. + if (strict && nbits != kBosch144Bits) + return false; // Not strictly a BOSCH144 message. + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + if (nbits % kBosch144NrOfSections != 0) + return false; // nbits has to be a multiple of kBosch144NrOfSections. + const uint16_t kSectionBits = nbits / kBosch144NrOfSections; + const uint16_t kSectionBytes = kSectionBits / 8; + const uint16_t kNBytes = kSectionBytes * kBosch144NrOfSections; + // Capture each section individually + for (uint16_t pos = 0, section = 0; + pos < kNBytes; + pos += kSectionBytes, section++) { + uint16_t used = 0; + // Section Header + Section Data + Section Footer + used = matchGeneric(results->rawbuf + offset, results->state + pos, + results->rawlen - offset, kSectionBits, + kBoschHdrMark, kBoschHdrSpace, + kBoschBitMark, kBoschOneSpace, + kBoschBitMark, kBoschZeroSpace, + kBoschBitMark, kBoschFooterSpace, + section >= kBosch144NrOfSections - 1, + _tolerance, kMarkExcess, true); + if (!used) return false; // Didn't match. + offset += used; + } + + // Compliance + + // Success + results->decode_type = decode_type_t::BOSCH144; + 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_BOSCH144 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Bosch.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Bosch.h new file mode 100644 index 000000000..9ebee9854 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Bosch.h @@ -0,0 +1,193 @@ +// Copyright 2022 Nico Thien +/// @file +/// @brief Support for Bosch A/C protocol +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 + +// Supports: +// Brand: Bosch, Model: CL3000i-Set 26 E A/C +// Brand: Bosch, Model: RG10A(G2S)BGEF remote + + +#ifndef IR_BOSCH_H_ +#define IR_BOSCH_H_ + +#define __STDC_LIMIT_MACROS +#include +#include +#include +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRrecv.h" +#include "IRtext.h" +#include "IRutils.h" +#ifndef UNIT_TEST +#include +#endif +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// Constants +const uint16_t kBoschHdrMark = 4366; +const uint16_t kBoschBitMark = 502; +const uint16_t kBoschHdrSpace = 4415; +const uint16_t kBoschOneSpace = 1645; +const uint16_t kBoschZeroSpace = 571; +const uint16_t kBoschFooterSpace = 5235; +const uint16_t kBoschFreq = 38000; // Hz. (Guessing the most common frequency.) +const uint16_t kBosch144NrOfSections = 3; +const uint16_t kBosch144BytesPerSection = 6; + +using irutils::addBoolToString; +using irutils::addModeToString; +using irutils::addFanToString; +using irutils::addTempToString; +using std::min; +using std::max; +using std::memcpy; +using std::memcmp; + +// Modes Bit[0] to Section 3 Bit[1-2] to Section 1 +// ModeS3 ModeS1 +const uint8_t kBosch144Cool = 0b000; +const uint8_t kBosch144Dry = 0b011; +const uint8_t kBosch144Auto = 0b101; +const uint8_t kBosch144Heat = 0b110; +const uint8_t kBosch144Fan = 0b010; + +// Fan Control Bit[0-5] to Section 3 Bit[6-8] to Section 1 +// FanS3 FanS1 +const uint16_t kBosch144Fan20 = 0b111001010; +const uint16_t kBosch144Fan40 = 0b100010100; +const uint16_t kBosch144Fan60 = 0b010011110; +const uint16_t kBosch144Fan80 = 0b001101000; +const uint16_t kBosch144Fan100 = 0b001110010; +const uint16_t kBosch144FanAuto = 0b101110011; +const uint16_t kBosch144FanAuto0 = 0b000110011; + +// Temperature +const uint8_t kBosch144TempMin = 16; // Celsius +const uint8_t kBosch144TempMax = 30; // Celsius +const uint8_t kBosch144TempRange = kBosch144TempMax - kBosch144TempMin + 1; +const uint8_t kBosch144TempMap[kBosch144TempRange] = { + 0b00001, // 16C // Bit[0] to Section 3 Bit[1-4] to Section 1 + 0b00000, // 17C // TempS3 TempS1 + 0b00010, // 18c + 0b00110, // 19C + 0b00100, // 20C + 0b01100, // 21C + 0b01110, // 22C + 0b01010, // 23C + 0b01000, // 24C + 0b11000, // 25C + 0b11010, // 26C + 0b10010, // 27C + 0b10000, // 28C + 0b10100, // 29C + 0b10110 // 30C +}; + +// "OFF" is a 96bit-message the same as Coolix protocol +const uint8_t kBosch144Off[] = {0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F, + 0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F}; + +// On, 25C, Mode: Auto +const uint8_t kBosch144DefaultState[kBosch144StateLength] = { + 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A}; + +union Bosch144Protocol { + uint8_t raw[kBosch144StateLength]; ///< The state in IR code form. + struct { + uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ + uint8_t InnvertS1_1:8; // Invert byte 0b01001101 / 0x4D # + uint8_t :5; // not used (without timer use) # + uint8_t FanS1 :3; // Fan speed bits in Section 1 # + uint8_t InnvertS1_2:8; // Invert byte # Section 1 = + uint8_t :2; // not used (without timer use) # Sektion 2 + uint8_t ModeS1 :2; // Operation mode bits S1 # + uint8_t TempS1 :4; // Desired temperature (Celsius) S2 # + uint8_t InnvertS1_3:8; // Invert byte (without timer use) ############ + + uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ + uint8_t InnvertS2_1:8; // Invert byte 0b01001101 / 0x4D # + uint8_t :5; // not used (without timer use) # + uint8_t FanS2 :3; // Fan speed bits in Section 2 # + uint8_t InnvertS2_2:8; // Invert byte # Section 2 = + uint8_t :2; // not used (without timer use) # Sektion 1 + uint8_t ModeS2 :2; // Operation mode bits S2 # + uint8_t TempS2 :4; // Desired temperature (Celsius) S2 # + uint8_t InnvertS2_3:8; // Invert byte (without timer use) ########### + + uint8_t :8; // Fixed value 0b11010101 / 0xD5 ########### + uint8_t ModeS3 :1; // ModeBit in Section 3 # + uint8_t FanS3 :6; // Fan speed bits in Section 3 # + uint8_t :1; // Unknown # + uint8_t :7; // Unknown # + uint8_t Quiet :1; // Silent-Mode # Section 3 + uint8_t :4; // Unknown # + uint8_t TempS3 :1; // Desired temp. Bit in Section3 # + uint8_t :3; // Unknown # + uint8_t :8; // Unknown # + uint8_t ChecksumS3 :8; // Checksum from byte 13-17 ########### + }; +}; + +// Classes + +/// Class for handling detailed Bosch144 A/C messages. +class IRBosch144AC { + public: + explicit IRBosch144AC(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + void stateReset(void); +#if SEND_BOSCH144 + void send(const uint16_t repeat = 0); + /// Run the calibration to calculate uSec timing offsets for this platform. + /// @return The uSec timing offset needed per modulation of the IR Led. + /// @note This will produce a 65ms IR signal pulse at 38kHz. + /// Only ever needs to be run once per object instantiation, if at all. + int8_t calibrate(void) { return _irsend.calibrate(); } +#endif // SEND_BOSCH144 + void begin(); + void setPower(const bool state); + bool getPower(void) const; + void setTemp(const uint8_t temp); + uint8_t getTemp(void) const; + void setFan(const uint16_t speed); + uint16_t getFan(void) const; + void setMode(const uint8_t mode); + uint8_t getMode(void) const; + void setQuiet(const bool on); + bool getQuiet(void) const; + uint8_t* getRaw(void); + void setRaw(const uint8_t new_code[], + const uint16_t length = kBosch144StateLength); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint16_t convertFan(const stdAc::fanspeed_t speed); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint16_t speed); + stdAc::state_t toCommon(void) const; + String toString(void) const; +#ifndef UNIT_TEST + + private: + IRsend _irsend; ///< Instance of the IR send class +#else + /// @cond IGNORE + IRsendTest _irsend; ///< Instance of the testing IR send class + /// @endcond +#endif + Bosch144Protocol _; ///< The state of the IR remote in IR code form. + + // Internal State settings + bool powerFlag; + + void setInvertBytes(); + void setCheckSumS3(); + void setTempRaw(const uint8_t code); + uint8_t getTempRaw(void) const; +}; + +#endif // IR_BOSCH_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Carrier.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Carrier.cpp index f52628aae..42b45f9ab 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Carrier.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Carrier.cpp @@ -1,8 +1,9 @@ -// Copyright 2018, 2020 David Conran +// Copyright 2018-2022 David Conran /// @file /// @brief Carrier protocols. /// @see CarrierAc https://github.com/crankyoldgit/IRremoteESP8266/issues/385 /// @see CarrierAc64 https://github.com/crankyoldgit/IRremoteESP8266/issues/1127 +/// @see CarrierAc128 https://github.com/crankyoldgit/IRremoteESP8266/issues/1797 #include "ir_Carrier.h" #include @@ -45,6 +46,16 @@ const uint16_t kCarrierAc64OneSpace = 1736; const uint16_t kCarrierAc64ZeroSpace = 615; const uint32_t kCarrierAc64Gap = kDefaultMessageGap; // A guess. +const uint16_t kCarrierAc128HdrMark = 4600; +const uint16_t kCarrierAc128HdrSpace = 2600; +const uint16_t kCarrierAc128Hdr2Mark = 9300; +const uint16_t kCarrierAc128Hdr2Space = 5000; +const uint16_t kCarrierAc128BitMark = 340; +const uint16_t kCarrierAc128OneSpace = 1000; +const uint16_t kCarrierAc128ZeroSpace = 400; +const uint16_t kCarrierAc128SectionGap = 20600; +const uint16_t kCarrierAc128InterSpace = 6700; +const uint16_t kCarrierAc128SectionBits = kCarrierAc128Bits / 2; #if SEND_CARRIER_AC /// Send a Carrier HVAC formatted message. @@ -533,3 +544,104 @@ stdAc::state_t IRCarrierAc64::toCommon(void) const { result.clock = -1; return result; } + +#if SEND_CARRIER_AC128 +/// Send a Carrier 128bit HVAC formatted message. +/// Status: BETA / Seems to work with tests. Needs testing agaisnt real devices. +/// @param[in] data The message to be sent. +/// @param[in] nbytes The byte size of the message being sent. +/// @param[in] repeat The number of times the message is to be repeated. +void IRsend::sendCarrierAC128(const uint8_t data[], const uint16_t nbytes, + const uint16_t repeat) { + // Min length check. + if (nbytes <= kCarrierAc128StateLength / 2) return; + + enableIROut(kCarrierAcFreq); + // Handle repeats. + for (uint16_t r = 0; r <= repeat; r++) { + // First part of the message. + // Headers + Data + SectionGap + sendGeneric(kCarrierAc128HdrMark, kCarrierAc128HdrSpace, + kCarrierAc128BitMark, kCarrierAc128OneSpace, + kCarrierAc128BitMark, kCarrierAc128ZeroSpace, + kCarrierAc128BitMark, kCarrierAc128SectionGap, + data, nbytes / 2, kCarrierAcFreq, false, 0, kDutyDefault); + // Inter-message markers + mark(kCarrierAc128HdrMark); + space(kCarrierAc128InterSpace); + // Second part of the message + // Headers + Data + SectionGap + sendGeneric(kCarrierAc128Hdr2Mark, kCarrierAc128Hdr2Space, + kCarrierAc128BitMark, kCarrierAc128OneSpace, + kCarrierAc128BitMark, kCarrierAc128ZeroSpace, + kCarrierAc128BitMark, kCarrierAc128SectionGap, + data + (nbytes / 2), nbytes / 2, kCarrierAcFreq, + false, 0, kDutyDefault); + // Footer + mark(kCarrierAc128HdrMark); + space(kDefaultMessageGap); + } +} +#endif // SEND_CARRIER_AC128 + +#if DECODE_CARRIER_AC128 +/// Decode the supplied Carrier 128-bit HVAC message. +/// Status: STABLE / Expected to work. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// result. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +bool IRrecv::decodeCarrierAC128(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * (nbits + 2 * kHeader + kFooter) - 1 + offset) + return false; // Can't possibly be a valid Carrier message. + if (strict && nbits != kCarrierAc128Bits) + return false; // We expect Carrier to be 128 bits of message. + + uint16_t used; + uint16_t pos = 0; + const uint16_t sectionbits = nbits / 2; + // Match the first section. + used = matchGeneric(results->rawbuf + offset, results->state, + results->rawlen - offset, sectionbits, + kCarrierAc128HdrMark, kCarrierAc128HdrSpace, + kCarrierAc128BitMark, kCarrierAc128OneSpace, + kCarrierAc128BitMark, kCarrierAc128ZeroSpace, + kCarrierAc128BitMark, kCarrierAc128SectionGap, true, + kUseDefTol, kMarkExcess, false); + if (used == 0) return false; // No match. + offset += used; + pos += sectionbits / 8; + // Look for the inter-message markers. + if (!matchMark(results->rawbuf[offset++], kCarrierAc128HdrMark)) + return false; + if (!matchSpace(results->rawbuf[offset++], kCarrierAc128InterSpace)) + return false; + // Now look for the second section. + used = matchGeneric(results->rawbuf + offset, results->state + pos, + results->rawlen - offset, sectionbits, + kCarrierAc128Hdr2Mark, kCarrierAc128Hdr2Space, + kCarrierAc128BitMark, kCarrierAc128OneSpace, + kCarrierAc128BitMark, kCarrierAc128ZeroSpace, + kCarrierAc128BitMark, kCarrierAc128SectionGap, true, + kUseDefTol, kMarkExcess, false); + if (used == 0) return false; // No match. + offset += used; + // Now check for the Footer. + if (!matchMark(results->rawbuf[offset++], kCarrierAc128HdrMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kDefaultMessageGap)) return false; + + + // Compliance + // if (strict && !IRCarrierAc128::validChecksum(results->value)) return false; + + // Success + results->bits = nbits; + results->decode_type = CARRIER_AC128; + return true; +} +#endif // DECODE_CARRIER_AC128 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Carrier.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Carrier.h index aa9ea8447..c642c51e5 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Carrier.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Carrier.h @@ -1,8 +1,9 @@ -// Copyright 2020 David Conran +// Copyright 2020-2022 David Conran /// @file /// @brief Carrier A/C /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1127 /// @see https://docs.google.com/spreadsheets/d/1EZy78L0cn1KDIX1aKq2biptejFqCjD5HO3tLiRvXf48/edit#gid=0 +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1797 // Supports: // Brand: Carrier/Surrey, Model: 42QG5A55970 remote @@ -11,6 +12,7 @@ // Brand: Carrier/Surrey, Model: 619EGX0180E0 A/C // Brand: Carrier/Surrey, Model: 619EGX0220E0 A/C // Brand: Carrier/Surrey, Model: 53NGK009/012 Inverter +// Brand: Carrier, Model: 40GKX0E2006 remote (CARRIER_AC128) #ifndef IR_CARRIER_H_ #define IR_CARRIER_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_ClimaButler.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_ClimaButler.cpp new file mode 100644 index 000000000..d8b4f5a98 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_ClimaButler.cpp @@ -0,0 +1,86 @@ +// Copyright 2022 benjy3gg +// Copyright 2022 David Conran (crankyoldgit) +/// @file +/// @brief Support for Clima-Butler protocol +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1812 + +// Supports: +// Brand: Clima-Butler, Model: AR-715 remote +// Brand: Clima-Butler, Model: RCS-SD43UWI A/C + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + + +const uint16_t kClimaButlerBitMark = 511; // uSeconds +const uint16_t kClimaButlerHdrMark = kClimaButlerBitMark; +const uint16_t kClimaButlerHdrSpace = 3492; // uSeconds +const uint16_t kClimaButlerOneSpace = 1540; // uSeconds +const uint16_t kClimaButlerZeroSpace = 548; // uSeconds +const uint32_t kClimaButlerGap = kDefaultMessageGap; // uSeconds (A guess.) +const uint16_t kClimaButlerFreq = 38000; // Hz. (Guess.) + +#if SEND_CLIMABUTLER +/// Send a ClimaButler formatted message. +/// Status: STABLE / Confirmed working. +/// @param[in] data containing the IR command. +/// @param[in] nbits Nr. of bits to send. usually kClimaButlerBits +/// @param[in] repeat Nr. of times the message is to be repeated. +void IRsend::sendClimaButler(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + enableIROut(kClimaButlerFreq); + for (uint16_t r = 0; r <= repeat; r++) { + // Header + Data + sendGeneric(kClimaButlerHdrMark, kClimaButlerHdrSpace, + kClimaButlerBitMark, kClimaButlerOneSpace, + kClimaButlerBitMark, kClimaButlerZeroSpace, + kClimaButlerBitMark, kClimaButlerHdrSpace, + data, nbits, kClimaButlerFreq, true, 0, kDutyDefault); + // Footer + mark(kClimaButlerBitMark); + space(kClimaButlerGap); + } +} +#endif // SEND_CLIMABUTLER + +#if DECODE_CLIMABUTLER +/// Decode the supplied ClimaButler message. +/// Status: STABLE / Confirmed working. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +bool IRrecv::decodeClimaButler(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * nbits + kHeader + 2 * kFooter - offset) + return false; // Too short a message to match. + if (strict && nbits != kClimaButlerBits) + return false; + + // Header + Data + uint16_t used = matchGeneric(results->rawbuf + offset, &(results->value), + results->rawlen - offset, nbits, + kClimaButlerHdrMark, kClimaButlerHdrSpace, + kClimaButlerBitMark, kClimaButlerOneSpace, + kClimaButlerBitMark, kClimaButlerZeroSpace, + kClimaButlerBitMark, kClimaButlerHdrSpace); + if (!used) return false; // Didn't matched. + offset += used; + // Footer + if (!matchMark(results->rawbuf[offset++], kClimaButlerBitMark)) + return false; + if (results->rawlen <= offset && !matchAtLeast(results->rawbuf[offset], + kClimaButlerGap)) + return false; + + // Success + results->decode_type = decode_type_t::CLIMABUTLER; + results->bits = nbits; + results->command = 0; + results->address = 0; + return true; +} +#endif // DECODE_CLIMABUTLER diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp index 0358b89a5..755e89190 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp @@ -719,7 +719,7 @@ void IRsend::sendCoolix48(const uint64_t data, const uint16_t nbits, } #endif // SEND_COOLIX48 -#if DECODE_COOLIX +#if DECODE_COOLIX48 /// Decode the supplied Coolix 48-bit A/C message. /// Status: BETA / Probably Working. /// @param[in,out] results Ptr to the data to decode & where to store the decode diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Daikin.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Daikin.cpp index cf5f3a694..f44cd8f13 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Daikin.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Daikin.cpp @@ -1,6 +1,6 @@ // Copyright 2016 sillyfrog // Copyright 2017 sillyfrog, crankyoldgit -// Copyright 2018-2021 crankyoldgit +// Copyright 2018-2022 crankyoldgit // Copyright 2019 pasna (IRDaikin160 class / Daikin176 class) /// @file @@ -21,6 +21,7 @@ /// @see Daikin216 https://github.com/crankyoldgit/IRremoteESP8266/issues/689 /// @see Daikin216 https://github.com/danny-source/Arduino_DY_IRDaikin /// @see Daikin64 https://github.com/crankyoldgit/IRremoteESP8266/issues/1064 +/// @see Daikin200 https://github.com/crankyoldgit/IRremoteESP8266/issues/1802 #include "ir_Daikin.h" #include @@ -3733,3 +3734,193 @@ stdAc::state_t IRDaikin64::toCommon(const stdAc::state_t *prev) const { result.light = false; return result; } + +#if SEND_DAIKIN200 +/// Send a Daikin200 (200-bit) A/C formatted message. +/// Status: BETA / Untested on a real device. +/// @param[in] data The message to be sent. +/// @param[in] nbytes The number of bytes of message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1802 +void IRsend::sendDaikin200(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kDaikin200Section1Length) + return; // Not enough bytes to send a partial message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Section #1 + sendGeneric(kDaikin200HdrMark, kDaikin200HdrSpace, kDaikin200BitMark, + kDaikin200OneSpace, kDaikin200BitMark, kDaikin200ZeroSpace, + kDaikin200BitMark, kDaikin200Gap, data, + kDaikin200Section1Length, + kDaikin200Freq, false, 0, kDutyDefault); + // Section #2 + sendGeneric(kDaikin200HdrMark, kDaikin200HdrSpace, kDaikin200BitMark, + kDaikin200OneSpace, kDaikin200BitMark, kDaikin200ZeroSpace, + kDaikin200BitMark, kDaikin200Gap, + data + kDaikin200Section1Length, + nbytes - kDaikin200Section1Length, + kDaikin200Freq, false, 0, kDutyDefault); + } +} +#endif // SEND_DAIKIN200 + +#if DECODE_DAIKIN200 +/// Decode the supplied Daikin 200-bit message. (DAIKIN200) +/// Status: STABLE / Known to be working. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// result. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1802 +bool IRrecv::decodeDaikin200(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1 + offset) + return false; + + // Compliance + if (strict && nbits != kDaikin200Bits) return false; + + const uint8_t ksectionSize[kDaikin200Sections] = {kDaikin200Section1Length, + kDaikin200Section2Length}; + // Sections + uint16_t pos = 0; + for (uint8_t section = 0; section < kDaikin200Sections; section++) { + uint16_t used; + // Section Header + Section Data + Section Footer + used = matchGeneric(results->rawbuf + offset, results->state + pos, + results->rawlen - offset, ksectionSize[section] * 8, + kDaikin200HdrMark, kDaikin200HdrSpace, + kDaikin200BitMark, kDaikin200OneSpace, + kDaikin200BitMark, kDaikin200ZeroSpace, + kDaikin200BitMark, kDaikin200Gap, + section >= kDaikin200Sections - 1, + kDaikinTolerance, 0, false); + if (used == 0) return false; + offset += used; + pos += ksectionSize[section]; + } + // Compliance + if (strict) { + if (pos * 8 != kDaikin200Bits) return false; + // Validate the checksum. + if (!IRDaikin176::validChecksum(results->state, pos)) return false; + } + + // Success + results->decode_type = decode_type_t::DAIKIN200; + 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_DAIKIN200 + +#if SEND_DAIKIN312 +/// Send a Daikin312 (312-bit / 39 byte) A/C formatted message. +/// Status: BETA / Untested on a real device. +/// @param[in] data The message to be sent. +/// @param[in] nbytes The number of bytes of message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1829 +void IRsend::sendDaikin312(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kDaikin312Section1Length) + return; // Not enough bytes to send a partial message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Send the header, 0b00000 + sendGeneric(0, 0, // No header for the header + kDaikin312BitMark, kDaikin312OneSpace, + kDaikin312BitMark, kDaikin312ZeroSpace, + kDaikin312BitMark, kDaikin312HdrGap, + (uint64_t)0b00000, kDaikinHeaderLength, + kDaikin2Freq, false, 0, kDutyDefault); + // Section #1 + sendGeneric(kDaikin312HdrMark, kDaikin312HdrSpace, kDaikin312BitMark, + kDaikin312OneSpace, kDaikin312BitMark, kDaikin312ZeroSpace, + kDaikin312BitMark, kDaikin312SectionGap, data, + kDaikin312Section1Length, + kDaikin2Freq, false, 0, kDutyDefault); + // Section #2 + sendGeneric(kDaikin312HdrMark, kDaikin312HdrSpace, kDaikin312BitMark, + kDaikin312OneSpace, kDaikin312BitMark, kDaikin312ZeroSpace, + kDaikin312BitMark, kDaikin312SectionGap, + data + kDaikin312Section1Length, + nbytes - kDaikin312Section1Length, + kDaikin2Freq, false, 0, kDutyDefault); + } +} +#endif // SEND_DAIKIN312 + +#if DECODE_DAIKIN312 +/// Decode the supplied Daikin 312-bit / 39-byte message. (DAIKIN312) +/// Status: STABLE / Confirmed working. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// result. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1829 +bool IRrecv::decodeDaikin312(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + // Is there enough data to match successfully? + if (results->rawlen < 2 * (nbits + kDaikinHeaderLength + kHeader + kFooter) + + kFooter - 1 + offset) + return false; + + // Compliance + if (strict && nbits != kDaikin312Bits) return false; + + const uint8_t ksectionSize[kDaikin312Sections] = {kDaikin312Section1Length, + kDaikin312Section2Length}; + // Header/Leader Section + uint64_t leaderdata = 0; + uint16_t used = matchGeneric(results->rawbuf + offset, &leaderdata, + results->rawlen - offset, kDaikinHeaderLength, + 0, 0, // No Header Mark or Space for the "header" + kDaikin312BitMark, kDaikin312OneSpace, + kDaikin312BitMark, kDaikin312ZeroSpace, + kDaikin312BitMark, kDaikin312HdrGap, + false, kDaikinTolerance, 0, false); + if (!used) return false; // Failed to match. + if (leaderdata) return false; // The header bits should all be zero. + + offset += used; + + // Data Sections + uint16_t pos = 0; + for (uint8_t section = 0; section < kDaikin312Sections; section++) { + // Section Header + Section Data + Section Footer + used = matchGeneric(results->rawbuf + offset, results->state + pos, + results->rawlen - offset, ksectionSize[section] * 8, + kDaikin312HdrMark, kDaikin312HdrSpace, + kDaikin312BitMark, kDaikin312OneSpace, + kDaikin312BitMark, kDaikin312ZeroSpace, + kDaikin312BitMark, kDaikin312SectionGap, + section >= kDaikin312Sections - 1, + kDaikinTolerance, 0, false); + if (used == 0) return false; + offset += used; + pos += ksectionSize[section]; + } + // Compliance + if (strict) { + if (pos * 8 != kDaikin312Bits) return false; + } + + // Success + results->decode_type = decode_type_t::DAIKIN312; + 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_DAIKIN312 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Daikin.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Daikin.h index 25540e2c2..3a98f07e7 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Daikin.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Daikin.h @@ -1,6 +1,6 @@ // Copyright 2016 sillyfrog // Copyright 2017 sillyfrog, crankyoldgit -// Copyright 2018-2021 crankyoldgit +// Copyright 2018-2022 crankyoldgit // Copyright 2019 pasna (IRDaikin160 class / Daikin176 class) /// @file @@ -21,6 +21,8 @@ /// @see Daikin216 https://github.com/crankyoldgit/IRremoteESP8266/issues/689 /// @see Daikin216 https://github.com/danny-source/Arduino_DY_IRDaikin /// @see Daikin64 https://github.com/crankyoldgit/IRremoteESP8266/issues/1064 +/// @see Daikin200 https://github.com/crankyoldgit/IRremoteESP8266/issues/1802 +/// @see Daikin312 https://github.com/crankyoldgit/IRremoteESP8266/issues/1829 // Supports: // Brand: Daikin, Model: ARC433** remote (DAIKIN) @@ -36,17 +38,21 @@ // Brand: Daikin, Model: BRC4C151 remote (DAIKIN176) // Brand: Daikin, Model: 17 Series FTXB09AXVJU A/C (DAIKIN128) // Brand: Daikin, Model: 17 Series FTXB12AXVJU A/C (DAIKIN128) -// Brand: Daikin, Model: 17 Series FTXB24AXVJU A/C (NOT SUPPORTED) +// Brand: Daikin, Model: 17 Series FTXB24AXVJU A/C (DAIKIN128) // Brand: Daikin, Model: BRC52B63 remote (DAIKIN128) // Brand: Daikin, Model: ARC480A5 remote (DAIKIN152) // Brand: Daikin, Model: FFN-C/FCN-F Series A/C (DAIKIN64) // Brand: Daikin, Model: DGS01 remote (DAIKIN64) // Brand: Daikin, Model: M Series A/C (DAIKIN) // Brand: Daikin, Model: FTXM-M A/C (DAIKIN) +// Brand: Daikin, Model: ARC466A12 remote (DAIKIN) // Brand: Daikin, Model: ARC466A33 remote (DAIKIN) // Brand: Daikin, Model: FTWX35AXV1 A/C (DAIKIN64) // Brand: Daikin, Model: ARC484A4 remote (DAIKIN216) // Brand: Daikin, Model: FTQ60TV16U2 A/C (DAIKIN216) +// Brand: Daikin, Model: BRC4M150W16 remote (DAIKIN200) +// Brand: Daikin, Model: FTXM20R5V1B A/C (DAIKIN312) +// Brand: Daikin, Model: ARC466A67 remote (DAIKIN312) #ifndef IR_DAIKIN_H_ #define IR_DAIKIN_H_ @@ -676,6 +682,30 @@ const uint8_t kDaikin64MaxTemp = 30; // Celsius const uint8_t kDaikin64ChecksumOffset = 60; const uint8_t kDaikin64ChecksumSize = 4; // Mask 0b1111 << 59 +const uint16_t kDaikin200Freq = 38000; // Modulation Frequency in Hz. +const uint16_t kDaikin200HdrMark = 4920; +const uint16_t kDaikin200HdrSpace = 2230; +const uint16_t kDaikin200BitMark = 290; +const uint16_t kDaikin200OneSpace = 1850; +const uint16_t kDaikin200ZeroSpace = 780; +const uint16_t kDaikin200Gap = 29400; +const uint16_t kDaikin200Sections = 2; +const uint16_t kDaikin200Section1Length = 7; +const uint16_t kDaikin200Section2Length = kDaikin200StateLength - + kDaikin200Section1Length; + +const uint16_t kDaikin312HdrMark = 3518; +const uint16_t kDaikin312HdrSpace = 1688; +const uint16_t kDaikin312BitMark = 453; +const uint16_t kDaikin312ZeroSpace = 414; +const uint16_t kDaikin312OneSpace = 1275; +const uint16_t kDaikin312HdrGap = 25100; +const uint16_t kDaikin312SectionGap = 35512; +const uint16_t kDaikin312Sections = 2; +const uint16_t kDaikin312Section1Length = 20; +const uint16_t kDaikin312Section2Length = kDaikin312StateLength - + kDaikin312Section1Length; + // Legacy defines. #define DAIKIN_COOL kDaikinCool #define DAIKIN_HEAT kDaikinHeat diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.cpp index eca1adf93..0c2a84331 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.cpp @@ -1,5 +1,5 @@ // Copyright 2017 Jonny Graham -// Copyright 2017-2021 David Conran +// Copyright 2017-2022 David Conran // Copyright 2021 siriuslzx /// @file @@ -116,6 +116,7 @@ void IRFujitsuAC::stateReset(void) { _.longcode[1] = 0x63; _.longcode[3] = 0x10; _.longcode[4] = 0x10; + _rawstatemodified = true; } /// Set up hardware to be able to send a message. @@ -142,6 +143,7 @@ bool IRFujitsuAC::updateUseLongOrShort(void) { case kFujitsuAcCmdStepHoriz: // 0x79 case kFujitsuAcCmdToggleSwingHoriz: // 0x7A _.Cmd = _cmd; + _rawstatemodified = true; break; default: switch (_model) { @@ -150,10 +152,12 @@ bool IRFujitsuAC::updateUseLongOrShort(void) { case fujitsu_ac_remote_model_t::ARREB1E: case fujitsu_ac_remote_model_t::ARREW4E: _.Cmd = 0xFE; + _rawstatemodified = true; break; case fujitsu_ac_remote_model_t::ARDB1: case fujitsu_ac_remote_model_t::ARJW2: _.Cmd = 0xFC; + _rawstatemodified = true; break; } fullCmd = true; @@ -164,7 +168,8 @@ bool IRFujitsuAC::updateUseLongOrShort(void) { /// Calculate and set the checksum values for the internal state. void IRFujitsuAC::checkSum(void) { - if (updateUseLongOrShort()) { // Is it a long code? + _rawstatemodified = true; + if (updateUseLongOrShort()) { // Is it going to be a long code? // Nr. of bytes in the message after this byte. _.RestLength = _state_length - 7; _.Protocol = (_model == fujitsu_ac_remote_model_t::ARREW4E) ? 0x31 : 0x30; @@ -179,7 +184,13 @@ void IRFujitsuAC::checkSum(void) { } } if (_model != fujitsu_ac_remote_model_t::ARRY4) { - if (_model != fujitsu_ac_remote_model_t::ARREW4E) _.Clean = false; + switch (_model) { + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARREW4E: + break; + default: + _.Clean = false; + } _.Filter = false; } // Set the On/Off/Sleep timer Nr of mins. @@ -235,13 +246,17 @@ uint8_t IRFujitsuAC::getStateLength(void) { return updateUseLongOrShort() ? _state_length : _state_length_short; } +/// Is the current binary state representation a long or a short code? +/// @return true, if long; false, if short. +bool IRFujitsuAC::isLongCode(void) const { + return _.Cmd == 0xFE || _.Cmd == 0xFC; +} + /// Get a PTR to the internal state/code for this protocol. /// @return PTR to a code for this protocol based on the current internal state. uint8_t* IRFujitsuAC::getRaw(void) { checkSum(); - if (_.Cmd == 0xFE || _.Cmd == 0xFC) - return _.longcode; - return _.shortcode; + return isLongCode() ? _.longcode : _.shortcode; } /// Build the internal state/config from the current (raw) A/C message. @@ -281,7 +296,8 @@ void IRFujitsuAC::buildFromState(const uint16_t length) { setCmd(kFujitsuAcCmdStayOn); // Currently the only way we know how to tell ARRAH2E & ARRY4 apart is if // either the raw Filter or Clean setting is on. - if (_model == fujitsu_ac_remote_model_t::ARRAH2E && (_.Filter || _.Clean)) + if (_model == fujitsu_ac_remote_model_t::ARRAH2E && (_.Filter || _.Clean) && + !get10CHeat()) setModel(fujitsu_ac_remote_model_t::ARRY4); if (_state_length == kFujitsuAcStateLength && _.OutsideQuiet) setModel(fujitsu_ac_remote_model_t::ARREB1E); @@ -312,6 +328,7 @@ bool IRFujitsuAC::setRaw(const uint8_t newState[], const uint16_t length) { _.longcode[i] = 0; } buildFromState(length); + _rawstatemodified = false; return true; } @@ -405,6 +422,7 @@ bool IRFujitsuAC::getPower(void) const { return _cmd != kFujitsuAcCmdTurnOff; } /// @param[in] on true, the setting is on. false, the setting is off. void IRFujitsuAC::setOutsideQuiet(const bool on) { _.OutsideQuiet = on; + _rawstatemodified = true; setCmd(kFujitsuAcCmdStayOn); // No special command involved. } @@ -461,6 +479,7 @@ void IRFujitsuAC::setTemp(const float temp, const bool useCelsius) { } else { _.Temp = _temp - offset; } + _rawstatemodified = true; setCmd(kFujitsuAcCmdStayOn); // No special command involved. } @@ -484,6 +503,7 @@ void IRFujitsuAC::setFanSpeed(const uint8_t fanSpeed) { _.Fan = kFujitsuAcFanHigh; // Set the fan to maximum if out of range. else _.Fan = fanSpeed; + _rawstatemodified = true; setCmd(kFujitsuAcCmdStayOn); // No special command involved. } @@ -498,6 +518,7 @@ void IRFujitsuAC::setMode(const uint8_t mode) { _.Mode = kFujitsuAcModeHeat; // Set the mode to maximum if out of range. else _.Mode = mode; + _rawstatemodified = true; setCmd(kFujitsuAcCmdStayOn); // No special command involved. } @@ -511,6 +532,7 @@ uint8_t IRFujitsuAC::getMode(void) const { return _.Mode; } /// @note Not all models support all possible swing modes. void IRFujitsuAC::setSwing(const uint8_t swingMode) { _.Swing = swingMode; + _rawstatemodified = true; switch (_model) { // No Horizontal support. case fujitsu_ac_remote_model_t::ARDB1: @@ -531,14 +553,13 @@ void IRFujitsuAC::setSwing(const uint8_t swingMode) { /// Get the requested swing operation mode of the A/C unit. /// @return The contents of the swing state/mode. -uint8_t IRFujitsuAC::getSwing(void) const { - return _.Swing; -} +uint8_t IRFujitsuAC::getSwing(void) const { return _.Swing; } /// Set the Clean mode of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. void IRFujitsuAC::setClean(const bool on) { _.Clean = on; + _rawstatemodified = true; setCmd(kFujitsuAcCmdStayOn); // No special command involved. } @@ -555,6 +576,7 @@ bool IRFujitsuAC::getClean(void) const { /// @param[in] on true, the setting is on. false, the setting is off. void IRFujitsuAC::setFilter(const bool on) { _.Filter = on; + _rawstatemodified = true; setCmd(kFujitsuAcCmdStayOn); // No special command involved. } @@ -563,7 +585,7 @@ void IRFujitsuAC::setFilter(const bool on) { bool IRFujitsuAC::getFilter(void) const { switch (_model) { case fujitsu_ac_remote_model_t::ARRY4: return _.Filter; - default: return false; + default: return false; } } @@ -572,6 +594,7 @@ bool IRFujitsuAC::getFilter(void) const { void IRFujitsuAC::set10CHeat(const bool on) { switch (_model) { // Only selected models support this. + case fujitsu_ac_remote_model_t::ARRAH2E: case fujitsu_ac_remote_model_t::ARREW4E: setClean(on); // 10C Heat uses the same bit as Clean if (on) { @@ -579,6 +602,7 @@ void IRFujitsuAC::set10CHeat(const bool on) { _.Power = true; _.Fan = kFujitsuAcFanAuto; _.Swing = kFujitsuAcSwingOff; + _rawstatemodified = true; } default: break; @@ -589,6 +613,7 @@ void IRFujitsuAC::set10CHeat(const bool on) { /// @return true, the setting is on. false, the setting is off. bool IRFujitsuAC::get10CHeat(void) const { switch (_model) { + case fujitsu_ac_remote_model_t::ARRAH2E: case fujitsu_ac_remote_model_t::ARREW4E: return (_.Clean && _.Power && _.Mode == kFujitsuAcModeFan && _.Fan == kFujitsuAcFanAuto && _.Swing == kFujitsuAcSwingOff); @@ -602,9 +627,8 @@ uint8_t IRFujitsuAC::getTimerType(void) const { switch (_model) { // These models seem to have timer support. case fujitsu_ac_remote_model_t::ARRAH2E: - case fujitsu_ac_remote_model_t::ARREB1E: - return _.TimerType; - default: return kFujitsuAcStopTimers; + case fujitsu_ac_remote_model_t::ARREB1E: return _.TimerType; + default: return kFujitsuAcStopTimers; } } @@ -620,6 +644,7 @@ void IRFujitsuAC::setTimerType(const uint8_t timertype) { break; default: _.TimerType = kFujitsuAcStopTimers; } + _rawstatemodified = true; } /// Get the On Timer setting of the A/C. @@ -634,6 +659,7 @@ uint16_t IRFujitsuAC::getOnTimer(void) const { /// @param[in] nr_mins Nr. of minutes to set the timer to. 0 means disabled. void IRFujitsuAC::setOnTimer(const uint16_t nr_mins) { _.OnTimer = std::min(kFujitsuAcTimerMax, nr_mins); // Bounds check. + _rawstatemodified = true; if (_.OnTimer) { _.TimerType = kFujitsuAcOnTimer; } else if (getTimerType() == kFujitsuAcOnTimer) { @@ -646,10 +672,8 @@ void IRFujitsuAC::setOnTimer(const uint16_t nr_mins) { uint16_t IRFujitsuAC::getOffSleepTimer(void) const { switch (getTimerType()) { case kFujitsuAcOffTimer: - case kFujitsuAcSleepTimer: - return _.OffTimer; - default: - return 0; + case kFujitsuAcSleepTimer: return _.OffTimer; + default: return 0; } } @@ -657,12 +681,13 @@ uint16_t IRFujitsuAC::getOffSleepTimer(void) const { /// @param[in] nr_mins Nr. of minutes to set the timer to. 0 means disabled. inline void IRFujitsuAC::setOffSleepTimer(const uint16_t nr_mins) { _.OffTimer = std::min(kFujitsuAcTimerMax, nr_mins); // Bounds check. + _rawstatemodified = true; } /// Set the Off Timer time for the A/C. /// @param[in] nr_mins Nr. of minutes to set the timer to. 0 means disabled. void IRFujitsuAC::setOffTimer(const uint16_t nr_mins) { - setOffSleepTimer(nr_mins); + setOffSleepTimer(nr_mins); // This will also set _rawstatemodified to true. if (nr_mins) _.TimerType = kFujitsuAcOffTimer; else if (getTimerType() != kFujitsuAcOnTimer) @@ -672,7 +697,7 @@ void IRFujitsuAC::setOffTimer(const uint16_t nr_mins) { /// Set the Sleep Timer time for the A/C. /// @param[in] nr_mins Nr. of minutes to set the timer to. 0 means disabled. void IRFujitsuAC::setSleepTimer(const uint16_t nr_mins) { - setOffSleepTimer(nr_mins); + setOffSleepTimer(nr_mins); // This will also set _rawstatemodified to true. if (nr_mins) _.TimerType = kFujitsuAcSleepTimer; else if (getTimerType() != kFujitsuAcOnTimer) @@ -706,7 +731,10 @@ bool IRFujitsuAC::validChecksum(uint8_t state[], const uint16_t length) { /// Set the device's remote ID number. /// @param[in] num The ID for the remote. Valid number range is 0 to 3. -void IRFujitsuAC::setId(const uint8_t num) { _.Id = num; } +void IRFujitsuAC::setId(const uint8_t num) { + _.Id = num; + _rawstatemodified = true; +} /// Get the current device's remote ID number. /// @return The current device's remote ID number. @@ -714,7 +742,10 @@ uint8_t IRFujitsuAC::getId(void) const { return _.Id; } /// Set the Temperature units for the A/C. /// @param[in] on true, use Celsius. false, use Fahrenheit. -void IRFujitsuAC::setCelsius(const bool on) { _.Fahrenheit = !on; } +void IRFujitsuAC::setCelsius(const bool on) { + _.Fahrenheit = !on; + _rawstatemodified = true; +} /// Get the Clean mode status of the A/C. /// @return true, the setting is on. false, the setting is off. @@ -774,35 +805,45 @@ stdAc::fanspeed_t IRFujitsuAC::toCommonFanSpeed(const uint8_t speed) { } /// Convert the current internal state into its stdAc::state_t equivalent. +/// @param[in] prev Ptr to a previous state. /// @return The stdAc equivalent of the native settings. -stdAc::state_t IRFujitsuAC::toCommon(void) const { +stdAc::state_t IRFujitsuAC::toCommon(const stdAc::state_t *prev) { stdAc::state_t result{}; + if (prev != NULL) result = *prev; result.protocol = decode_type_t::FUJITSU_AC; + checkSum(); result.model = _model; result.power = getPower(); - result.mode = toCommonMode(_.Mode); - result.celsius = getCelsius(); - result.degrees = getTemp(); - result.fanspeed = toCommonFanSpeed(_.Fan); - uint8_t swing = _.Swing; - switch (result.model) { - case fujitsu_ac_remote_model_t::ARREB1E: - case fujitsu_ac_remote_model_t::ARRAH2E: - case fujitsu_ac_remote_model_t::ARRY4: - result.clean = _.Clean; - result.filter = _.Filter; - 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; + // Only update these settings if it is a long message, or we have no previous + // state info for those settings. + if (isLongCode() || prev == NULL) { + result.mode = toCommonMode(_.Mode); + result.celsius = getCelsius(); + { + const float minHeat = result.celsius ? kFujitsuAcMinHeat + : kFujitsuAcMinHeatF; + result.degrees = get10CHeat() ? minHeat : getTemp(); + } + result.fanspeed = toCommonFanSpeed(_.Fan); + uint8_t swing = _.Swing; + switch (result.model) { + case fujitsu_ac_remote_model_t::ARREB1E: + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARRY4: + result.clean = _.Clean; + result.filter = _.Filter; + 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 = _.Fan == kFujitsuAcFanQuiet; result.turbo = _cmd == kFujitsuAcCmdPowerful; result.econo = _cmd == kFujitsuAcCmdEcono; @@ -820,54 +861,67 @@ stdAc::state_t IRFujitsuAC::toCommon(void) const { /// @return A human readable string. String IRFujitsuAC::toString(void) const { String result = ""; - result.reserve(100); // Reserve some heap for the string to reduce fragging. + result.reserve(180); // Reserve some heap for the string to reduce fragging. fujitsu_ac_remote_model_t model = _model; result += addModelToString(decode_type_t::FUJITSU_AC, model, false); result += addIntToString(_.Id, kIdStr); result += addBoolToString(getPower(), kPowerStr); - result += addModeToString(_.Mode, kFujitsuAcModeAuto, kFujitsuAcModeCool, - kFujitsuAcModeHeat, kFujitsuAcModeDry, - kFujitsuAcModeFan); - result += addTempFloatToString(getTemp(), getCelsius()); - result += addFanToString(_.Fan, kFujitsuAcFanHigh, kFujitsuAcFanLow, - kFujitsuAcFanAuto, kFujitsuAcFanQuiet, - kFujitsuAcFanMed); - switch (model) { - // These models have no internal swing, clean. or filter state. - case fujitsu_ac_remote_model_t::ARDB1: - case fujitsu_ac_remote_model_t::ARJW2: - break; - // These models have Clean & Filter, plus Swing (via fall thru) - case fujitsu_ac_remote_model_t::ARRAH2E: - case fujitsu_ac_remote_model_t::ARREB1E: - case fujitsu_ac_remote_model_t::ARRY4: - result += addBoolToString(getClean(), kCleanStr); - result += addBoolToString(getFilter(), kFilterStr); - // FALL THRU - default: // e.g. ARREW4E - if (model == fujitsu_ac_remote_model_t::ARREW4E) - result += addBoolToString(get10CHeat(), k10CHeatStr); - result += addIntToString(_.Swing, kSwingStr); - result += kSpaceLBraceStr; - switch (_.Swing) { - case kFujitsuAcSwingOff: - result += kOffStr; - break; - case kFujitsuAcSwingVert: - result += kSwingVStr; - break; - case kFujitsuAcSwingHoriz: - result += kSwingHStr; - break; - case kFujitsuAcSwingBoth: - result += kSwingVStr; - result += '+'; - result += kSwingHStr; - break; - default: - result += kUnknownStr; - } - result += ')'; + if (_rawstatemodified || isLongCode()) { + result += addModeToString(_.Mode, kFujitsuAcModeAuto, kFujitsuAcModeCool, + kFujitsuAcModeHeat, kFujitsuAcModeDry, + kFujitsuAcModeFan); + { + const bool isCelsius = getCelsius(); + const float minHeat = isCelsius ? kFujitsuAcMinHeat : kFujitsuAcMinHeatF; + result += addTempFloatToString(get10CHeat() ? minHeat : getTemp(), + isCelsius); + } + result += addFanToString(_.Fan, kFujitsuAcFanHigh, kFujitsuAcFanLow, + kFujitsuAcFanAuto, kFujitsuAcFanQuiet, + kFujitsuAcFanMed); + switch (model) { + // These models have no internal swing, clean. or filter state. + case fujitsu_ac_remote_model_t::ARDB1: + case fujitsu_ac_remote_model_t::ARJW2: + break; + // These models have Clean & Filter, plus Swing (via fall thru) + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARREB1E: + case fujitsu_ac_remote_model_t::ARRY4: + result += addBoolToString(getClean(), kCleanStr); + result += addBoolToString(getFilter(), kFilterStr); + // FALL THRU + default: // e.g. ARREW4E + switch (model) { + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARREW4E: + result += addBoolToString(get10CHeat(), k10CHeatStr); + break; + default: + break; + } + result += addIntToString(_.Swing, kSwingStr); + result += kSpaceLBraceStr; + switch (_.Swing) { + case kFujitsuAcSwingOff: + result += kOffStr; + break; + case kFujitsuAcSwingVert: + result += kSwingVStr; + break; + case kFujitsuAcSwingHoriz: + result += kSwingHStr; + break; + case kFujitsuAcSwingBoth: + result += kSwingVStr; + result += '+'; + result += kSwingHStr; + break; + default: + result += kUnknownStr; + } + result += ')'; + } } result += kCommaSpaceStr; result += kCommandStr; @@ -902,33 +956,36 @@ String IRFujitsuAC::toString(void) const { default: result += kNAStr; } - uint16_t mins = 0; - String type_str = kTimerStr; - switch (model) { - case fujitsu_ac_remote_model_t::ARREB1E: - case fujitsu_ac_remote_model_t::ARREW4E: - result += addBoolToString(getOutsideQuiet(), kOutsideQuietStr); - // FALL THRU - // These models seem to have timer support. - case fujitsu_ac_remote_model_t::ARRAH2E: - switch (getTimerType()) { - case kFujitsuAcOnTimer: - type_str = kOnTimerStr; - mins = getOnTimer(); - break; - case kFujitsuAcOffTimer: - type_str = kOffTimerStr; - mins = getOffSleepTimer(); - break; - case kFujitsuAcSleepTimer: - type_str = kSleepTimerStr; - mins = getOffSleepTimer(); - break; - } - result += addLabeledString(mins ? minsToString(mins) : kOffStr, type_str); - break; - default: - break; + if (_rawstatemodified || isLongCode()) { + uint16_t mins = 0; + String type_str = kTimerStr; + switch (model) { + case fujitsu_ac_remote_model_t::ARREB1E: + case fujitsu_ac_remote_model_t::ARREW4E: + result += addBoolToString(getOutsideQuiet(), kOutsideQuietStr); + // FALL THRU + // These models seem to have timer support. + case fujitsu_ac_remote_model_t::ARRAH2E: + switch (getTimerType()) { + case kFujitsuAcOnTimer: + type_str = kOnTimerStr; + mins = getOnTimer(); + break; + case kFujitsuAcOffTimer: + type_str = kOffTimerStr; + mins = getOffSleepTimer(); + break; + case kFujitsuAcSleepTimer: + type_str = kSleepTimerStr; + mins = getOffSleepTimer(); + break; + } + result += addLabeledString(mins ? minsToString(mins) : kOffStr, + type_str); + break; + default: + break; + } } return result; } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.h index 70c0a4cf0..6e2583a0c 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.h @@ -1,5 +1,5 @@ // Copyright 2017 Jonny Graham -// Copyright 2018-2021 David Conran +// Copyright 2018-2022 David Conran // Copyright 2021 siriuslzx /// @file @@ -30,6 +30,7 @@ // Brand: Fujitsu, Model: AR-DL10 remote (ARDB1) // Brand: Fujitsu, Model: ASU30C1 A/C (ARDB1) // Brand: Fujitsu, Model: AR-RAH1U remote (ARREB1E) +// Brand: Fujitsu, Model: AR-RAH2U remote (ARRAH2E) // Brand: Fujitsu, Model: ASU12RLF A/C (ARREB1E) // Brand: Fujitsu, Model: AR-REW4E remote (ARREW4E) // Brand: Fujitsu, Model: ASYG09KETA-B A/C (ARREW4E) @@ -37,6 +38,9 @@ // Brand: Fujitsu, Model: ASTG09K A/C (ARREW4E) // Brand: Fujitsu, Model: ASTG18K A/C (ARREW4E) // Brand: Fujitsu, Model: AR-REW1E remote (ARREW4E) +// Brand: Fujitsu, Model: AR-REG1U remote (ARRAH2E) +// Brand: OGeneral, Model: AR-RCL1E remote (ARRAH2E) +// Brand: Fujitsu General, Model: AR-JW17 remote (ARDB1) #ifndef IR_FUJITSU_H_ #define IR_FUJITSU_H_ @@ -128,9 +132,11 @@ const uint8_t kFujitsuAcFanMed = 0x02; const uint8_t kFujitsuAcFanLow = 0x03; const uint8_t kFujitsuAcFanQuiet = 0x04; +const float kFujitsuAcMinHeat = 10; // 10C const float kFujitsuAcMinTemp = 16; // 16C const float kFujitsuAcMaxTemp = 30; // 30C const uint8_t kFujitsuAcTempOffsetC = kFujitsuAcMinTemp; +const float kFujitsuAcMinHeatF = 50; // 50F const float kFujitsuAcMinTempF = 60; // 60F const float kFujitsuAcMaxTempF = 88; // 88F const uint8_t kFujitsuAcTempOffsetF = 44; @@ -206,6 +212,7 @@ class IRFujitsuAC { bool setRaw(const uint8_t newState[], const uint16_t length); uint8_t getStateLength(void); static bool validChecksum(uint8_t* state, const uint16_t length); + bool isLongCode(void) const; void setPower(const bool on); void off(void); void on(void); @@ -233,7 +240,7 @@ class IRFujitsuAC { static uint8_t convertFan(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) const; + stdAc::state_t toCommon(const stdAc::state_t *prev = NULL); String toString(void) const; #ifndef UNIT_TEST @@ -249,6 +256,7 @@ class IRFujitsuAC { fujitsu_ac_remote_model_t _model; uint8_t _state_length; uint8_t _state_length_short; + bool _rawstatemodified; void checkSum(void); bool updateUseLongOrShort(void); void buildFromState(const uint16_t length); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.cpp index 16789b99b..ead7178e3 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.cpp @@ -162,6 +162,7 @@ void IRGreeAC::setRaw(const uint8_t new_code[]) { else _model = gree_ac_remote_model_t::YBOFB; } + if (_.Mode == kGreeEcono) _model = gree_ac_remote_model_t::YX1FSF; } /// Calculate and set the checksum values for the internal state. @@ -186,7 +187,8 @@ bool IRGreeAC::validChecksum(const uint8_t state[], const uint16_t length) { 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; + case gree_ac_remote_model_t::YBOFB: + case gree_ac_remote_model_t::YX1FSF: _model = model; break; default: _model = gree_ac_remote_model_t::YAW1F; } } @@ -291,6 +293,7 @@ void IRGreeAC::setMode(const uint8_t new_mode) { case kGreeDry: setFan(1); break; case kGreeCool: case kGreeFan: + case kGreeEcono: case kGreeHeat: break; // If we get an unexpected mode, default to AUTO. default: mode = kGreeAuto; @@ -352,11 +355,17 @@ bool IRGreeAC::getTurbo(void) const { return _.Turbo; } /// Set the Econo setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRGreeAC::setEcono(const bool on) { _.Econo = on; } +void IRGreeAC::setEcono(const bool on) { + _.Econo = on; + if (on && getModel() == gree_ac_remote_model_t::YX1FSF) + setMode(kGreeEcono); +} /// Get the Econo setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRGreeAC::getEcono(void) const { return _.Econo; } +bool IRGreeAC::getEcono(void) const { + return _.Econo || getMode() == kGreeEcono; +} /// Set the Vertical Swing mode of the A/C. /// @param[in] automatic Do we use the automatic setting? @@ -589,7 +598,7 @@ stdAc::state_t IRGreeAC::toCommon(void) { result.swingv = toCommonSwingV(_.SwingV); result.swingh = toCommonSwingH(_.SwingH); result.turbo = _.Turbo; - result.econo = _.Econo; + result.econo = getEcono(); result.light = _.Light; result.clean = _.Xfan; result.sleep = _.Sleep ? 0 : -1; @@ -608,8 +617,15 @@ String IRGreeAC::toString(void) { result.reserve(220); // Reserve some heap for the string to reduce fragging. result += addModelToString(decode_type_t::GREE, _model, false); result += addBoolToString(_.Power, kPowerStr); - result += addModeToString(_.Mode, kGreeAuto, kGreeCool, kGreeHeat, - kGreeDry, kGreeFan); + if (_model == gree_ac_remote_model_t::YX1FSF && _.Mode == kGreeEcono) { + result += addIntToString(_.Mode, kModeStr); + result += kSpaceLBraceStr; + result += kEconoStr; + result += ')'; + } else { + result += addModeToString(_.Mode, kGreeAuto, kGreeCool, kGreeHeat, + kGreeDry, kGreeFan); + } result += addTempToString(getTemp(), !_.UseFahrenheit); result += addFanToString(_.Fan, kGreeFanMax, kGreeFanMin, kGreeFanAuto, kGreeFanAuto, kGreeFanMed); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.h index be5ac31ce..eb9d4a00c 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.h @@ -1,9 +1,10 @@ -// Copyright 2016 David Conran +// Copyright 2016-2022 David Conran /// @file /// @brief Support for Gree A/C protocols. /// @see https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.h /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1508 +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1821 // Supports: // Brand: Ultimate, Model: Heat Pump @@ -15,6 +16,7 @@ // Brand: Gree, Model: YAA1FBF remote // Brand: Gree, Model: YB1F2F remote // Brand: Gree, Model: YAN1F1 remote +// Brand: Gree, Model: YX1F2F remote (YX1FSF) // Brand: Gree, Model: VIR09HP115V1AH A/C // Brand: Gree, Model: VIR12HP230V1AH A/C // Brand: Amana, Model: PBC093G00CC A/C @@ -23,6 +25,7 @@ // Brand: Cooper & Hunter, Model: CH-S09FTXG A/C // Brand: Vailland, Model: YACIFB remote // Brand: Vailland, Model: VAI5-035WNI A/C +// Brand: Soleus Air, Model: window A/C (YX1FSF) #ifndef IR_GREE_H_ #define IR_GREE_H_ @@ -86,11 +89,12 @@ union GreeProtocol{ // 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; +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; +const uint8_t kGreeEcono = 5; const uint8_t kGreeFanAuto = 0; const uint8_t kGreeFanMin = 1; diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.cpp index e3a5ed8a1..a60828282 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.cpp @@ -46,7 +46,8 @@ using irutils::minsToString; _.x##Mins = mins % 60;\ } while (0) -#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02 || SEND_HAIER_AC176) +#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02 || SEND_HAIER_AC160 || \ + SEND_HAIER_AC176) /// Send a Haier A/C formatted message. (HSU07-HEA03 remote) /// Status: STABLE / Known to be working. /// @param[in] data The message to be sent. @@ -93,6 +94,18 @@ void IRsend::sendHaierAC176(const unsigned char data[], const uint16_t nbytes, } #endif // SEND_HAIER_AC176 +#if SEND_HAIER_AC160 +/// Send a Haier 160 bit remote A/C formatted message. +/// Status: STABLE / Known to be working. +/// @param[in] data The message to be sent. +/// @param[in] nbytes The number of bytes of message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +void IRsend::sendHaierAC160(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes >= kHaierAC160StateLength) sendHaierAC(data, nbytes, repeat); +} +#endif // SEND_HAIER_AC160 + /// Class constructor /// @param[in] pin GPIO to be used when sending. /// @param[in] inverted Is the output signal to be inverted? @@ -568,7 +581,7 @@ void IRHaierAC176::checksum(void) { /// @return true, if the state has a valid checksum. Otherwise, false. bool IRHaierAC176::validChecksum(const uint8_t state[], const uint16_t length) { if (length < 2) return false; // 1 byte of data can't have a checksum. - if (length < kHaierAC176StateLength) { // Is it too short? + if (length < kHaierAC160StateLength) { // Is it too short? // Then it is just a checksum of the whole thing. return (state[length - 1] == sumBytes(state, length - 1)); } else { // It is long enough for two checksums. @@ -1323,7 +1336,8 @@ bool IRHaierACYRW02::validChecksum(const uint8_t state[], } // End of IRHaierACYRW02 class. -#if (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02) +#if (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02 || DECODE_HAIER_AC160 || \ + DECODE_HAIER_AC176) /// Decode the supplied Haier HSU07-HEA03 remote message. /// Status: STABLE / Known to be working. /// @param[in,out] results Ptr to the data to decode & where to store the decode @@ -1435,3 +1449,721 @@ bool IRrecv::decodeHaierAC176(decode_results* results, uint16_t offset, return true; } #endif // DECODE_HAIER_AC176 + +#if DECODE_HAIER_AC160 +/// Decode the supplied Haier 160 bit remote A/C message. +/// Status: STABLE / Known to be working. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// result. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +bool IRrecv::decodeHaierAC160(decode_results* results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (strict) { + if (nbits != kHaierAC160Bits) + return false; // Not strictly a HAIER_AC160 message. + } + + // The protocol is almost exactly the same as HAIER_AC + if (!decodeHaierAC(results, offset, nbits, false)) return false; + + // Compliance + if (strict) { + if (!IRHaierAC176::validChecksum(results->state, nbits / 8)) return false; + } + + // Success + // It looks correct, but we haven't check the checksum etc. + results->decode_type = HAIER_AC160; + return true; +} +#endif // DECODE_HAIER_AC160 + + +/// Class constructor +/// @param[in] pin GPIO to be used when sending. +/// @param[in] inverted Is the output signal to be inverted? +/// @param[in] use_modulation Is frequency modulation to be used? +IRHaierAC160::IRHaierAC160(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { stateReset(); } + +/// Set up hardware to be able to send a message. +void IRHaierAC160::begin(void) { _irsend.begin(); } + +#if SEND_HAIER_AC160 +/// Send the current internal state as an IR message. +/// @param[in] repeat Nr. of times the message will be repeated. +void IRHaierAC160::send(const uint16_t repeat) { + _irsend.sendHaierAC160(getRaw(), kHaierAC160StateLength, repeat); +} +#endif // SEND_HAIER_AC160 + +/// Calculate and set the checksum values for the internal state. +void IRHaierAC160::checksum(void) { + _.Sum = sumBytes(_.raw, kHaierACYRW02StateLength - 1); + _.Sum2 = sumBytes(_.raw + kHaierACYRW02StateLength, + kHaierAC160StateLength - kHaierACYRW02StateLength - 1); +} + +/// Reset the internal state to a fixed known good state. +void IRHaierAC160::stateReset(void) { + std::memset(_.raw, 0, sizeof _.raw); + _.Model = kHaierAcYrw02ModelA; + _.Prefix = kHaierAc160Prefix; + _.Temp = kHaierAcYrw02DefTempC - kHaierAcYrw02MinTempC; + setClean(false); + setFan(kHaierAcYrw02FanAuto); + _.Power = true; + _.Button = kHaierAcYrw02ButtonPower; +} + +/// Get a PTR to the internal state/code for this protocol. +/// @return PTR to a code for this protocol based on the current internal state. +uint8_t* IRHaierAC160::getRaw(void) { + checksum(); + return _.raw; +} + +/// Set the internal state from a valid code for this protocol. +/// @param[in] new_code A valid code for this protocol. +void IRHaierAC160::setRaw(const uint8_t new_code[]) { + memcpy(_.raw, new_code, kHaierAC160StateLength); +} + +/// Set the Button/Command setting of the A/C. +/// @param[in] button The value of the button/command that was pressed. +void IRHaierAC160::setButton(uint8_t button) { + switch (button) { + case kHaierAcYrw02ButtonTempUp: + case kHaierAcYrw02ButtonTempDown: + case kHaierAcYrw02ButtonSwingV: + case kHaierAcYrw02ButtonSwingH: + case kHaierAcYrw02ButtonFan: + case kHaierAcYrw02ButtonPower: + case kHaierAcYrw02ButtonMode: + case kHaierAcYrw02ButtonHealth: + case kHaierAcYrw02ButtonTurbo: + case kHaierAcYrw02ButtonSleep: + case kHaierAcYrw02ButtonLock: + case kHaierAc160ButtonClean: + case kHaierAcYrw02ButtonCFAB: + _.Button = button; + } +} + +/// Get the Button/Command setting of the A/C. +/// @return The value of the button/command that was pressed. +uint8_t IRHaierAC160::getButton(void) const { return _.Button; } + +/// Set the operating mode of the A/C. +/// @param[in] mode The desired operating mode. +void IRHaierAC160::setMode(uint8_t mode) { + switch (mode) { + case kHaierAcYrw02Auto: + case kHaierAcYrw02Dry: + case kHaierAcYrw02Fan: + // Turbo & Quiet is only available in Cool/Heat mode. + _.Turbo = false; + _.Quiet = false; + // FALL-THRU + case kHaierAcYrw02Cool: + case kHaierAcYrw02Heat: + _.Button = kHaierAcYrw02ButtonMode; + _.Mode = mode; + break; + default: + setMode(kHaierAcYrw02Auto); // Unexpected, default to auto mode. + } + _.AuxHeating = (_.Mode == kHaierAcYrw02Heat); // Set only if heat mode. +} + +/// Get the operating mode setting of the A/C. +/// @return The current operating mode setting. +uint8_t IRHaierAC160::getMode(void) const { return _.Mode; } + +/// Set the default temperature units to use. +/// @param[in] on Use Fahrenheit as the units. +/// true is Fahrenheit, false is Celsius. +void IRHaierAC160::setUseFahrenheit(const bool on) { _.UseFahrenheit = on; } + +/// Get the default temperature units in use. +/// @return true is Fahrenheit, false is Celsius. +bool IRHaierAC160::getUseFahrenheit(void) const { return _.UseFahrenheit; } + +/// Set the temperature. +/// @param[in] degree The temperature in degrees. +/// @param[in] fahrenheit Use units of Fahrenheit and set that as units used. +void IRHaierAC160::setTemp(const uint8_t degree, const bool fahrenheit) { + uint8_t old_temp = getTemp(); + if (old_temp == degree) return; + + if (_.UseFahrenheit == fahrenheit) { + if (old_temp > degree) + _.Button = kHaierAcYrw02ButtonTempDown; + else + _.Button = kHaierAcYrw02ButtonTempUp; + } else { + _.Button = kHaierAcYrw02ButtonCFAB; + } + _.UseFahrenheit = fahrenheit; + + uint8_t temp = degree; + if (fahrenheit) { + if (temp < kHaierAcYrw02MinTempF) + temp = kHaierAcYrw02MinTempF; + else if (temp > kHaierAcYrw02MaxTempF) + temp = kHaierAcYrw02MaxTempF; + if (degree >= 77) { temp++; } + if (degree >= 79) { temp++; } + // See at IRHaierAC160::getTemp() comments for clarification + _.ExtraDegreeF = temp % 2; + _.Temp = (temp - kHaierAcYrw02MinTempF -_.ExtraDegreeF) >> 1; + } else { + if (temp < kHaierAcYrw02MinTempC) + temp = kHaierAcYrw02MinTempC; + else if (temp > kHaierAcYrw02MaxTempC) + temp = kHaierAcYrw02MaxTempC; + _.Temp = temp - kHaierAcYrw02MinTempC; + } +} + +/// Get the current temperature setting. +/// The unit of temperature is specified by UseFahrenheit value. +/// @return The current setting for temperature. +uint8_t IRHaierAC160::getTemp(void) const { + if (!_.UseFahrenheit) { return _.Temp + kHaierAcYrw02MinTempC; } + uint8_t degree = _.Temp*2 + kHaierAcYrw02MinTempF + _.ExtraDegreeF; + // The way of coding the temperature in degree Fahrenheit is + // kHaierAcYrw02MinTempF + Temp*2 + ExtraDegreeF, for example + // Temp = 0b0011, ExtraDegreeF = 0b1, temperature is 60 + 3*2 + 1 = 67F + // But around 78F there is unconsistency, see table below + // + // | Fahrenheit | Temp | ExtraDegreeF | + // | 60F | 0b0000 | 0b0 | + // | 61F | 0b0000 | 0b1 | + // | 62F | 0b0001 | 0b0 | + // | 63F | 0b0001 | 0b1 | + // | 64F | 0b0010 | 0b0 | + // | 65F | 0b0010 | 0b1 | + // | 66F | 0b0011 | 0b0 | + // | 67F | 0b0011 | 0b1 | + // | 68F | 0b0100 | 0b0 | + // | 69F | 0b0100 | 0b1 | + // | 70F | 0b0101 | 0b0 | + // | 71F | 0b0101 | 0b1 | + // | 72F | 0b0110 | 0b0 | + // | 73F | 0b0110 | 0b1 | + // | 74F | 0b0111 | 0b0 | + // | 75F | 0b0111 | 0b1 | + // | 76F | 0b1000 | 0b0 | + // | Not Used | 0b1000 | 0b1 | + // | 77F | 0b1001 | 0b0 | + // | Not Used | 0b1001 | 0b1 | + // | 78F | 0b1010 | 0b0 | + // | 79F | 0b1010 | 0b1 | + // | 80F | 0b1011 | 0b0 | + // | 81F | 0b1011 | 0b1 | + // | 82F | 0b1100 | 0b0 | + // | 83F | 0b1100 | 0b1 | + // | 84F | 0b1101 | 0b0 | + // | 86F | 0b1110 | 0b0 | + // | 85F | 0b1101 | 0b1 | + if (degree >= 77) { degree--; } + if (degree >= 79) { degree--; } + return degree; +} + +/// Set the Clean setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRHaierAC160::setClean(const bool on) { + _.Button = kHaierAc160ButtonClean; + _.Clean = on; + _.Clean2 = on; +} + +/// Get the Clean setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRHaierAC160::getClean(void) const { return _.Clean && _.Clean2; } + +/// Get the value of the current power setting. +/// @return true, the setting is on. false, the setting is off. +bool IRHaierAC160::getPower(void) const { return _.Power; } + +/// Change the power setting. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRHaierAC160::setPower(const bool on) { + _.Button = kHaierAcYrw02ButtonPower; + _.Power = on; +} + +/// Change the power setting to On. +void IRHaierAC160::on(void) { setPower(true); } + +/// Change the power setting to Off. +void IRHaierAC160::off(void) { setPower(false); } + +/// Get the Sleep setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRHaierAC160::getSleep(void) const { return _.Sleep; } + +/// Set the Sleep setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRHaierAC160::setSleep(const bool on) { + _.Button = kHaierAcYrw02ButtonSleep; + _.Sleep = on; +} + +/// Get the Turbo setting of the A/C. +/// @return The current turbo setting. +bool IRHaierAC160::getTurbo(void) const { return _.Turbo; } + +/// Set the Turbo setting of the A/C. +/// @param[in] on The desired turbo setting. +/// @note Turbo & Quiet can't be on at the same time, and only in Heat/Cool mode +void IRHaierAC160::setTurbo(const bool on) { + switch (getMode()) { + case kHaierAcYrw02Cool: + case kHaierAcYrw02Heat: + _.Turbo = on; + _.Button = kHaierAcYrw02ButtonTurbo; + if (on) _.Quiet = false; + } +} + +/// Get the Quiet setting of the A/C. +/// @return The current Quiet setting. +bool IRHaierAC160::getQuiet(void) const { return _.Quiet; } + +/// Set the Quiet setting of the A/C. +/// @param[in] on The desired Quiet setting. +/// @note Turbo & Quiet can't be on at the same time, and only in Heat/Cool mode +void IRHaierAC160::setQuiet(const bool on) { + switch (getMode()) { + case kHaierAcYrw02Cool: + case kHaierAcYrw02Heat: + _.Quiet = on; + _.Button = kHaierAcYrw02ButtonTurbo; + if (on) _.Turbo = false; + } +} + +/// Get the value of the Aux Heating setting. +/// @return true, the setting is on. false, the setting is off. +bool IRHaierAC160::getAuxHeating(void) const { return _.AuxHeating; } + +/// Change the Aux Heating setting. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRHaierAC160::setAuxHeating(const bool on) { + _.Button = kHaierAc160ButtonAuxHeating; + _.AuxHeating = on; +} + +/// Get the value of the current Light toggle setting. +/// @return true, the setting is on. false, the setting is off. +/// @note This setting seems to be controlled just by the button setting. +bool IRHaierAC160::getLightToggle(void) const { + return _.Button == kHaierAc160ButtonLight; +} + +/// Set the Light Toggle setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +/// @note This setting seems to be controlled just by the button setting. +void IRHaierAC160::setLightToggle(const bool on) { + _.Button = on ? kHaierAc160ButtonLight : kHaierAcYrw02ButtonPower; +} + +/// Get the current fan speed setting. +/// @return The current fan speed. +uint8_t IRHaierAC160::getFan(void) const { return _.Fan; } + +/// Set the speed of the fan. +/// @param[in] speed The desired setting. +void IRHaierAC160::setFan(uint8_t speed) { + switch (speed) { + case kHaierAcYrw02FanLow: + case kHaierAcYrw02FanMed: + case kHaierAcYrw02FanHigh: + case kHaierAcYrw02FanAuto: + _.Fan = speed; + _.Fan2 = (speed == kHaierAcYrw02FanAuto) ? 0 : speed; + _.Button = kHaierAcYrw02ButtonFan; + } +} + +/// Set the Health (filter) setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRHaierAC160::setHealth(const bool on) { + _.Button = kHaierAcYrw02ButtonHealth; + _.Health = on; +} + +/// Get the Health (filter) setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRHaierAC160::getHealth(void) const { return _.Health; } + +/// Get the Vertical Swing position setting of the A/C. +/// @return The native position/mode. +uint8_t IRHaierAC160::getSwingV(void) const { return _.SwingV; } + +/// Set the Vertical Swing mode of the A/C. +/// @param[in] pos The position/mode to set the vanes to. +void IRHaierAC160::setSwingV(const uint8_t pos) { + switch (pos) { + case kHaierAc160SwingVOff: + case kHaierAc160SwingVAuto: + case kHaierAc160SwingVTop: + case kHaierAc160SwingVHighest: + case kHaierAc160SwingVHigh: + case kHaierAc160SwingVMiddle: + case kHaierAc160SwingVLow: + case kHaierAc160SwingVLowest: + _.Button = kHaierAcYrw02ButtonSwingV; + _.SwingV = pos; + break; + default: return; // If in doubt, Do nothing. + } +} + +/// Set the Timer operating mode. +/// @param[in] mode The timer mode to use. +void IRHaierAC160::setTimerMode(const uint8_t mode) { + _.TimerMode = (mode > kHaierAcYrw02OffThenOnTimer) ? kHaierAcYrw02NoTimers + : mode; + switch (_.TimerMode) { + case kHaierAcYrw02NoTimers: + setOnTimer(0); // Disable the On timer. + setOffTimer(0); // Disable the Off timer. + break; + case kHaierAcYrw02OffTimer: + setOnTimer(0); // Disable the On timer. + break; + case kHaierAcYrw02OnTimer: + setOffTimer(0); // Disable the Off timer. + break; + } +} + +/// Get the Timer operating mode. +/// @return The mode of the timer is currently configured to. +uint8_t IRHaierAC160::getTimerMode(void) const { return _.TimerMode; } + +/// Set the number of minutes of the On Timer setting. +/// @param[in] mins Nr. of Minutes for the Timer. `0` means disable the timer. +void IRHaierAC160::setOnTimer(const uint16_t mins) { + const uint16_t nr_mins = std::min((uint16_t)(23 * 60 + 59), mins); + _.OnTimerHrs = nr_mins / 60; + _.OnTimerMins = nr_mins % 60; + + const bool enabled = (nr_mins > 0); + uint8_t mode = getTimerMode(); + switch (mode) { + case kHaierAcYrw02OffTimer: + mode = enabled ? kHaierAcYrw02OffThenOnTimer : mode; + break; + case kHaierAcYrw02OnThenOffTimer: + case kHaierAcYrw02OffThenOnTimer: + mode = enabled ? kHaierAcYrw02OffThenOnTimer : kHaierAcYrw02OffTimer; + break; + default: + // Enable/Disable the On timer for the simple case. + mode = enabled << 1; + } + _.TimerMode = mode; +} + +/// Get the number of minutes of the On Timer setting. +/// @return Nr of minutes. +uint16_t IRHaierAC160::getOnTimer(void) const { + return _.OnTimerHrs * 60 + _.OnTimerMins; +} + +/// Set the number of minutes of the Off Timer setting. +/// @param[in] mins Nr. of Minutes for the Timer. `0` means disable the timer. +void IRHaierAC160::setOffTimer(const uint16_t mins) { + const uint16_t nr_mins = std::min((uint16_t)(23 * 60 + 59), mins); + _.OffTimerHrs = nr_mins / 60; + _.OffTimerMins = nr_mins % 60; + + const bool enabled = (nr_mins > 0); + uint8_t mode = getTimerMode(); + switch (mode) { + case kHaierAcYrw02OnTimer: + mode = enabled ? kHaierAcYrw02OnThenOffTimer : mode; + break; + case kHaierAcYrw02OnThenOffTimer: + case kHaierAcYrw02OffThenOnTimer: + mode = enabled ? kHaierAcYrw02OnThenOffTimer : kHaierAcYrw02OnTimer; + break; + default: + // Enable/Disable the Off timer for the simple case. + mode = enabled; + } + _.TimerMode = mode; +} + +/// Get the number of minutes of the Off Timer setting. +/// @return Nr of minutes. +uint16_t IRHaierAC160::getOffTimer(void) const { + return _.OffTimerHrs * 60 + _.OffTimerMins; +} + +/// Get the Lock setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRHaierAC160::getLock(void) const { return _.Lock; } + +/// Set the Lock setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRHaierAC160::setLock(const bool on) { + _.Button = kHaierAcYrw02ButtonLock; + _.Lock = on; +} + +/// Convert a stdAc::opmode_t enum into its native mode. +/// @param[in] mode The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRHaierAC160::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: return kHaierAcYrw02Cool; + case stdAc::opmode_t::kHeat: return kHaierAcYrw02Heat; + case stdAc::opmode_t::kDry: return kHaierAcYrw02Dry; + case stdAc::opmode_t::kFan: return kHaierAcYrw02Fan; + default: return kHaierAcYrw02Auto; + } +} + +/// Convert a stdAc::fanspeed_t enum into it's native speed. +/// @param[in] speed The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRHaierAC160::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: return kHaierAcYrw02FanLow; + case stdAc::fanspeed_t::kMedium: return kHaierAcYrw02FanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: return kHaierAcYrw02FanHigh; + default: return kHaierAcYrw02FanAuto; + } +} + +/// Convert a stdAc::swingv_t enum into it's native setting. +/// @param[in] position The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRHaierAC160::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: return kHaierAc160SwingVTop; + case stdAc::swingv_t::kHigh: return kHaierAc160SwingVHigh; + case stdAc::swingv_t::kMiddle: return kHaierAc160SwingVMiddle; + case stdAc::swingv_t::kLow: return kHaierAc160SwingVLow; + case stdAc::swingv_t::kLowest: return kHaierAc160SwingVLowest; + case stdAc::swingv_t::kOff: return kHaierAc160SwingVOff; + default: return kHaierAc160SwingVAuto; + } +} + +/// Convert a native mode into its stdAc equivalent. +/// @param[in] mode The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::opmode_t IRHaierAC160::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 into its stdAc equivalent. +/// @param[in] speed The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::fanspeed_t IRHaierAC160::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 stdAc::swingv_t enum into it's native setting. +/// @param[in] pos The enum to be converted. +/// @return The native equivalent of the enum. +stdAc::swingv_t IRHaierAC160::toCommonSwingV(const uint8_t pos) { + switch (pos) { + case kHaierAc160SwingVTop: + case kHaierAc160SwingVHighest: return stdAc::swingv_t::kHighest; + case kHaierAc160SwingVHigh: return stdAc::swingv_t::kHigh; + case kHaierAc160SwingVMiddle: return stdAc::swingv_t::kMiddle; + case kHaierAc160SwingVLow: return stdAc::swingv_t::kLow; + case kHaierAc160SwingVLowest: return stdAc::swingv_t::kLowest; + case kHaierAc160SwingVOff: return stdAc::swingv_t::kOff; + default: return stdAc::swingv_t::kAuto; + } +} + +/// Convert the current internal state into its stdAc::state_t equivalent. +/// @param[in] prev Ptr to the previous state if required. +/// @return The stdAc equivalent of the native settings. +stdAc::state_t IRHaierAC160::toCommon(const stdAc::state_t *prev) const { + 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. + // e.g. Any setting that toggles should probably go here. + result.light = false; + } + result.protocol = decode_type_t::HAIER_AC160; + result.power = _.Power; + result.mode = toCommonMode(_.Mode); + result.celsius = !_.UseFahrenheit; + result.degrees = getTemp(); + result.fanspeed = toCommonFanSpeed(_.Fan); + result.swingv = toCommonSwingV(_.SwingV); + result.swingh = stdAc::swingh_t::kOff; + result.sleep = _.Sleep ? 0 : -1; + result.turbo = _.Turbo; + result.quiet = _.Quiet; + result.clean = _.Clean && _.Clean2; + result.light ^= getLightToggle(); + result.filter = _.Health; + // Not supported. + result.model = -1; + result.econo = false; + result.beep = true; + result.clock = -1; + return result; +} + +/// Convert the current internal state into a human readable string. +/// @return A human readable string. +String IRHaierAC160::toString(void) const { + String result = ""; + result.reserve(280); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(_.Power, kPowerStr, false); + uint8_t cmd = _.Button; + result += addIntToString(cmd, kButtonStr); + result += kSpaceLBraceStr; + switch (cmd) { + case kHaierAcYrw02ButtonPower: + result += kPowerStr; + break; + case kHaierAcYrw02ButtonMode: + result += kModeStr; + break; + case kHaierAcYrw02ButtonFan: + result += kFanStr; + break; + case kHaierAcYrw02ButtonTempUp: + result += kTempUpStr; + break; + case kHaierAcYrw02ButtonTempDown: + result += kTempDownStr; + break; + case kHaierAcYrw02ButtonSleep: + result += kSleepStr; + break; + case kHaierAcYrw02ButtonHealth: + result += kHealthStr; + break; + case kHaierAcYrw02ButtonSwingV: + result += kSwingVStr; + break; + case kHaierAcYrw02ButtonSwingH: + result += kSwingHStr; + break; + case kHaierAcYrw02ButtonTurbo: + result += kTurboStr; + break; + case kHaierAcYrw02ButtonTimer: + result += kTimerStr; + break; + case kHaierAcYrw02ButtonLock: + result += kLockStr; + break; + case kHaierAc160ButtonClean: + result += kCleanStr; + break; + case kHaierAc160ButtonLight: + result += kLightStr; + break; + case kHaierAc160ButtonAuxHeating: + result += kHeatingStr; + break; + case kHaierAcYrw02ButtonCFAB: + result += kCelsiusFahrenheitStr; + break; + default: + result += kUnknownStr; + } + result += ')'; + result += addModeToString(_.Mode, kHaierAcYrw02Auto, kHaierAcYrw02Cool, + kHaierAcYrw02Heat, kHaierAcYrw02Dry, + kHaierAcYrw02Fan); + result += addTempToString(getTemp(), !_.UseFahrenheit); + result += addFanToString(_.Fan, kHaierAcYrw02FanHigh, kHaierAcYrw02FanLow, + kHaierAcYrw02FanAuto, kHaierAcYrw02FanAuto, + kHaierAcYrw02FanMed); + result += addBoolToString(_.Turbo, kTurboStr); + result += addBoolToString(_.Quiet, kQuietStr); + result += addBoolToString(_.Health, kHealthStr); + result += addIntToString(_.SwingV, kSwingVStr); + result += kSpaceLBraceStr; + switch (_.SwingV) { + case kHaierAc160SwingVOff: result += kOffStr; break; + case kHaierAc160SwingVAuto: result += kAutoStr; break; + case kHaierAc160SwingVTop: result += kTopStr; break; + case kHaierAc160SwingVHighest: result += kHighestStr; break; + case kHaierAc160SwingVHigh: result += kHighStr; break; + case kHaierAc160SwingVMiddle: result += kMiddleStr; break; + case kHaierAc160SwingVLow: result += kLowStr; break; + case kHaierAc160SwingVLowest: result += kLowestStr; break; + default: result += kUnknownStr; + } + result += ')'; + result += addBoolToString(_.Sleep, kSleepStr); + result += addBoolToString(getClean(), kCleanStr); + const uint8_t tmode = getTimerMode(); + result += addIntToString(tmode, kTimerModeStr); + result += kSpaceLBraceStr; + switch (tmode) { + case kHaierAcYrw02NoTimers: + result += kNAStr; + break; + case kHaierAcYrw02OnTimer: + result += kOnStr; + break; + case kHaierAcYrw02OffTimer: + result += kOffStr; + break; + case kHaierAcYrw02OnThenOffTimer: + result += kOnStr; + result += '-'; + result += kOffStr; + break; + case kHaierAcYrw02OffThenOnTimer: + result += kOffStr; + result += '-'; + result += kOnStr; + break; + default: + result += kUnknownStr; + } + result += ')'; + result += addLabeledString((tmode != kHaierAcYrw02NoTimers && + tmode != kHaierAcYrw02OffTimer) ? + minsToString(getOnTimer()) : kOffStr, kOnTimerStr); + result += addLabeledString((tmode != kHaierAcYrw02NoTimers && + tmode != kHaierAcYrw02OnTimer) ? + minsToString(getOffTimer()) : kOffStr, kOffTimerStr); + result += addBoolToString(_.Lock, kLockStr); + result += addBoolToString(_.AuxHeating, kHeatingStr); + return result; +} +// End of IRHaierAC160 class. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.h index 4e5c8e64c..31cf4bcff 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.h @@ -8,6 +8,7 @@ /// @see https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0 /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/485 /// @see https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1804 // Supports: // Brand: Haier, Model: HSU07-HEA03 remote (HAIER_AC) @@ -17,6 +18,7 @@ // Brand: Mabe, Model: MMI18HDBWCA6MI8 A/C (HAIER_AC176) // Brand: Mabe, Model: V12843 HJ200223 remote (HAIER_AC176) // Brand: Daichi, Model: D-H A/C (HAIER_AC176) +// Brand: Haier, Model: KFR-26GW/83@UI-Ge A/C (HAIER_AC160) #ifndef IR_HAIER_H_ #define IR_HAIER_H_ @@ -144,6 +146,7 @@ const uint8_t kHaierAcYrw02DefTempC = 25; const uint8_t kHaierAcYrw02ModelA = 0xA6; const uint8_t kHaierAcYrw02ModelB = 0x59; const uint8_t kHaierAc176Prefix = 0xB7; +const uint8_t kHaierAc160Prefix = 0xB5; const uint8_t kHaierAcYrw02SwingVOff = 0x0; const uint8_t kHaierAcYrw02SwingVTop = 0x1; @@ -152,6 +155,15 @@ const uint8_t kHaierAcYrw02SwingVBottom = 0x3; // Only available in heat mode. const uint8_t kHaierAcYrw02SwingVDown = 0xA; const uint8_t kHaierAcYrw02SwingVAuto = 0xC; // Airflow +const uint8_t kHaierAc160SwingVOff = 0b0000; +const uint8_t kHaierAc160SwingVTop = 0b0001; +const uint8_t kHaierAc160SwingVHighest = 0b0010; +const uint8_t kHaierAc160SwingVHigh = 0b0100; +const uint8_t kHaierAc160SwingVMiddle = 0b0110; +const uint8_t kHaierAc160SwingVLow = 0b1000; +const uint8_t kHaierAc160SwingVLowest = 0b0011; +const uint8_t kHaierAc160SwingVAuto = 0b1100; // Airflow + const uint8_t kHaierAcYrw02SwingHMiddle = 0x0; const uint8_t kHaierAcYrw02SwingHLeftMax = 0x3; const uint8_t kHaierAcYrw02SwingHLeft = 0x4; @@ -182,6 +194,9 @@ const uint8_t kHaierAcYrw02ButtonTurbo = 0b01000; const uint8_t kHaierAcYrw02ButtonSleep = 0b01011; const uint8_t kHaierAcYrw02ButtonTimer = 0b10000; const uint8_t kHaierAcYrw02ButtonLock = 0b10100; +const uint8_t kHaierAc160ButtonLight = 0b10101; +const uint8_t kHaierAc160ButtonAuxHeating = 0b10110; +const uint8_t kHaierAc160ButtonClean = 0b11001; const uint8_t kHaierAcYrw02ButtonCFAB = 0b11010; const uint8_t kHaierAcYrw02NoTimers = 0b000; @@ -260,6 +275,75 @@ union HaierAc176Protocol{ }; }; +/// Native representation of a Haier 160 bit A/C message. +union HaierAc160Protocol{ + uint8_t raw[kHaierAC160StateLength]; ///< The state in native form + struct { + // Byte 0 + uint8_t Model :8; + // Byte 1 + uint8_t SwingV :4; + uint8_t Temp :4; // 16C~30C + // Byte 2 + uint8_t :5; + uint8_t SwingH :3; + // Byte 3 + uint8_t :1; + uint8_t Health :1; + uint8_t :3; + uint8_t TimerMode :3; + // Byte 4 + uint8_t :6; + uint8_t Power :1; + uint8_t AuxHeating :1; + // Byte 5 + uint8_t OffTimerHrs :5; + uint8_t Fan :3; + // Byte 6 + uint8_t OffTimerMins:6; + uint8_t Turbo :1; + uint8_t Quiet :1; + // Byte 7 + uint8_t OnTimerHrs :5; + uint8_t Mode :3; + // Byte 8 + uint8_t OnTimerMins :6; + uint8_t :1; + uint8_t Sleep :1; + // Byte 9 + uint8_t :8; + // Byte 10 + uint8_t ExtraDegreeF :1; + uint8_t :3; + uint8_t Clean :1; + uint8_t UseFahrenheit:1; + uint8_t :2; + // Byte 11 + uint8_t :8; + // Byte 12 + uint8_t Button :5; + uint8_t Lock :1; + uint8_t :2; + // Byte 13 + uint8_t Sum :8; + // Byte 14 + uint8_t Prefix :8; + // Byte 15 + uint8_t :6; + uint8_t Clean2 :1; + uint8_t :1; + // Byte 16 + uint8_t :5; + uint8_t Fan2 :3; + // Byte 17 + uint8_t :8; + // Byte 18 + uint8_t :8; + // Byte 19 + uint8_t Sum2 :8; + }; +}; + // Legacy Haier YRW02 remote defines. #define HAIER_AC_YRW02_SWING_OFF kHaierAcYrw02SwingOff #define HAIER_AC_YRW02_SWING_TOP kHaierAcYrw02SwingTop @@ -474,4 +558,96 @@ class IRHaierACYRW02 : public IRHaierAC176 { const uint8_t state[], const uint16_t length = kHaierACYRW02StateLength); }; + +/// Class for handling detailed Haier 160 bit A/C messages. +class IRHaierAC160 { + public: + explicit IRHaierAC160(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); +#if SEND_HAIER_AC160 + virtual void send(const uint16_t repeat = kHaierAc160DefaultRepeat); + /// Run the calibration to calculate uSec timing offsets for this platform. + /// @return The uSec timing offset needed per modulation of the IR Led. + /// @note This will produce a 65ms IR signal pulse at 38kHz. + /// Only ever needs to be run once per object instantiation, if at all. + int8_t calibrate(void) { return _irsend.calibrate(); } +#endif // SEND_HAIER_AC160 + void begin(void); + void stateReset(void); + + void setButton(const uint8_t button); + uint8_t getButton(void) const; + + void setUseFahrenheit(const bool on); + bool getUseFahrenheit(void) const; + void setTemp(const uint8_t temp, const bool fahrenheit = false); + uint8_t getTemp(void) const; + + void setFan(const uint8_t speed); + uint8_t getFan(void) const; + + uint8_t getMode(void) const; + void setMode(const uint8_t mode); + + bool getPower(void) const; + void setPower(const bool on); + void on(void); + void off(void); + + bool getSleep(void) const; + void setSleep(const bool on); + bool getClean(void) const; + void setClean(const bool on); + bool getLightToggle(void) const; + void setLightToggle(const bool on); + + bool getTurbo(void) const; + void setTurbo(const bool on); + bool getQuiet(void) const; + void setQuiet(const bool on); + bool getAuxHeating(void) const; + void setAuxHeating(const bool on); + + uint8_t getSwingV(void) const; + void setSwingV(const uint8_t pos); + + void setTimerMode(const uint8_t setting); + uint8_t getTimerMode(void) const; + void setOnTimer(const uint16_t mins); + uint16_t getOnTimer(void) const; + void setOffTimer(const uint16_t mins); + uint16_t getOffTimer(void) const; + + bool getLock(void) const; + void setLock(const bool on); + + bool getHealth(void) const; + void setHealth(const bool on); + + uint8_t* getRaw(void); + virtual void setRaw(const uint8_t new_code[]); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kHaierAC160StateLength); + 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); + static stdAc::swingv_t toCommonSwingV(const uint8_t pos); + static bool toCommonTurbo(const uint8_t speed); + static bool toCommonQuiet(const uint8_t speed); + stdAc::state_t toCommon(const stdAc::state_t *prev = NULL) const; + String toString(void) const; +#ifndef UNIT_TEST + + private: + IRsend _irsend; ///< Instance of the IR send class +#else // UNIT_TEST + /// @cond IGNORE + IRsendTest _irsend; ///< Instance of the testing IR send class + /// @endcond +#endif // UNIT_TEST + HaierAc160Protocol _; + void checksum(void); +}; #endif // IR_HAIER_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Midea.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Midea.h index 32d8d6c71..e44055e79 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Midea.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Midea.h @@ -23,8 +23,10 @@ // Brand: Danby, Model: DAC100BGUWDB (MIDEA) // Brand: Danby, Model: DAC120BGUWDB (MIDEA) // Brand: Danby, Model: R09C/BCGE remote (MIDEA) +// Brand: Trotec, Model: TROTEC PAC 2100 X (MIDEA) // Brand: Trotec, Model: TROTEC PAC 3900 X (MIDEA) // Brand: Trotec, Model: RG57H(B)/BGE remote (MIDEA) +// Brand: Trotec, Model: RG57H3(B)/BGCEF-M remote (MIDEA) // Brand: Lennox, Model: RG57A6/BGEFU1 remote (MIDEA) // Brand: Lennox, Model: MWMA009S4-3P A/C (MIDEA) // Brand: Lennox, Model: MWMA012S4-3P A/C (MIDEA) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_NEC.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_NEC.h index 95da064b7..c9b0a6ec1 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_NEC.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_NEC.h @@ -14,6 +14,8 @@ // Brand: Duux, Model: Blizzard Smart 10K / DXMA04 A/C // Brand: Duux, Model: YJ-A081 TR Remote // Brand: Silan Microelectronics, Model: SC6121-001 IC +// Brand: BBK, Model: SP550S 5.1 sound system +// Brand: Tanix, Model: TX3 mini Android TV Box #ifndef IR_NEC_H_ #define IR_NEC_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.h index acabb3648..6c59c7af4 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.h @@ -12,6 +12,7 @@ // Supports: // Brand: Samsung, Model: UA55H6300 TV (SAMSUNG) // Brand: Samsung, Model: BN59-01178B TV remote (SAMSUNG) +// Brand: Samsung, Model: UE40K5510AUXRU TV (SAMSUNG) // Brand: Samsung, Model: DB63-03556X003 remote // Brand: Samsung, Model: DB93-16761C remote // Brand: Samsung, Model: IEC-R03 remote diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sanyo.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sanyo.cpp index ab3a4ec93..4a38e8e09 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sanyo.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sanyo.cpp @@ -77,6 +77,14 @@ const uint32_t kSanyoAc88Gap = 3675; ///< uSeconds const uint16_t kSanyoAc88Freq = 38000; ///< Hz. (Guess only) const uint8_t kSanyoAc88ExtraTolerance = 5; /// (%) Extra tolerance to use. +const uint16_t kSanyoAc152HdrMark = 3300; ///< uSeconds +const uint16_t kSanyoAc152BitMark = 440; ///< uSeconds +const uint16_t kSanyoAc152HdrSpace = 1725; ///< uSeconds +const uint16_t kSanyoAc152OneSpace = 1290; ///< uSeconds +const uint16_t kSanyoAc152ZeroSpace = 405; ///< uSeconds +const uint16_t kSanyoAc152Freq = 38000; ///< Hz. (Guess only) +const uint8_t kSanyoAc152ExtraTolerance = 13; /// (%) Extra tolerance to use. + #if SEND_SANYO /// Construct a Sanyo LC7461 message. /// @param[in] address The 13 bit value of the address(Custom) portion of the @@ -687,7 +695,7 @@ void IRsend::sendSanyoAc88(const uint8_t data[], const uint16_t nbytes, #endif // SEND_SANYO_AC88 #if DECODE_SANYO_AC88 -/// Decode the supplied SanyoAc message. +/// Decode the supplied SanyoAc88 message. /// Status: ALPHA / Untested. /// @param[in,out] results Ptr to the data to decode & where to store the decode /// @warning data's bit order may change. It is not yet confirmed. @@ -976,3 +984,61 @@ String IRSanyoAc88::toString(void) const { result += addLabeledString(minsToString(getClock()), kClockStr); return result; } + +#if SEND_SANYO_AC152 +/// Send a SanyoAc152 formatted message. +/// Status: BETA / Probably works. +/// @param[in] data An array of bytes containing the IR command. +/// @warning data's bit order may change. It is not yet confirmed. +/// @param[in] nbytes Nr. of bytes of data in the array. +/// @param[in] repeat Nr. of times the message is to be repeated. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1826 +void IRsend::sendSanyoAc152(const uint8_t data[], const uint16_t nbytes, + const uint16_t repeat) { + // (Header + Data + Footer) per repeat + sendGeneric(kSanyoAc152HdrMark, kSanyoAc152HdrSpace, + kSanyoAc152BitMark, kSanyoAc152OneSpace, + kSanyoAc152BitMark, kSanyoAc152ZeroSpace, + kSanyoAc152BitMark, kDefaultMessageGap, + data, nbytes, kSanyoAc152Freq, false, repeat, kDutyDefault); + space(kDefaultMessageGap); // Make a guess at a post message gap. +} +#endif // SEND_SANYO_AC152 + +#if DECODE_SANYO_AC152 +/// Decode the supplied SanyoAc152 message. +/// Status: BETA / Probably works. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// @warning data's bit order may change. It is not yet confirmed. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1503 +bool IRrecv::decodeSanyoAc152(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (strict && nbits != kSanyoAc152Bits) + return false; + + // Header + Data + Footer + if (!matchGeneric(results->rawbuf + offset, results->state, + results->rawlen - offset, nbits, + kSanyoAc152HdrMark, kSanyoAc152HdrSpace, + kSanyoAc152BitMark, kSanyoAc152OneSpace, + kSanyoAc152BitMark, kSanyoAc152ZeroSpace, + kSanyoAc152BitMark, + kDefaultMessageGap, // Just a guess. + false, _tolerance + kSanyoAc152ExtraTolerance, + kMarkExcess, false)) + return false; // No match! + + // Success + results->decode_type = decode_type_t::SANYO_AC152; + 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_SANYO_AC152 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sanyo.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sanyo.h index 66376328f..42575cb3b 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sanyo.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sanyo.h @@ -13,6 +13,7 @@ /// @see https://docs.google.com/spreadsheets/d/1dYfLsnYvpjV-SgO8pdinpfuBIpSzm8Q1R5SabrLeskw/edit?usp=sharing /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1503 /// @see https://docs.google.com/spreadsheets/d/1weUmGAsEpfX38gg5rlDN69Uchnbr6gQl9FqHffLBIRk/edit#gid=0 +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1826 // Supports: // Brand: Sanyo, Model: SA 8650B - disabled @@ -21,6 +22,8 @@ // Brand: Sanyo, Model: RCS-2HS4E remote (SANYO_AC) // Brand: Sanyo, Model: SAP-K242AH A/C (SANYO_AC) // Brand: Sanyo, Model: RCS-2S4E remote (SANYO_AC) +// Brand: Sanyo, Model: RCS-4MHVPIS4EE remote (SANYO_AC152) +// Brand: Sanyo, Model: SAP-KMRV124EHE A/C (SANYO_AC152) #ifndef IR_SANYO_H_ #define IR_SANYO_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sony.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sony.cpp index 5746ee9b1..fb7b9af6f 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sony.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sony.cpp @@ -11,6 +11,7 @@ // Supports: // Brand: Sony, Model: HT-CT380 Soundbar (Uses 38kHz & 3 repeats) +// Brand: Sony, Model: HT-SF150 Soundbar (Uses 38kHz & 3 repeats) #include #include "IRrecv.h" diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.cpp index 1aceef44b..45e210f2b 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.cpp @@ -1,4 +1,4 @@ -// Copyright 2019, 2021 David Conran +// Copyright 2019, 2021, 2022 David Conran /// @file /// @brief Support for TCL protocols. @@ -14,10 +14,19 @@ #include "IRutils.h" // Constants - const uint8_t kTcl112AcTimerResolution = 20; // Minutes const uint16_t kTcl112AcTimerMax = 720; // Minutes (12 hrs) +const uint16_t kTcl96AcHdrMark = 1056; // uSeconds. +const uint16_t kTcl96AcHdrSpace = 550; // uSeconds. +const uint16_t kTcl96AcBitMark = 600; // uSeconds. +const uint32_t kTcl96AcGap = kDefaultMessageGap; // Just a guess. +const uint8_t kTcl96AcSpaceCount = 4; +const uint16_t kTcl96AcBitSpaces[kTcl96AcSpaceCount] = {360, // 0b00 + 838, // 0b01 + 2182, // 0b10 + 1444}; // 0b11 + using irutils::addBoolToString; using irutils::addFanToString; using irutils::addIntToString; @@ -527,3 +536,81 @@ String IRTcl112Ac::toString(void) const { /// It's the same as `decodeMitsubishi112()`. A shared routine is used. /// You can find it in: ir_Mitsubishi.cpp #endif // DECODE_TCL112AC + +#if SEND_TCL96AC +/// Send a TCL 96-bit A/C message. +/// Status: BETA / Untested on a real device working. +/// @param[in] data The message to be sent. +/// @param[in] nbytes The number of bytes of message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +void IRsend::sendTcl96Ac(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + enableIROut(38); + for (uint16_t r = 0; r <= repeat; r++) { + // Header + mark(kTcl96AcHdrMark); + space(kTcl96AcHdrSpace); + // Data + for (uint16_t pos = 0; pos < nbytes; pos++) { + uint8_t databyte = data[pos]; + for (uint8_t bits = 0; bits < 8; bits += 2) { + mark(kTcl96AcBitMark); + space(kTcl96AcBitSpaces[GETBITS8(databyte, 8 - 2, 2)]); + databyte <<= 2; + } + } + // Footer + mark(kTcl96AcBitMark); + space(kTcl96AcGap); + } +} +#endif // SEND_TCL96AC + +#if DECODE_TCL96AC +/// Decode the supplied Tcl96Ac message. +/// Status: ALPHA / Experimental. +/// @param[in,out] results Ptr to the data to decode & where to store the result +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return True if it can decode it, false if it can't. +bool IRrecv::decodeTcl96Ac(decode_results* results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < nbits + kHeader + kFooter - 1 + offset) + return false; // Message is smaller than we expected. + if (strict && nbits != kTcl96AcBits) + return false; // Not strictly a TCL96AC message. + uint8_t data = 0; + // Header. + if (!matchMark(results->rawbuf[offset++], kTcl96AcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kTcl96AcHdrSpace)) return false; + // Data (2 bits at a time) + for (uint16_t bits_so_far = 0; bits_so_far < nbits; bits_so_far += 2) { + if (bits_so_far % 8) + data <<= 2; // Make space for the new data bits. + else + data = 0; + if (!matchMark(results->rawbuf[offset++], kTcl96AcBitMark)) return false; + uint8_t value = 0; + while (value < kTcl96AcSpaceCount) { + if (matchSpace(results->rawbuf[offset], kTcl96AcBitSpaces[value])) { + data += value; + break; + } + value++; + } + if (value >= kTcl96AcSpaceCount) return false; // No matches. + offset++; + *(results->state + bits_so_far / 8) = data; + } + // Footer + if (!matchMark(results->rawbuf[offset++], kTcl96AcBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kTcl96AcGap)) return false; + // Success + results->decode_type = TCL96AC; + results->bits = nbits; + return true; +} +#endif // DECODE_TCL96AC diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h index c7ae038d0..805270aa2 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h @@ -10,6 +10,7 @@ // Brand: Teknopoint, Model: GZ-055B-E1 remote (GZ055BE1) // Brand: Daewoo, Model: DSB-F0934ELH-V A/C // Brand: Daewoo, Model: GYKQ-52E remote +// Brand: TCL, Model: GYKQ-58(XM) remote (TCL96AC) #ifndef IR_TCL_H_ #define IR_TCL_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toto.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toto.cpp new file mode 100644 index 000000000..2997e760e --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toto.cpp @@ -0,0 +1,131 @@ +// Copyright 2022 David Conran (crankyoldgit) +/// @file +/// @brief Support for the Toto Toilet IR protocols. +/// @see https://www.d-resi.jp/dt/nishi-shinjuku/limited/imgs/pdf/book6.pdf +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1806 + +// Supports: +// Brand: Toto, Model: Washlet Toilet NJ + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// Constants +const uint16_t kTotoHdrMark = 6197; +const uint16_t kTotoHdrSpace = 2754; +const uint16_t kTotoBitMark = 600; +const uint16_t kTotoOneSpace = 1634; +const uint16_t kTotoZeroSpace = 516; +const uint16_t kTotoGap = 38000; +const uint16_t kTotoSpecialGap = 42482; +const uint64_t kTotoPrefix = 0x0802; +const uint16_t kTotoPrefixBits = 15; + +#if SEND_TOTO +/// Send a Toto Toilet formatted message. +/// Status: BETA / Seems to work. +/// @param[in] data The message to be sent. +/// @param[in] nbits The number of bits of message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1806 +void IRsend::sendToto(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + if (nbits <= kTotoShortBits) { // Short code message. + sendGeneric(kTotoHdrMark, kTotoHdrSpace, + kTotoBitMark, kTotoOneSpace, + kTotoBitMark, kTotoZeroSpace, + kTotoBitMark, kTotoGap, + (data << kTotoPrefixBits) | kTotoPrefix, + nbits + kTotoPrefixBits, + 38, false, repeat, kDutyDefault); + } else { // Long code message + // This is really two messages sent at least one extra time each. + sendToto(data >> kTotoShortBits, nbits - kTotoShortBits, repeat + 1); + sendToto(GETBITS64(data, 0, kTotoShortBits), kTotoShortBits, repeat + 1); + } +} +#endif // SEND_TOTO + +#if DECODE_TOTO +/// Decode the supplied Toto Toilet message. +/// Status: ALPHA / Untested. +/// @param[in,out] results Ptr to the data to decode & where to store the result +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return True if it can decode it, false if it can't. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1806 +bool IRrecv::decodeToto(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (strict && nbits != kTotoShortBits && nbits != kTotoLongBits) + return false; // We expect Toto to be a certain sized messages. + + const uint16_t repeats = (nbits > kTotoShortBits) ? kTotoDefaultRepeat + 1 + : kTotoDefaultRepeat; + const uint16_t ksections = (nbits > kTotoShortBits) ? 2 : 1; + const uint16_t ksection_bits = nbits / ksections; + + if (results->rawlen < (2 * (nbits + kTotoPrefixBits) + kHeader + kFooter) * + (repeats + 1) - 1 + offset) + return false; // We don't have enough entries to possibly match. + + uint16_t used = 0; + + // Long messages have two sections, short have only one. + for (uint16_t section = 1; section <= ksections; section++) { + results->value <<= ksection_bits; + uint64_t data = 0; + uint64_t repeat_data = 0; + for (uint16_t r = 0; r <= repeats; r++) { // We expect a repeat. + uint64_t prefix = 0; + // Header + Prefix + used = matchGeneric(results->rawbuf + offset, &prefix, + results->rawlen - offset, kTotoPrefixBits, + kTotoHdrMark, kTotoHdrSpace, + kTotoBitMark, kTotoOneSpace, + kTotoBitMark, kTotoZeroSpace, + 0, 0, false, // No Footer + kUseDefTol, kMarkExcess, false); + if (!used) return false; // Didn't match, so fail. + offset += used; + if (strict && (prefix != kTotoPrefix)) return false; + // Data + Footer + Gap + used = matchGeneric(results->rawbuf + offset, &data, + results->rawlen - offset, ksection_bits, + 0, 0, // No Header + kTotoBitMark, kTotoOneSpace, + kTotoBitMark, kTotoZeroSpace, + kTotoBitMark, kTotoGap, true, + kUseDefTol, kMarkExcess, false); + if (!used) return false; // Didn't match, so fail. + offset += used; + if (strict) { + if (r && data != repeat_data) return false; // Repeat didn't match. + // Integrity check. + uint8_t result = 0; + uint64_t check = data; + uint16_t bits = 0; + // Loop over the data 8 bits at a time. + while (bits < ksection_bits) { + result ^= (check & 0b111111111); // Xor with the last 8 bits. + bits += 8; + check >>= 8; + } + if (result) return false; // Intergrity check failed. + } + repeat_data = data; + } + results->value |= data; + } + // Success + results->bits = nbits; + results->decode_type = decode_type_t::TOTO; + results->command = GETBITS64(results->value, 0, ksection_bits - 8); + results->address = GETBITS64(results->value, ksection_bits, + ksection_bits - 8); + return true; +} +#endif // DECODE_TOTO diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Voltas.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Voltas.h index cf79d3458..d8ad77bcb 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Voltas.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Voltas.h @@ -9,6 +9,7 @@ // // Ref: https://docs.google.com/spreadsheets/d/1zzDEUQ52y7MZ7_xCU3pdjdqbRXOwZLsbTGvKWcicqCI/ // Ref: https://www.corona.co.jp/box/download.php?id=145060636229 +// Ref: https://github.com/crankyoldgit/IRremoteESP8266/files/8646964/Voltas.Window.AC.122LZF.Remote.Instructions.pdf #ifndef IR_VOLTAS_H_ #define IR_VOLTAS_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h index a623039f0..40b85c27c 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h @@ -566,6 +566,9 @@ D_STR_INDIRECT " " D_STR_MODE #ifndef D_STR_YBOFB #define D_STR_YBOFB "YBOFB" #endif // D_STR_YBOFB +#ifndef D_STR_YX1FSF +#define D_STR_YX1FSF "YX1FSF" +#endif // D_STR_YX1FSF #ifndef D_STR_V9014557_A #define D_STR_V9014557_A "V9014557-A" #endif // D_STR_V9014557_A @@ -706,6 +709,12 @@ D_STR_INDIRECT " " D_STR_MODE #ifndef D_STR_ARRIS #define D_STR_ARRIS "ARRIS" #endif // D_STR_ARRIS +#ifndef D_STR_BOSCH +#define D_STR_BOSCH "BOSCH" +#endif // D_STR_BOSCH +#ifndef D_STR_BOSCH144 +#define D_STR_BOSCH144 D_STR_BOSCH "144" +#endif // D_STR_BOSCH144 #ifndef D_STR_BOSE #define D_STR_BOSE "BOSE" #endif // D_STR_BOSE @@ -718,6 +727,12 @@ D_STR_INDIRECT " " D_STR_MODE #ifndef D_STR_CARRIER_AC64 #define D_STR_CARRIER_AC64 D_STR_CARRIER_AC "64" #endif // D_STR_CARRIER_AC64 +#ifndef D_STR_CARRIER_AC128 +#define D_STR_CARRIER_AC128 D_STR_CARRIER_AC "128" +#endif // D_STR_CARRIER_AC128 +#ifndef D_STR_CLIMABUTLER +#define D_STR_CLIMABUTLER "CLIMABUTLER" +#endif // D_STR_CLIMABUTLER #ifndef D_STR_COOLIX #define D_STR_COOLIX "COOLIX" #endif // D_STR_COOLIX @@ -731,25 +746,31 @@ D_STR_INDIRECT " " D_STR_MODE #define D_STR_DAIKIN "DAIKIN" #endif // D_STR_DAIKIN #ifndef D_STR_DAIKIN128 -#define D_STR_DAIKIN128 "DAIKIN128" +#define D_STR_DAIKIN128 D_STR_DAIKIN "128" #endif // D_STR_DAIKIN128 #ifndef D_STR_DAIKIN152 -#define D_STR_DAIKIN152 "DAIKIN152" +#define D_STR_DAIKIN152 D_STR_DAIKIN "152" #endif // D_STR_DAIKIN152 #ifndef D_STR_DAIKIN160 -#define D_STR_DAIKIN160 "DAIKIN160" +#define D_STR_DAIKIN160 D_STR_DAIKIN "160" #endif // D_STR_DAIKIN160 #ifndef D_STR_DAIKIN176 -#define D_STR_DAIKIN176 "DAIKIN176" +#define D_STR_DAIKIN176 D_STR_DAIKIN "176" #endif // D_STR_DAIKIN176 #ifndef D_STR_DAIKIN2 -#define D_STR_DAIKIN2 "DAIKIN2" +#define D_STR_DAIKIN2 D_STR_DAIKIN "2" #endif // D_STR_DAIKIN2 +#ifndef D_STR_DAIKIN200 +#define D_STR_DAIKIN200 D_STR_DAIKIN "200" +#endif // D_STR_DAIKIN200 #ifndef D_STR_DAIKIN216 -#define D_STR_DAIKIN216 "DAIKIN216" +#define D_STR_DAIKIN216 D_STR_DAIKIN "216" #endif // D_STR_DAIKIN216 +#ifndef D_STR_DAIKIN312 +#define D_STR_DAIKIN312 D_STR_DAIKIN "312" +#endif // D_STR_DAIKIN312 #ifndef D_STR_DAIKIN64 -#define D_STR_DAIKIN64 "DAIKIN64" +#define D_STR_DAIKIN64 D_STR_DAIKIN "64" #endif // D_STR_DAIKIN64 #ifndef D_STR_DELONGHI_AC #define D_STR_DELONGHI_AC "DELONGHI_AC" @@ -794,10 +815,13 @@ D_STR_INDIRECT " " D_STR_MODE #define D_STR_HAIER_AC "HAIER_AC" #endif // D_STR_HAIER_AC #ifndef D_STR_HAIER_AC_YRW02 -#define D_STR_HAIER_AC_YRW02 "HAIER_AC_YRW02" +#define D_STR_HAIER_AC_YRW02 D_STR_HAIER_AC "_YRW02" #endif // D_STR_HAIER_AC_YRW02 +#ifndef D_STR_HAIER_AC160 +#define D_STR_HAIER_AC160 D_STR_HAIER_AC "160" +#endif // D_STR_HAIER_AC160 #ifndef D_STR_HAIER_AC176 -#define D_STR_HAIER_AC176 "HAIER_AC176" +#define D_STR_HAIER_AC176 D_STR_HAIER_AC "176" #endif // D_STR_HAIER_AC176 #ifndef D_STR_HITACHI_AC #define D_STR_HITACHI_AC "HITACHI_AC" @@ -959,13 +983,16 @@ D_STR_INDIRECT " " D_STR_MODE #define D_STR_SANYO "SANYO" #endif // D_STR_SANYO #ifndef D_STR_SANYO_AC -#define D_STR_SANYO_AC "SANYO_AC" +#define D_STR_SANYO_AC D_STR_SANYO "_AC" #endif // D_STR_SANYO_AC #ifndef D_STR_SANYO_AC88 -#define D_STR_SANYO_AC88 "SANYO_AC88" +#define D_STR_SANYO_AC88 D_STR_SANYO_AC "88" #endif // D_STR_SANYO_AC88 +#ifndef D_STR_SANYO_AC152 +#define D_STR_SANYO_AC152 D_STR_SANYO_AC "152" +#endif // D_STR_SANYO_AC152 #ifndef D_STR_SANYO_LC7461 -#define D_STR_SANYO_LC7461 "SANYO_LC7461" +#define D_STR_SANYO_LC7461 D_STR_SANYO "_LC7461" #endif // D_STR_SANYO_LC7461 #ifndef D_STR_SHARP #define D_STR_SHARP "SHARP" @@ -985,6 +1012,9 @@ D_STR_INDIRECT " " D_STR_MODE #ifndef D_STR_SYMPHONY #define D_STR_SYMPHONY "SYMPHONY" #endif // D_STR_SYMPHONY +#ifndef D_STR_TCL96AC +#define D_STR_TCL96AC "TCL96AC" +#endif // D_STR_TCL96AC #ifndef D_STR_TCL112AC #define D_STR_TCL112AC "TCL112AC" #endif // D_STR_TCL112AC @@ -1000,6 +1030,9 @@ D_STR_INDIRECT " " D_STR_MODE #ifndef D_STR_TOSHIBA_AC #define D_STR_TOSHIBA_AC "TOSHIBA_AC" #endif // D_STR_TOSHIBA_AC +#ifndef D_STR_TOTO +#define D_STR_TOTO "TOTO" +#endif // D_STR_TOTO #ifndef D_STR_TRANSCOLD #define D_STR_TRANSCOLD "TRANSCOLD" #endif // D_STR_TRANSCOLD diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp index 1947ea532..15351ba61 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp @@ -623,9 +623,9 @@ TEST(TestIRac, Fujitsu) { "Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, " "Fan: 2 (Medium), Command: N/A"; std::string arrah2e_expected = - "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, " - "Fan: 2 (Medium), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Sleep Timer: 03:00"; + "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 10C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: On, " + "Swing: 0 (Off), Command: N/A, Sleep Timer: 03:00"; std::string arry4_expected = "Model: 5 (ARRY4), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, " "Fan: 2 (Medium), Clean: On, Filter: On, Swing: 0 (Off), Command: N/A"; @@ -658,20 +658,21 @@ TEST(TestIRac, Fujitsu) { ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); ac._irsend.reset(); + // Try to set the device to 10C Heat mode. irac.fujitsu(&ac, ARRAH2E, // Model true, // Power - stdAc::opmode_t::kCool, // Mode + stdAc::opmode_t::kFan, // Mode (Fan needed for 10C Heat) true, // Celsius - 19, // Degrees - stdAc::fanspeed_t::kMedium, // Fan speed - stdAc::swingv_t::kOff, // Vertical swing - stdAc::swingh_t::kOff, // Horizontal swing + 19, // Degrees (Ignored in 10C Heat) + stdAc::fanspeed_t::kAuto, // Fan speed (Auto needed for 10C) + stdAc::swingv_t::kOff, // Vertical swing (Ditto) + stdAc::swingh_t::kOff, // Horizontal swing (Ditto) false, // Quiet false, // Turbo (Powerful) false, // Econo true, // Filter - true, // Clean + true, // Clean (Needed for 10C Heat) 3 * 60); // Sleep ASSERT_EQ(arrah2e_expected, ac.toString()); ac._irsend.makeDecodeResult(); @@ -819,6 +820,41 @@ TEST(TestIRac, Haier) { ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); } +TEST(TestIRac, Haier160) { + IRHaierAC160 ac(kGpioUnused); + IRac irac(kGpioUnused); + IRrecv capture(kGpioUnused); + const char expected[] = + "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 23C, " + "Fan: 2 (Medium), Turbo: On, Quiet: Off, Health: On, " + "Swing(V): 4 (High), Sleep: On, " + "Clean: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, " + "Lock: Off, Heating: Off"; + ac.begin(); + irac.haier160(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + true, // Celsius + 23, // Degrees + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kHigh, // Vertical swing + true, // Turbo + false, // Quiet + true, // Filter/Health + true, // Clean + true, // Light + true, // Light (prev) + 8 * 60 + 0); // Sleep time + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(HAIER_AC160, ac._irsend.capture.decode_type); + ASSERT_EQ(kHaierAC160Bits, ac._irsend.capture.bits); + ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); + stdAc::state_t r, p; + ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); +} + TEST(TestIRac, Haier176) { IRHaierAC176 ac(kGpioUnused); IRac irac(kGpioUnused); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Bosch_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Bosch_test.cpp new file mode 100644 index 000000000..dd9402b69 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Bosch_test.cpp @@ -0,0 +1,100 @@ +// Copyright 2022 David Conran + +#include "IRac.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + + +TEST(TestUtils, Housekeeping) { + // Bosch144 + ASSERT_EQ("BOSCH144", typeToString(decode_type_t::BOSCH144)); + ASSERT_EQ(decode_type_t::BOSCH144, strToDecodeType("BOSCH144")); + ASSERT_TRUE(hasACState(decode_type_t::BOSCH144)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::BOSCH144)); + ASSERT_EQ(kBosch144Bits, IRsend::defaultBits(decode_type_t::BOSCH144)); + ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::BOSCH144)); +} + +// Tests for decodeBosch144(). + +// Decode normal Bosch144 messages. +TEST(TestDecodeBosch144, RealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + + // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1787#issuecomment-1099993189 + // Mode: Cool; Fan: 100% ; Temp: 16°C + const uint16_t rawData[299] = { + 4380, 4400, + 528, 1646, 504, 570, 504, 1646, 504, 1646, 504, 572, 502, 570, 504, 1646, + 504, 570, 504, 572, 502, 1646, 504, 570, 502, 570, 502, 1648, 502, 1646, + 502, 570, 502, 1646, 504, 572, 502, 572, 502, 1644, 504, 1646, 504, 1646, + 504, 1646, 502, 1648, 500, 1646, 504, 1646, 504, 1646, 504, 572, 502, 570, + 504, 570, 504, 570, 504, 570, 504, 570, 506, 570, 502, 572, 502, 570, 502, + 572, 502, 572, 502, 572, 502, 572, 502, 572, 500, 1648, 502, 1644, 502, + 1646, 504, 1646, 502, 1646, 504, 1646, 504, 1644, 504, 1646, + 504, 5234, + 4360, 4422, + 504, 1646, 502, 596, 478, 1670, 478, 1646, 504, 570, 504, 572, 500, 1646, + 502, 572, 502, 572, 502, 1644, 506, 570, 502, 570, 504, 1644, 506, 1644, + 502, 574, 502, 1644, 504, 570, 504, 570, 504, 1644, 504, 1646, 504, 1644, + 506, 1644, 504, 1646, 504, 1646, 504, 1644, 504, 1646, 502, 570, 504, 570, + 504, 570, 504, 570, 502, 570, 504, 570, 502, 572, 502, 570, 504, 570, 504, + 570, 504, 570, 502, 572, 502, 570, 506, 570, 504, 1646, 502, 1646, 504, + 1646, 504, 1646, 504, 1646, 502, 1644, 504, 1644, 504, 1646, + 502, 5236, + 4360, 4424, + 504, 1646, 504, 1646, 502, 572, 504, 1644, 504, 570, 504, 1646, 504, 570, + 502, 1644, 504, 570, 504, 1644, 506, 1646, 502, 572, 502, 572, 502, 1646, + 504, 570, 504, 570, 504, 570, 502, 572, 504, 570, 504, 570, 504, 570, 502, + 572, 502, 570, 504, 570, 502, 570, 504, 572, 502, 572, 502, 1646, 504, + 570, 504, 570, 504, 570, 502, 574, 502, 572, 502, 572, 502, 572, 502, 572, + 502, 572, 502, 570, 504, 572, 502, 572, 502, 572, 502, 1646, 504, 572, + 502, 570, 502, 1646, 504, 572, 504, 570, 504, 1644, + 504}; // COOLIX B23F00 + const uint8_t expectedState[kBosch144StateLength] = { + 0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF, + 0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF, + 0xD5, 0x64, 0x00, 0x10, 0x00, 0x49}; + irsend.begin(); + irsend.reset(); + + irsend.sendRaw(rawData, 299, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(decode_type_t::BOSCH144, irsend.capture.decode_type); + EXPECT_EQ(kBosch144Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "Power: On, Mode: 0 (Cool), Fan: 5 (High), Temp: 16C, Quiet: Off", + IRAcUtils::resultAcToString(&irsend.capture)); + stdAc::state_t result, prev; + ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); +} + +TEST(TestDecodeBosch144, SyntheticSelfDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + irsend.reset(); + const uint8_t expectedState[kBosch144StateLength] = { + 0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF, + 0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF, + 0xD5, 0x64, 0x00, 0x10, 0x00, 0x49}; + irsend.sendBosch144(expectedState); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(decode_type_t::BOSCH144, irsend.capture.decode_type); + EXPECT_EQ(kBosch144Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "Power: On, Mode: 0 (Cool), Fan: 5 (High), Temp: 16C, Quiet: Off", + IRAcUtils::resultAcToString(&irsend.capture)); + stdAc::state_t result, prev; + ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Carrier_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Carrier_test.cpp index caf7e46d8..fa0f07b0c 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Carrier_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Carrier_test.cpp @@ -1,8 +1,9 @@ -// Copyright 2018, 2020 David Conran +// Copyright 2018-2022 David Conran #include "ir_Carrier.h" #include "IRac.h" #include "IRrecv.h" +#include "IRrecv_test.h" #include "IRsend.h" #include "IRsend_test.h" #include "gtest/gtest.h" @@ -11,7 +12,7 @@ // Test sending typical data only. TEST(TestSendCarrierAC, SendDataOnly) { - IRsendTest irsend(0); + IRsendTest irsend(kGpioUnused); irsend.begin(); irsend.reset(); @@ -88,7 +89,7 @@ TEST(TestSendCarrierAC, SendDataOnly) { // Test sending typical data only. TEST(TestSendCarrierAC, SendWithRepeats) { - IRsendTest irsend(0); + IRsendTest irsend(kGpioUnused); irsend.begin(); irsend.reset(); @@ -156,7 +157,7 @@ TEST(TestSendCarrierAC, SendWithRepeats) { // Decode normal "synthetic" messages. TEST(TestDecodeCarrierAC, NormalDecodeWithStrict) { - IRsendTest irsend(0); + IRsendTest irsend(kGpioUnused); IRrecv irrecv(0); irsend.begin(); @@ -196,7 +197,7 @@ TEST(TestDecodeCarrierAC, NormalDecodeWithStrict) { // Decode a "real" example message. TEST(TestDecodeCarrierAC, RealExamples) { - IRsendTest irsend(0); + IRsendTest irsend(kGpioUnused); IRrecv irrecv(0); irsend.begin(); @@ -262,6 +263,16 @@ TEST(TestUtils, Housekeeping) { IRsend::defaultBits(decode_type_t::CARRIER_AC64)); ASSERT_EQ(kCarrierAc64MinRepeat, IRsend::minRepeats(decode_type_t::CARRIER_AC64)); + + // CARRIER_AC128 + ASSERT_EQ("CARRIER_AC128", typeToString(decode_type_t::CARRIER_AC128)); + ASSERT_EQ(decode_type_t::CARRIER_AC128, strToDecodeType("CARRIER_AC128")); + ASSERT_TRUE(hasACState(decode_type_t::CARRIER_AC128)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::CARRIER_AC128)); + ASSERT_EQ(kCarrierAc128Bits, + IRsend::defaultBits(decode_type_t::CARRIER_AC128)); + ASSERT_EQ(kCarrierAc128MinRepeat, + IRsend::minRepeats(decode_type_t::CARRIER_AC128)); } /// Decode a "real" example message. @@ -610,3 +621,75 @@ TEST(TestCarrierAc64Class, ReconstructKnownState) { "Sleep: On, On Timer: Off, Off Timer: Off", ac.toString()); } + +// Decode a "real" Carrier 128bit example message. +TEST(TestDecodeCarrierAC128, RealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + const uint8_t expected_state[kCarrierAc128StateLength] = { + 0x16, 0x22, 0x48, 0x19, 0x10, 0x10, 0x16, 0x28, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x80}; + irsend.begin(); + + irsend.reset(); + // Data from: + // https://docs.google.com/spreadsheets/d/1lqs1UDAvUauzAyoVRAGhARKPaSk3pgOO7iHFw9M5HJE/edit#gid=0&range=F3 + const uint16_t rawData[267] = { + 4594, 2614, + 336, 418, 336, 998, 330, 1002, 338, 416, 336, 998, 332, 424, 328, 426, + 336, 416, 336, 418, 334, 1000, 332, 420, 330, 424, 338, 418, 336, 994, + 334, 420, 332, 424, 328, 424, 338, 416, 336, 418, 336, 996, 332, 422, 330, + 424, 338, 992, 338, 416, 336, 998, 332, 424, 336, 418, 336, 994, 336, 998, + 332, 420, 340, 416, 338, 416, 334, 420, 334, 420, 332, 424, 328, 426, 336, + 994, 336, 418, 334, 422, 330, 422, 332, 422, 338, 416, 338, 416, 336, 418, + 332, 1000, 332, 424, 336, 416, 338, 418, 334, 420, 332, 1000, 332, 1002, + 336, 416, 338, 994, 334, 422, 330, 424, 338, 416, 336, 416, 336, 420, 332, + 422, 330, 1000, 342, 412, 338, 996, 334, 422, 332, 402, + 338, 20636, + 4604, 6724, + 9296, 4976, + 356, 426, 336, 418, 334, 420, 332, 420, 330, 424, 340, 414, 338, 416, 336, + 420, 334, 418, 334, 420, 332, 422, 340, 416, 336, 418, 336, 416, 336, 420, + 332, 420, 332, 424, 338, 416, 336, 418, 336, 994, 334, 422, 332, 422, 340, + 412, 338, 418, 334, 418, 334, 420, 332, 422, 332, 424, 340, 414, 338, 414, + 336, 420, 334, 420, 330, 424, 328, 426, 336, 416, 336, 418, 334, 420, 366, + 388, 362, 392, 358, 392, 360, 394, 368, 386, 368, 388, 364, 388, 366, 390, + 360, 394, 358, 394, 368, 388, 366, 386, 366, 390, 362, 392, 358, 394, 360, + 394, 370, 384, 366, 388, 362, 390, 362, 390, 362, 392, 360, 396, 368, 384, + 366, 390, 364, 390, 362, 392, 360, 954, + 336, 20638, + 4622}; + + irsend.sendRaw(rawData, 267, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(CARRIER_AC128, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAc128Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected_state, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); +} + +// Decode a synthetic Carrier AC 128-bit message. +TEST(TestDecodeCarrierAC128, SyntheticExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + const uint8_t expected_state[kCarrierAc128StateLength] = { + 0x16, 0x22, 0x48, 0x19, 0x10, 0x10, 0x16, 0x28, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x80}; + irsend.reset(); + irsend.sendCarrierAC128(expected_state); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(CARRIER_AC128, irsend.capture.decode_type); + ASSERT_EQ(kCarrierAc128Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected_state, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); + stdAc::state_t r, p; + ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_ClimaButler_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_ClimaButler_test.cpp new file mode 100644 index 000000000..6a9841d27 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_ClimaButler_test.cpp @@ -0,0 +1,67 @@ +// Copyright 2022 crankyoldgit + +#include "IRac.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for decodeClimaButler(). +TEST(TestDecodeClimaButler, RealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + const uint16_t rawData[109] = { + 554, 3512, + 558, 1488, 580, 496, 522, 494, 546, 558, 552, 494, 548, 496, 546, 500, + 548, 558, 544, 504, 544, 502, 540, 506, 538, 570, 514, 530, 514, 532, 512, + 534, 512, 592, 512, 536, 510, 532, 510, 536, 510, 598, 510, 536, 506, 536, + 514, 534, 510, 594, 514, 534, 510, 536, 534, 510, 510, 598, 514, 534, 510, + 536, 508, 536, 534, 572, 534, 500, 512, 1536, 512, 526, 510, 1588, 512, + 1536, 510, 538, 512, 532, 510, 588, 510, 1536, 514, 532, 510, 536, 534, + 570, 512, 534, 510, 536, 514, 528, 540, 568, 540, 506, 512, 524, 510, + 1534, 516, 532, + 536, 3396, + 544}; // UNKNOWN E6CA5369 POWER OFF + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData, 109, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(decode_type_t::CLIMABUTLER, irsend.capture.decode_type); + ASSERT_EQ(kClimaButlerBits, irsend.capture.bits); + EXPECT_EQ(0x8000000058802, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); + stdAc::state_t r, p; + ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); +} + +TEST(TestDecodeClimaButler, SyntheticExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + irsend.reset(); + irsend.sendClimaButler(0x8000000058802); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(decode_type_t::CLIMABUTLER, irsend.capture.decode_type); + ASSERT_EQ(kClimaButlerBits, irsend.capture.bits); + EXPECT_EQ(0x8000000058802, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +TEST(TestUtils, Housekeeping) { + ASSERT_EQ("CLIMABUTLER", typeToString(decode_type_t::CLIMABUTLER)); + ASSERT_EQ(decode_type_t::CLIMABUTLER, strToDecodeType("CLIMABUTLER")); + ASSERT_FALSE(hasACState(decode_type_t::CLIMABUTLER)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::CLIMABUTLER)); + ASSERT_EQ(kClimaButlerBits, IRsend::defaultBits(decode_type_t::CLIMABUTLER)); + ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::CLIMABUTLER)); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Daikin_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Daikin_test.cpp index 783bd4e66..71641d4dc 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Daikin_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Daikin_test.cpp @@ -1552,6 +1552,20 @@ TEST(TestUtils, Housekeeping) { ASSERT_EQ(decode_type_t::DAIKIN64, strToDecodeType("DAIKIN64")); ASSERT_FALSE(hasACState(decode_type_t::DAIKIN64)); ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::DAIKIN64)); + + ASSERT_EQ("DAIKIN200", typeToString(decode_type_t::DAIKIN200)); + ASSERT_EQ(decode_type_t::DAIKIN200, strToDecodeType("DAIKIN200")); + ASSERT_TRUE(hasACState(decode_type_t::DAIKIN200)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::DAIKIN200)); + ASSERT_EQ(kDaikin200Bits, IRsend::defaultBits(decode_type_t::DAIKIN200)); + ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::DAIKIN200)); + + ASSERT_EQ("DAIKIN312", typeToString(decode_type_t::DAIKIN312)); + ASSERT_EQ(decode_type_t::DAIKIN312, strToDecodeType("DAIKIN312")); + ASSERT_TRUE(hasACState(decode_type_t::DAIKIN312)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::DAIKIN312)); + ASSERT_EQ(kDaikin312Bits, IRsend::defaultBits(decode_type_t::DAIKIN312)); + ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::DAIKIN312)); } // https://github.com/crankyoldgit/IRremoteESP8266/issues/582#issuecomment-453863879 @@ -3879,3 +3893,228 @@ TEST(TestDaikin176Class, UnitId) { ASSERT_EQ(0, ac.getId()); EXPECT_STATE_EQ(unita, ac.getRaw(), kDaikin176Bits); } + +TEST(TestDaikin128Class, Issue1754_HeatMode) { + // Data from "MODE HEAT" + // Mesg Desc.: Power Toggle: Off, Mode: 8 (Heat), Temp: 19C, Fan: 4 (Medium), + // Powerful: Off, Quiet: Off, Swing(V): Off, Sleep: Off, Econo: Off, + // Clock: 20:22, On Timer: Off, On Timer: 10:00, Off Timer: Off, + // Off Timer: 16:30, Light Toggle: 0 (Off) + // Ref: https://docs.google.com/document/d/1bhPlwsUE4ppL1dlX6_aYmqCSxeE6HlOumYsR35S0CKA/edit#heading=h.luu34vdlzof1 + + const uint8_t heatmode[16] = { // As recorded from a real remote. + 0x16, 0x48, 0x22, 0x20, 0x10, 0x56, 0x19, 0x34, + 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B}; + + IRDaikin128 ac(kGpioUnused); + // Try to reproduce the exact same state. + ac.setClock(20 * 60 + 22); + ac.setOnTimer(10 * 60); + ac.setOnTimerEnabled(false); + ac.setOffTimer(16 * 60 + 30); + ac.setOffTimerEnabled(false); + ac.setPowerToggle(false); + ac.setTemp(19); + ac.setFan(kDaikin128FanMed); + ac.setPowerful(false); + ac.setQuiet(false); + ac.setSwingVertical(false); + ac.setSleep(false); + ac.setEcono(false); + ac.setLightToggle(0); + ac.setMode(kDaikin128Heat); + + EXPECT_EQ( + "Power Toggle: Off, Mode: 8 (Heat), Temp: 19C, Fan: 4 (Medium), " + "Powerful: Off, Quiet: Off, Swing(V): Off, Sleep: Off, Econo: Off, " + "Clock: 20:22, On Timer: Off, On Timer: 10:00, Off Timer: Off, " + "Off Timer: 16:30, Light Toggle: 0 (Off)", + ac.toString()); + // Compare the synthetic state to the captured one. + EXPECT_STATE_EQ(heatmode, ac.getRaw(), kDaikin128Bits); +} + +// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1802 +TEST(TestDecodeDaikin200, RealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + const uint16_t rawData[407] = { + 4852, 2298, + 202, 1942, 202, 870, 200, 870, 202, 868, 202, 1942, 202, 870, 202, 870, + 202, 870, 202, 870, 202, 1942, 202, 870, 202, 1942, 202, 1942, 202, 868, + 202, 1942, 202, 1942, 202, 1912, 232, 1942, 202, 1942, 202, 868, 202, + 1942, 202, 870, 202, 870, 202, 868, 202, 868, 204, 868, 202, 870, 202, + 1942, 202, 868, 204, 868, 202, 1942, 202, 870, 202, 870, 200, 870, 202, + 1942, 202, 868, 202, 870, 202, 870, 202, 870, 202, 870, 202, 870, 202, + 870, 202, 870, 202, 868, 202, 868, 204, 868, 202, 870, 202, 870, 202, 870, + 202, 1942, 202, 1942, 202, 1942, 202, 868, 202, 868, 204, 1942, 202, 870, + 202, 29468, + 4880, 2266, + 256, 1888, 230, 844, 202, 868, 202, 870, 256, 1888, 230, 842, 228, 842, + 230, 842, 256, 814, 232, 1914, 254, 816, 230, 1916, 256, 1888, 256, 814, + 256, 1890, 254, 1888, 256, 1888, 256, 1888, 256, 1888, 256, 816, 230, + 1912, 258, 814, 256, 816, 256, 816, 282, 790, 280, 790, 282, 790, 282, + 1862, 258, 814, 280, 790, 282, 1862, 280, 792, 280, 790, 282, 788, 282, + 790, 282, 790, 282, 790, 282, 790, 282, 788, 282, 790, 282, 1862, 282, + 1862, 282, 790, 282, 788, 282, 1862, 282, 1864, 280, 1862, 282, 790, 280, + 790, 282, 790, 282, 790, 282, 788, 284, 790, 282, 760, 310, 790, 282, 788, + 282, 1862, 282, 788, 282, 790, 282, 788, 282, 788, 282, 1862, 284, 788, + 282, 788, 284, 788, 282, 790, 282, 788, 284, 788, 282, 790, 282, 788, 284, + 758, 312, 788, 284, 788, 282, 788, 284, 788, 282, 788, 284, 788, 282, 788, + 284, 788, 284, 758, 314, 786, 284, 788, 284, 1860, 282, 790, 282, 790, + 282, 1862, 282, 758, 312, 762, 310, 788, 284, 788, 282, 758, 314, 758, + 314, 1862, 282, 760, 312, 1860, 284, 760, 310, 788, 282, 760, 312, 788, + 284, 760, 312, 788, 282, 790, 282, 788, 284, 788, 282, 790, 282, 788, 282, + 758, 314, 788, 282, 758, 314, 1862, 282, 758, 312, 788, 284, 758, 312, + 758, 314, 788, 282, 758, 314, 758, 312, 788, 284, 788, 284, 758, 312, 760, + 312, 762, 310, 790, 284, 788, 282, 758, 314, 758, 312, 788, 282, 760, 312, + 760, 312, 760, 312, 788, 282, 758, 314, 788, 284, 788, 284, 758, 312, 788, + 282, 790, 282, 1832, 310, 758, 316, 788, 284, 1862, 282, 1862, 282, 1832, + 310, 788, 284}; // UNKNOWN 3BFB2888 + + const uint8_t expectedState[kDaikin200StateLength] = { + 0x11, 0xDA, 0x17, 0x48, 0x04, 0x00, 0x4E, // Section 1 + 0x11, 0xDA, 0x17, 0x48, 0x00, 0x73, 0x00, 0x21, 0x00, // Section 2 + 0x00, 0x24, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00, 0x72}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData, 407, kDaikin64Freq); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(decode_type_t::DAIKIN200, irsend.capture.decode_type); + ASSERT_EQ(kDaikin200Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); + stdAc::state_t result, prev; + ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeDaikin200, SyntheticExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + const uint8_t expectedState[kDaikin200StateLength] = { + 0x11, 0xDA, 0x17, 0x48, 0x04, 0x00, 0x4E, // Section 1 + 0x11, 0xDA, 0x17, 0x48, 0x00, 0x73, 0x00, 0x21, 0x00, // Section 2 + 0x00, 0x24, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00, 0x72}; + + irsend.reset(); + irsend.sendDaikin200(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN200, irsend.capture.decode_type); + ASSERT_EQ(kDaikin200Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); +} + +/// https://github.com/crankyoldgit/IRremoteESP8266/issues/1829#issuecomment-1173077011 +TEST(TestDecodeDaikin312, RealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + // Ref: https://github.com/crankyoldgit/IRremoteESP8266/files/9034763/on_coling_210_fan_auto.txt.out.txt + const uint16_t rawData[643] = { + 508, 390, 452, 414, 452, 414, 452, 414, 452, 414, + 452, 25104, + 3518, 1688, + 478, 1256, 478, 414, 452, 414, 452, 414, 452, 1282, 452, 414, 452, 414, + 452, 414, 452, 414, 452, 1280, 454, 414, 452, 1256, 478, 1254, 478, 414, + 452, 1280, 452, 1282, 452, 1282, 452, 1282, 478, 1256, 480, 386, 452, 414, + 452, 1282, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, + 454, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 1280, 452, 414, + 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 1282, + 452, 414, 452, 414, 452, 414, 452, 1280, 452, 1280, 452, 418, 450, 1280, + 452, 1282, 452, 414, 452, 1282, 452, 414, 452, 416, 452, 1280, 454, 414, + 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, + 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 454, 414, + 452, 414, 452, 1282, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, + 452, 414, 454, 414, 452, 414, 452, 414, 452, 414, 452, 414, 478, 388, 452, + 414, 452, 414, 452, 414, 452, 414, 452, 414, 454, 414, 452, 414, 452, 414, + 452, 414, 452, 414, 452, 414, 452, 1282, 452, 414, 452, 414, 452, 414, + 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, + 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, + 478, 388, 452, 414, 478, 388, 452, 414, 452, 414, 452, 414, 452, 414, 452, + 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, + 452, 414, 452, 414, 452, 414, 452, 414, 448, 418, 448, 418, 448, 418, 448, + 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, + 448, 418, 448, 418, 448, 418, 448, 418, 448, 420, 448, 418, 450, 418, 448, + 1286, 448, 1286, 448, 420, 448, 418, 448, 418, 448, 418, 448, 1284, 448, + 1286, + 448, 35512, + 3518, 1688, + 478, 1282, 452, 414, 452, 414, 452, 414, 452, 1282, 452, 414, 452, 414, + 452, 414, 452, 414, 452, 1280, 452, 414, 452, 1256, 478, 1254, 478, 414, + 452, 1280, 452, 1282, 452, 1282, 452, 1282, 452, 1280, 452, 414, 452, 414, + 452, 1280, 452, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, + 448, 418, 448, 418, 452, 414, 448, 418, 448, 418, 448, 418, 448, 418, 448, + 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 1286, 452, 414, 452, + 414, 452, 1280, 452, 1282, 452, 1282, 452, 414, 452, 414, 452, 414, 452, + 1256, 478, 414, 452, 1282, 452, 414, 452, 1256, 478, 414, 452, 414, 452, + 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, + 454, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 1282, 452, 414, + 452, 1256, 478, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, + 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, + 414, 452, 414, 452, 414, 452, 414, 452, 1286, 448, 1286, 448, 418, 448, + 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, + 448, 418, 448, 1286, 448, 1286, 448, 418, 448, 418, 448, 418, 448, 418, + 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 420, 448, + 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 1260, 474, + 418, 448, 1264, 470, 418, 448, 418, 448, 418, 448, 1258, 474, 1260, 474, + 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 452, 414, 452, 414, + 452, 414, 452, 416, 452, 414, 448, 1264, 478, 384, 474, 418, 448, 418, + 448, 418, 448, 418, 448, 418, 448, 418, 448, 1260, 504, 362, 474, 418, + 448, 1260, 478, 388, 474}; // UNKNOWN 34EEF8FF + + const uint8_t expectedState[kDaikin312StateLength] = { + // Section 1 + 0x11, 0xDA, 0x27, 0x00, 0x02, 0x62, 0x4B, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, + // Section 2 + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x39, 0x2A, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC5, 0x00, 0x08, 0x48}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData, 643, kDaikin64Freq); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(decode_type_t::DAIKIN312, irsend.capture.decode_type); + ASSERT_EQ(kDaikin312Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); + stdAc::state_t result, prev; + ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeDaikin312, SyntheticExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + const uint8_t expectedState[kDaikin312StateLength] = { + // Section 1 + 0x11, 0xDA, 0x27, 0x00, 0x02, 0x62, 0x4B, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, + // Section 2 + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x39, 0x2A, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC5, 0x00, 0x08, 0x48}; + + irsend.reset(); + irsend.sendDaikin312(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN312, irsend.capture.decode_type); + ASSERT_EQ(kDaikin312Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Fujitsu_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Fujitsu_test.cpp index b3d7cff34..ed5ee59f1 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Fujitsu_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Fujitsu_test.cpp @@ -22,7 +22,7 @@ TEST(TestIRFujitsuACClass, GetRawDefault) { EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, " + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 3 (Swing(V)+Swing(H)), Command: N/A, Timer: Off", ac.toString()); @@ -45,7 +45,7 @@ TEST(TestIRFujitsuACClass, GetRawTurnOff) { EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 7 * 8); EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, " + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 3 (Swing(V)+Swing(H)), Command: N/A, Timer: Off", ac.toString()); @@ -66,8 +66,8 @@ TEST(TestIRFujitsuACClass, GetRawStepHoriz) { EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), " - "Command: Step Swing(H), Timer: Off", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 3 (Swing(V)+Swing(H)), Command: Step Swing(H), Timer: Off", ac.toString()); } @@ -80,8 +80,8 @@ TEST(TestIRFujitsuACClass, GetRawStepVert) { EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), " - "Command: Step Swing(V), Timer: Off", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 3 (Swing(V)+Swing(H)), Command: Step Swing(V), Timer: Off", ac.toString()); ac.setModel(ARDB1); @@ -106,7 +106,7 @@ TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) { 0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB}; EXPECT_STATE_EQ(expected, ac.getRaw(), 16 * 8); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 25C, " - "Fan: 4 (Quiet), Clean: Off, Filter: Off, " + "Fan: 4 (Quiet), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 2 (Swing(H)), Command: N/A, Timer: Off", ac.toString()); } @@ -126,7 +126,7 @@ TEST(TestIRFujitsuACClass, GetRawWithFan) { EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 20C, " - "Fan: 2 (Medium), Clean: Off, Filter: Off, " + "Fan: 2 (Medium), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 2 (Swing(H)), Command: N/A, Timer: Off", ac.toString()); @@ -149,7 +149,7 @@ TEST(TestIRFujitsuACClass, SetRaw) { EXPECT_STATE_EQ(expected_default_arrah2e, ac.getRaw(), ac.getStateLength() * 8); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, " + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 3 (Swing(V)+Swing(H)), Command: N/A, " "Timer: Off", ac.toString()); @@ -318,9 +318,7 @@ TEST(TestDecodeFujitsuAC, SyntheticShortMessages) { uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD}; EXPECT_STATE_EQ(expected_arrah2e, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 0 (Auto), Temp: 16C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Model: 1 (ARRAH2E), Id: 0, Power: Off, Command: N/A", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t r, p; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); @@ -365,7 +363,7 @@ TEST(TestDecodeFujitsuAC, SyntheticLongMessages) { ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 18C, " - "Fan: 4 (Quiet), Clean: Off, Filter: Off, " + "Fan: 4 (Quiet), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 1 (Swing(V)), Command: N/A, " "Timer: Off", ac.toString()); @@ -541,8 +539,8 @@ TEST(TestDecodeFujitsuAC, Issue414) { EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 4 (Heat), Temp: 24C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); // Resend it using the state this time. @@ -617,9 +615,7 @@ TEST(TestIRFujitsuACClass, toCommon) { // Now test it. EXPECT_EQ( // Off mode technically has no temp, mode, fan, etc. - "Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 0 (Auto), Temp: 16C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Model: 1 (ARRAH2E), Id: 0, Power: 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); @@ -723,7 +719,7 @@ TEST(TestIRFujitsuACClass, OutsideQuiet) { // the option is set. Otheriwse they appear the same. EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), " + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " "Command: N/A, Timer: Off", ac.toString()); ac.setModel(fujitsu_ac_remote_model_t::ARREB1E); EXPECT_EQ( @@ -826,8 +822,8 @@ TEST(TestDecodeFujitsuAC, Issue726) { EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 24C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); } @@ -859,16 +855,16 @@ TEST(TestIRFujitsuACClass, Clean) { EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); // Now it is in ARRAH2E model mode, it shouldn't accept setting it on. ac.setClean(true); EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.getModel()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); // But ARRY4 does. ac.setModel(fujitsu_ac_remote_model_t::ARRY4); @@ -905,8 +901,8 @@ TEST(TestIRFujitsuACClass, Filter) { EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); // Now it is in ARRAH2E model mode, it shouldn't accept setting it on. ac.setFilter(true); @@ -934,8 +930,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOffSleepTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "On Timer: 12:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, On Timer: 12:00", ac.toString()); const uint8_t timer_on_8h30m[kFujitsuAcStateLength] = { @@ -948,8 +944,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOffSleepTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "On Timer: 08:30", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, On Timer: 08:30", ac.toString()); // TIMER OFF 11H @@ -963,8 +959,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOnTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Off Timer: 11:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Off Timer: 11:00", ac.toString()); // TIMER OFF 0.5H @@ -978,8 +974,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOnTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Off Timer: 00:30", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Off Timer: 00:30", ac.toString()); // TIMER SLEEP 3H @@ -993,8 +989,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOnTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Sleep Timer: 03:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Sleep Timer: 03:00", ac.toString()); // Re-construct a known timer state from scratch. @@ -1011,8 +1007,8 @@ TEST(TestIRFujitsuACClass, Timers) { ac.setOffTimer(30); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Off Timer: 00:30", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Off Timer: 00:30", ac.toString()); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_STATE_EQ(timer_off_30m, ac.getRaw(), ac.getStateLength() * 8); @@ -1020,8 +1016,8 @@ TEST(TestIRFujitsuACClass, Timers) { ac.setOnTimer(12 * 60); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "On Timer: 12:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, On Timer: 12:00", ac.toString()); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ(12 * 60, ac.getOnTimer()); @@ -1033,8 +1029,8 @@ TEST(TestIRFujitsuACClass, Timers) { ac.setSleepTimer(3 * 60); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Sleep Timer: 03:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Sleep Timer: 03:00", ac.toString()); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_STATE_EQ(timer_sleep_3h, ac.getRaw(), ac.getStateLength() * 8); @@ -1122,7 +1118,7 @@ TEST(TestIRFujitsuACClass, Heat10Deg) { 0x69, 0x0B, 0x00, 0x23, 0x06, 0x23, 0x20, 0xEF}; ac.setRaw(heat_on, kFujitsuAcStateLength); EXPECT_EQ( - "Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 21C, " + "Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 10C, " "Fan: 0 (Auto), 10C Heat: On, Swing: 0 (Off), Command: N/A, " "Outside Quiet: Off, Timer: Off", ac.toString()); @@ -1138,7 +1134,7 @@ TEST(TestIRFujitsuACClass, Heat10Deg) { ac.set10CHeat(true); EXPECT_TRUE(ac.get10CHeat()); EXPECT_EQ( - "Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 21C, " + "Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 10C, " "Fan: 0 (Auto), 10C Heat: On, Swing: 0 (Off), Command: N/A, " "Outside Quiet: Off, Timer: Off", ac.toString()); @@ -1361,3 +1357,92 @@ TEST(TestIRFujitsuACClass, Discussion1701) { EXPECT_EQ(expected_raw_output, ac._irsend.outputStr()); // Success. } + +TEST(TestIRFujitsuACClass, toCommon_Issue1780HandlePrev) { + IRFujitsuAC ac(kGpioUnused); + ac.setMode(kFujitsuAcModeCool); + ac.setTemp(20); + ac.setFanSpeed(kFujitsuAcFanQuiet); + ac.setSwing(kFujitsuAcSwingBoth); + ac.on(); + ASSERT_TRUE(ac.toCommon().power); + stdAc::state_t prev = ac.toCommon(); // Copy in the state. + ac.off(); + ASSERT_FALSE(ac.toCommon().power); + ac.send(); // This should send a short code. + prev.degrees = 27; + ac.stateReset(); + IRrecv irrecv(kGpioUnused); + 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); + 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_EQ(27, ac.toCommon(&prev).degrees); + ASSERT_FALSE(ac.toCommon().quiet); + + ASSERT_EQ(stdAc::opmode_t::kAuto, ac.toCommon().mode); + ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon(&prev).mode); + ASSERT_EQ(stdAc::fanspeed_t::kAuto, ac.toCommon().fanspeed); + ASSERT_EQ(stdAc::fanspeed_t::kMin, ac.toCommon(&prev).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); + + stdAc::state_t result_inc_prev; + ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &result_inc_prev, + &prev)); + ASSERT_EQ(27, result_inc_prev.degrees); + ASSERT_EQ(stdAc::opmode_t::kCool, result_inc_prev.mode); + ASSERT_EQ(stdAc::fanspeed_t::kMin, result_inc_prev.fanspeed); +} + +TEST(TestIRFujitsuACClass, Improve10CHeat) { + IRFujitsuAC ac(kGpioUnused); + // Data from https://docs.google.com/spreadsheets/d/1RdmJdOZ3zxYlLXzluKTp4L6VVdjDXKgizwwIyTTG8MA/edit#gid=0&range=G2 + const uint8_t Arrah2u_10CHeatOn[16] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x41, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x20, 0x64}; + ASSERT_FALSE(ac.get10CHeat()); + ac.setRaw(Arrah2u_10CHeatOn, 16); + ASSERT_TRUE(ac.get10CHeat()); + ASSERT_EQ( + "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 10C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: On, Swing: 0 (Off), " + "Command: N/A, Timer: Off", + ac.toString()); + EXPECT_EQ(decode_type_t::FUJITSU_AC, ac.toCommon().protocol); + ASSERT_TRUE(ac.get10CHeat()); + EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.toCommon().model); + EXPECT_EQ(kFujitsuAcMinHeat, ac.toCommon().degrees); + + ac.stateReset(); + // Data from https://docs.google.com/spreadsheets/d/1RdmJdOZ3zxYlLXzluKTp4L6VVdjDXKgizwwIyTTG8MA/edit#gid=0&range=G8 + const uint8_t Arreg1u_10CHeatOn[16] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x61, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x20, 0x44}; + ASSERT_FALSE(ac.get10CHeat()); + ac.setRaw(Arreg1u_10CHeatOn, 16); + ASSERT_TRUE(ac.get10CHeat()); + ASSERT_EQ( + "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 10C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: On, Swing: 0 (Off), " + "Command: N/A, Timer: Off", + ac.toString()); + EXPECT_EQ(decode_type_t::FUJITSU_AC, ac.toCommon().protocol); + ASSERT_TRUE(ac.get10CHeat()); + EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.toCommon().model); + EXPECT_EQ(kFujitsuAcMinHeat, ac.toCommon().degrees); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Gree_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Gree_test.cpp index cb1832f61..e0160577e 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Gree_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Gree_test.cpp @@ -326,6 +326,9 @@ TEST(TestGreeClass, OperatingMode) { ac.setMode(kGreeHeat); EXPECT_EQ(kGreeHeat, ac.getMode()); + ac.setMode(kGreeEcono); + EXPECT_EQ(kGreeEcono, ac.getMode()); + ASSERT_NE(kGreeFanMax, 1); ac.setFan(kGreeFanMax); ac.setMode(kGreeDry); // Dry should lock the fan to speed 1. @@ -337,7 +340,7 @@ TEST(TestGreeClass, OperatingMode) { ac.setMode(kGreeFan); EXPECT_EQ(kGreeFan, ac.getMode()); - ac.setMode(kGreeHeat + 1); + ac.setMode(kGreeEcono + 1); EXPECT_EQ(kGreeAuto, ac.getMode()); ac.setMode(255); @@ -798,3 +801,40 @@ TEST(TestGreeClass, DisplayTempSource) { ac.setRaw(state); EXPECT_EQ(2, ac.getDisplayTempSource()); } + +TEST(TestUtils, Housekeeping) { + ASSERT_EQ("GREE", typeToString(decode_type_t::GREE)); + ASSERT_EQ(decode_type_t::GREE, strToDecodeType("GREE")); + ASSERT_TRUE(hasACState(decode_type_t::GREE)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::GREE)); + ASSERT_EQ(kGreeBits, IRsend::defaultBits(decode_type_t::GREE)); + ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::GREE)); + ASSERT_EQ(gree_ac_remote_model_t::YAW1F, IRac::strToModel("YAW1F")); + ASSERT_EQ(irutils::modelToStr(decode_type_t::GREE, + gree_ac_remote_model_t::YAW1F), "YAW1F"); + ASSERT_EQ(gree_ac_remote_model_t::YBOFB, IRac::strToModel("YBOFB")); + ASSERT_EQ(irutils::modelToStr(decode_type_t::GREE, + gree_ac_remote_model_t::YBOFB), "YBOFB"); + ASSERT_EQ(gree_ac_remote_model_t::YX1FSF, IRac::strToModel("YX1FSF")); + ASSERT_EQ(irutils::modelToStr(decode_type_t::GREE, + gree_ac_remote_model_t::YX1FSF), "YX1FSF"); +} + +TEST(TestGreeClass, Issue1821EnergySaver) { + IRGreeAC ac(kGpioUnused); + ac.begin(); + + // https://github.com/crankyoldgit/IRremoteESP8266/issues/1821#issue-1271458457 + const uint8_t energy[8] = {0x1D, 0x09, 0x60, 0x58, 0x00, 0x20, 0x00, 0xA0}; + + ac.setRaw(energy); + EXPECT_EQ(kGreeEcono, ac.getMode()); + EXPECT_TRUE(ac.getEcono()); + EXPECT_EQ(gree_ac_remote_model_t::YX1FSF, ac.getModel()); + EXPECT_EQ( + "Model: 3 (YX1FSF), Power: On, Mode: 5 (Econo), Temp: 77F, Fan: 1 (Low), " + "Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, " + "Sleep: Off, Swing(V) Mode: Manual, Swing(V): 0 (Last), " + "Swing(H): 0 (Off), Timer: Off, Display Temp: 0 (Off)", + ac.toString()); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Haier_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Haier_test.cpp index b60a08f23..5f2b9a92d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Haier_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Haier_test.cpp @@ -1357,6 +1357,13 @@ TEST(TestUtils, Housekeeping) { ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::HAIER_AC176)); ASSERT_EQ(kHaierAC176Bits, IRsend::defaultBits(decode_type_t::HAIER_AC176)); ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::HAIER_AC176)); + + ASSERT_EQ("HAIER_AC160", typeToString(decode_type_t::HAIER_AC160)); + ASSERT_EQ(decode_type_t::HAIER_AC160, strToDecodeType("HAIER_AC160")); + ASSERT_TRUE(hasACState(decode_type_t::HAIER_AC160)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::HAIER_AC160)); + ASSERT_EQ(kHaierAC160Bits, IRsend::defaultBits(decode_type_t::HAIER_AC160)); + ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::HAIER_AC160)); } TEST(TestHaierAC176Class, BuildKnownState) { @@ -1535,3 +1542,492 @@ TEST(TestHaierAC176Class, Models) { "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", ac.toString()); } + +TEST(TestDecodeHaierAC160, RealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + irsend.reset(); + // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1804#issue-1236115063 + const uint16_t rawData[325] = { + 3078, 3002, + 3058, 4338, + 590, 1612, 588, 516, 584, 1588, 586, 542, 560, 540, 560, 1590, 584, 1618, + 584, 542, 558, 1592, 584, 542, 582, 1594, 584, 542, 582, 1592, 560, 1642, + 560, 516, 558, 544, 558, 542, 558, 542, 582, 518, 558, 542, 558, 516, 558, + 542, 558, 542, 582, 520, 558, 542, 558, 542, 564, 510, 608, 492, 558, 542, + 582, 520, 558, 542, 558, 544, 582, 492, 608, 1594, 558, 544, 558, 542, + 582, 494, 608, 494, 558, 544, 558, 542, 558, 544, 558, 1616, 582, 1620, + 560, 542, 558, 542, 582, 494, 558, 542, 558, 542, 558, 544, 556, 542, 582, + 520, 580, 494, 582, 520, 582, 520, 558, 542, 558, 542, 582, 520, 582, 492, + 608, 1592, 582, 520, 558, 544, 558, 516, 584, 518, 558, 542, 582, 520, + 580, 520, 582, 520, 580, 492, 584, 516, 556, 544, 582, 518, 580, 520, 580, + 520, 580, 494, 606, 494, 580, 520, 580, 520, 582, 520, 580, 520, 556, 518, + 608, 492, 580, 520, 556, 544, 580, 520, 580, 520, 580, 494, 606, 494, 580, + 520, 580, 520, 580, 520, 580, 520, 580, 494, 606, 496, 578, 522, 580, 520, + 580, 520, 580, 520, 580, 494, 606, 494, 580, 520, 580, 520, 580, 1594, + 608, 494, 580, 1620, 580, 522, 580, 520, 580, 494, 578, 1620, 582, 520, + 580, 1596, 582, 1620, 582, 1594, 608, 1594, 582, 522, 580, 1594, 582, + 1620, 582, 520, 580, 1596, 582, 520, 580, 1620, 582, 494, 606, 496, 580, + 522, 580, 522, 580, 520, 580, 520, 580, 496, 604, 496, 580, 520, 580, + 1620, 582, 1594, 582, 522, 578, 522, 580, 522, 578, 522, 580, 496, 580, + 522, 578, 522, 578, 522, 578, 524, 578, 522, 578, 496, 578, 522, 578, 522, + 578, 546, 554, 522, 578, 522, 578, 520, 556, 546, 554, 546, 554, 546, 556, + 544, 556, 546, 554, 520, 554, 544, 556, 1620, 582, 544, 556, 1594, 580, + 546, 556, 1594, 580}; // UNKNOWN B6B57D85 + const uint8_t expectedState[kHaierAC160StateLength] = { + 0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x17, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15}; + + irsend.sendRaw(rawData, 325, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC160, irsend.capture.decode_type); + ASSERT_EQ(kHaierAC160Bits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 26C, Fan: 3 (Low), " + "Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), Sleep: Off, " + "Clean: Off, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off, " + "Heating: Off", + IRAcUtils::resultAcToString(&irsend.capture)); + stdAc::state_t result, prev; + ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeHaierAC160, SyntheticExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + const uint8_t expectedState[kHaierAC160StateLength] = { + 0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x17, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15}; + + irsend.reset(); + irsend.sendHaierAC160(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC160, irsend.capture.decode_type); + ASSERT_EQ(kHaierAC160Bits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 26C, Fan: 3 (Low), " + "Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), Sleep: Off, " + "Clean: Off, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off, " + "Heating: Off", + IRAcUtils::resultAcToString(&irsend.capture)); + stdAc::state_t result, prev; + ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); +} + +// Tests for the IRHaierAC160 class. + +TEST(TestHaierAC160Class, Button) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setButton(kHaierAcYrw02ButtonPower); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonMode); + EXPECT_EQ(kHaierAcYrw02ButtonMode, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonSleep); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonFan); + + // Test unexpected values. + ac.setButton(0xFF); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); + ac.setButton(0x10); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); +} + +TEST(TestHaierAC160Class, OperatingMode) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setMode(kHaierAcYrw02Auto); + EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode()); + EXPECT_EQ(kHaierAcYrw02ButtonMode, ac.getButton()); + + ac.setMode(kHaierAcYrw02Cool); + EXPECT_EQ(kHaierAcYrw02Cool, ac.getMode()); + EXPECT_FALSE(ac.getAuxHeating()); + + ac.setMode(kHaierAcYrw02Heat); + EXPECT_EQ(kHaierAcYrw02Heat, ac.getMode()); + EXPECT_TRUE(ac.getAuxHeating()); + + ac.setMode(kHaierAcYrw02Fan); + EXPECT_EQ(kHaierAcYrw02Fan, ac.getMode()); + EXPECT_FALSE(ac.getAuxHeating()); + + ac.setMode(kHaierAcYrw02Dry); + EXPECT_EQ(kHaierAcYrw02Dry, ac.getMode()); + + ac.setMode(kHaierAcYrw02Auto - 1); + EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode()); + + ac.setMode(kHaierAcYrw02Cool); + EXPECT_EQ(kHaierAcYrw02Cool, ac.getMode()); + + ac.setMode(kHaierAcYrw02Fan + 1); + EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode()); +} + +TEST(TestHaierAC160Class, Temperature) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setTemp(kHaierAcYrw02MinTempC); + EXPECT_EQ(kHaierAcYrw02MinTempC, ac.getTemp()); + + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setTemp(kHaierAcYrw02MinTempC + 1); + EXPECT_EQ(kHaierAcYrw02MinTempC + 1, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MaxTempC); + EXPECT_EQ(kHaierAcYrw02MaxTempC, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MinTempC - 1); + EXPECT_EQ(kHaierAcYrw02MinTempC, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MaxTempC + 1); + EXPECT_EQ(kHaierAcYrw02MaxTempC, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); + + ac.setTemp(23); + EXPECT_EQ(23, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setTemp(23); + EXPECT_EQ(23, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MinTempF, true); + EXPECT_EQ(kHaierAcYrw02MinTempF, ac.getTemp()); + + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setTemp(kHaierAcYrw02MinTempF + 1, true); + EXPECT_EQ(kHaierAcYrw02MinTempF + 1, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MaxTempF, true); + EXPECT_EQ(kHaierAcYrw02MaxTempF, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MinTempF - 1, true); + EXPECT_EQ(kHaierAcYrw02MinTempF, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MaxTempF + 1, true); + EXPECT_EQ(kHaierAcYrw02MaxTempF, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); + + ac.setTemp(66, true); + EXPECT_EQ(66, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setTemp(66, true); + EXPECT_EQ(66, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); + + // Test specific cases for converting to Fahrenheit + ac.setTemp(76, true); + EXPECT_EQ(76, ac.getTemp()); + ac.setTemp(77, true); + EXPECT_EQ(77, ac.getTemp()); + ac.setTemp(78, true); + EXPECT_EQ(78, ac.getTemp()); + + ac.setTemp(24); + EXPECT_EQ(kHaierAcYrw02ButtonCFAB, ac.getButton()); + + ac.setTemp(0); + EXPECT_EQ(kHaierAcYrw02MinTempC, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); + + ac.setTemp(255); + EXPECT_EQ(kHaierAcMaxTemp, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); +} + +TEST(TestHaierAC160Class, CleanMode) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setClean(true); + EXPECT_TRUE(ac.getClean()); + EXPECT_EQ(kHaierAc160ButtonClean, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setClean(false); + EXPECT_FALSE(ac.getClean()); + EXPECT_EQ(kHaierAc160ButtonClean, ac.getButton()); + + ac.setClean(true); + EXPECT_TRUE(ac.getClean()); + EXPECT_EQ(kHaierAc160ButtonClean, ac.getButton()); + + ac.stateReset(); + EXPECT_FALSE(ac.getClean()); + // clean button pressed. + // https://docs.google.com/spreadsheets/d/1RNJ7esbArS5fy1lmiM-i1PekXSNojCMad4WuuyunsC8/edit#gid=2048081808&range=FR22 + const uint8_t clean_on[kHaierAC160StateLength] = { + 0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00, + 0x10, 0x00, 0x19, 0x3B, 0xB5, 0x40, 0x60, 0x00, 0x00, 0x55}; + ac.setRaw(clean_on); + EXPECT_TRUE(ac.getClean()); + EXPECT_EQ( + "Power: On, Button: 25 (Clean), Mode: 1 (Cool), Temp: 26C, " + "Fan: 3 (Low), Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), " + "Sleep: Off, Clean: On, Timer Mode: 0 (N/A), " + "On Timer: Off, Off Timer: Off, Lock: Off, Heating: Off", + ac.toString()); + // No clean set. + // https://docs.google.com/spreadsheets/d/1RNJ7esbArS5fy1lmiM-i1PekXSNojCMad4WuuyunsC8/edit#gid=2048081808&range=FR4 + const uint8_t clean_off[kHaierAC160StateLength] = { + 0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x17, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15}; + ac.setRaw(clean_off); + EXPECT_FALSE(ac.getClean()); + EXPECT_EQ( + "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 26C, " + "Fan: 3 (Low), Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), " + "Sleep: Off, Clean: Off, Timer Mode: 0 (N/A), " + "On Timer: Off, Off Timer: Off, Lock: Off, Heating: Off", + ac.toString()); +} + +TEST(TestHaierAC160Class, Power) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + ac.on(); + EXPECT_TRUE(ac.getPower()); +} + +TEST(TestHaierAC160Class, SleepMode) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setSleep(false); + EXPECT_FALSE(ac.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton()); + + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton()); +} + +TEST(TestHaierAC160Class, Health) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setHealth(true); + EXPECT_TRUE(ac.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setHealth(false); + EXPECT_FALSE(ac.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, ac.getButton()); + + ac.setHealth(true); + EXPECT_TRUE(ac.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, ac.getButton()); +} + +TEST(TestHaierAC160Class, TurboAndQuiet) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setMode(kHaierAcYrw02Cool); // Turbo & Quiet is allowed in this mode. + ac.setTurbo(false); + ac.setQuiet(false); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_FALSE(ac.getQuiet()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + EXPECT_FALSE(ac.getQuiet()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton()); + + ac.setQuiet(true); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_TRUE(ac.getQuiet()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton()); + + ac.setTurbo(false); + ac.setQuiet(false); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_FALSE(ac.getQuiet()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton()); + + ac.setMode(kHaierAcYrw02Auto); // Turbo & Quiet is not allowed in this mode. + EXPECT_FALSE(ac.getTurbo()); + EXPECT_FALSE(ac.getQuiet()); + ac.setTurbo(true); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_NE(kHaierAcYrw02ButtonTurbo, ac.getButton()); + ac.setQuiet(true); + EXPECT_FALSE(ac.getQuiet()); + EXPECT_NE(kHaierAcYrw02ButtonTurbo, ac.getButton()); +} + +TEST(TestHaierAC160Class, Fan) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setFan(kHaierAcYrw02FanAuto); + EXPECT_EQ(kHaierAcYrw02FanAuto, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + + ac.setFan(kHaierAcYrw02FanLow); + EXPECT_EQ(kHaierAcYrw02FanLow, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); + + ac.setFan(kHaierAcYrw02FanHigh); + EXPECT_EQ(kHaierAcYrw02FanHigh, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); + + ac.setFan(kHaierAcYrw02FanMed); + EXPECT_EQ(kHaierAcYrw02FanMed, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); + + // Test unexpected values. + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setFan(0x00); + EXPECT_EQ(kHaierAcYrw02FanMed, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); +} + +TEST(TestHaierAC160Class, SwingV) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setSwingV(kHaierAc160SwingVOff); + EXPECT_EQ(kHaierAc160SwingVOff, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + + ac.setSwingV(kHaierAc160SwingVAuto); + EXPECT_EQ(kHaierAc160SwingVAuto, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton()); + + ac.setSwingV(kHaierAc160SwingVTop); + EXPECT_EQ(kHaierAc160SwingVTop, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton()); + + ac.setSwingV(kHaierAc160SwingVLow); + EXPECT_EQ(kHaierAc160SwingVLow, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton()); + + // Test unexpected values. + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setSwingV(0xFF); + EXPECT_EQ(kHaierAc160SwingVLow, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); +} + +TEST(TestHaierAC160Class, Light) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setLightToggle(true); + EXPECT_TRUE(ac.getLightToggle()); + EXPECT_EQ(kHaierAc160ButtonLight, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setLightToggle(false); + EXPECT_FALSE(ac.getLightToggle()); + EXPECT_NE(kHaierAc160ButtonLight, ac.getButton()); + + ac.setLightToggle(true); + EXPECT_TRUE(ac.getLightToggle()); + EXPECT_EQ(kHaierAc160ButtonLight, ac.getButton()); + + const uint8_t light_press[kHaierAC160StateLength] = { + 0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x15, 0x27, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15}; + ac.setRaw(light_press); + EXPECT_TRUE(ac.getLightToggle()); + EXPECT_EQ(kHaierAc160ButtonLight, ac.getButton()); + EXPECT_EQ( + "Power: On, Button: 21 (Light), Mode: 1 (Cool), Temp: 26C, " + "Fan: 3 (Low), Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), " + "Sleep: Off, Clean: Off, Timer Mode: 0 (N/A), " + "On Timer: Off, Off Timer: Off, Lock: Off, Heating: Off", + ac.toString()); +} + +TEST(TestHaierAC160Class, AuxHeating) { + IRHaierAC160 ac(kGpioUnused); + ac.begin(); + + ac.setAuxHeating(true); + EXPECT_TRUE(ac.getAuxHeating()); + EXPECT_EQ(kHaierAc160ButtonAuxHeating, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setAuxHeating(false); + EXPECT_FALSE(ac.getAuxHeating()); + EXPECT_EQ(kHaierAc160ButtonAuxHeating, ac.getButton()); + + ac.setAuxHeating(true); + EXPECT_TRUE(ac.getAuxHeating()); + EXPECT_EQ(kHaierAc160ButtonAuxHeating, ac.getButton()); + + // https://docs.google.com/spreadsheets/d/1RNJ7esbArS5fy1lmiM-i1PekXSNojCMad4WuuyunsC8/edit#gid=2048081808&range=A124:W143 + const uint8_t aux_button_off[kHaierAC160StateLength] = { + 0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x16, 0x88, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15}; + ac.setRaw(aux_button_off); + EXPECT_FALSE(ac.getAuxHeating()); + EXPECT_EQ(kHaierAc160ButtonAuxHeating, ac.getButton()); + EXPECT_EQ( + "Power: On, Button: 22 (Heating), Mode: 4 (Heat), Temp: 26C, " + "Fan: 3 (Low), Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), " + "Sleep: Off, Clean: Off, Timer Mode: 0 (N/A), " + "On Timer: Off, Off Timer: Off, Lock: Off, Heating: Off", + ac.toString()); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Sanyo_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Sanyo_test.cpp index 6378e7679..bcfaef972 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Sanyo_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Sanyo_test.cpp @@ -284,6 +284,14 @@ TEST(TestUtils, Housekeeping) { ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::SANYO_AC88)); ASSERT_EQ(kSanyoAc88Bits, IRsend::defaultBits(decode_type_t::SANYO_AC88)); ASSERT_EQ(kSanyoAc88MinRepeat, IRsend::minRepeats(decode_type_t::SANYO_AC88)); + // Sanyo A/C 152 Bit. + ASSERT_EQ("SANYO_AC152", typeToString(decode_type_t::SANYO_AC152)); + ASSERT_EQ(decode_type_t::SANYO_AC152, strToDecodeType("SANYO_AC152")); + ASSERT_TRUE(hasACState(decode_type_t::SANYO_AC152)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::SANYO_AC152)); + ASSERT_EQ(kSanyoAc152Bits, IRsend::defaultBits(decode_type_t::SANYO_AC152)); + ASSERT_EQ(kSanyoAc152MinRepeat, + IRsend::minRepeats(decode_type_t::SANYO_AC152)); } TEST(TestDecodeSanyoAc, DecodeRealExamples) { @@ -820,3 +828,70 @@ TEST(TestSanyoAc88Class, Clock) { ac.setClock(25 * 60 + 61); EXPECT_EQ(23 * 60 + 59, ac.getClock()); } + +TEST(TestDecodeSanyoAc152, DecodeRealExamples) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + // Ref: "16c" from https://github.com/crankyoldgit/IRremoteESP8266/issues/1826#issuecomment-1160708653 + const uint16_t rawData[307] = { + 3294, 1726, 420, 330, 458, 462, 382, 452, 438, 330, 456, 458, 384, 454, + 384, 1312, 422, 324, 512, 336, 454, 458, 384, 450, 438, 358, 436, 464, + 424, 326, 458, 476, 372, 458, 430, 328, 458, 464, 382, 1308, 424, 326, + 510, 1264, 424, 268, 520, 460, 380, 460, 436, 324, 462, 400, 436, 474, + 372, 456, 430, 342, 452, 450, 388, 446, 442, 1262, 422, 266, 520, 1314, + 372, 1306, 424, 1258, 370, 390, 448, 1314, 372, 1310, 426, 308, 522, 338, + 454, 470, 370, 454, 438, 330, 456, 468, 370, 456, 384, 464, 384, 1306, + 422, 328, 460, 472, 374, 448, 442, 1258, 426, 1256, 426, 268, 520, 464, + 382, 460, 430, 328, 508, 1264, 426, 262, 572, 1262, 424, 228, 604, 1262, + 372, 1312, 372, 1310, 426, 1256, 422, 1258, 424, 262, 524, 418, 428, 456, + 382, 1308, 372, 456, 386, 456, 382, 464, 378, 1308, 424, 360, 436, 454, + 430, 344, 450, 1306, 372, 1310, 424, 326, 510, 338, 452, 456, 384, 456, + 436, 328, 510, 1258, 372, 1310, 422, 338, 454, 466, 424, 328, 460, 1310, + 372, 1312, 424, 1258, 450, 262, 496, 1310, 372, 1310, 426, 1260, 424, 260, + 526, 442, 442, 1264, 426, 268, 520, 458, 380, 450, 386, 462, 436, 320, + 518, 1256, 372, 394, 446, 398, 494, 334, 506, 326, 510, 276, 518, 460, + 430, 332, 508, 326, 510, 356, 440, 448, 444, 264, 572, 336, 456, 408, 434, + 454, 438, 332, 506, 336, 454, 460, 384, 448, 444, 326, 510, 332, 456, 442, + 400, 456, 384, 456, 386, 452, 388, 454, 440, 326, 512, 272, 518, 450, 440, + 334, 454, 458, 440, 320, 516, 268, 570, 340, 452, 468, 424, 260, 574, 336, + 456, 394, 444, 458, 438, 328, 508, 1258, 370, 1312, 372, 1312, 424, 314, + 468, 1312, 450, 1232, 370, 1314, 420, 324, 514}; // UNKNOWN 584FBE80 + + const uint8_t expectedState[kSanyoAc152StateLength] = { + 0x40, 0x00, 0x14, 0x80, 0x6E, 0x80, 0x18, 0xEA, 0x23, 0x62, + 0x30, 0xEE, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData, 307, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SANYO_AC152, irsend.capture.decode_type); + EXPECT_EQ(kSanyoAc152Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); +} + +TEST(TestDecodeSanyoAc152, SyntheticSelfDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + const uint8_t expectedState[kSanyoAc152StateLength] = { + 0x40, 0x00, 0x14, 0x80, 0x6E, 0x80, 0x18, 0xEA, 0x23, 0x62, + 0x30, 0xEE, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77}; + irsend.begin(); + irsend.reset(); + irsend.sendSanyoAc152(expectedState); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SANYO_AC152, irsend.capture.decode_type); + EXPECT_EQ(kSanyoAc152Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Tcl_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Tcl_test.cpp index b7ab5301f..f1a4cf393 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Tcl_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Tcl_test.cpp @@ -1,4 +1,4 @@ -// Copyright 2019 David Conran +// Copyright 2019-2022 David Conran #include "ir_Tcl.h" #include "IRac.h" @@ -22,6 +22,13 @@ TEST(TestTcl112Ac, Housekeeping) { ASSERT_EQ(tcl_ac_remote_model_t::GZ055BE1, IRac::strToModel("GZ055BE1")); ASSERT_EQ(irutils::modelToStr(decode_type_t::TCL112AC, tcl_ac_remote_model_t::GZ055BE1), "GZ055BE1"); + + ASSERT_EQ("TCL96AC", typeToString(decode_type_t::TCL96AC)); + ASSERT_EQ(decode_type_t::TCL96AC, strToDecodeType("TCL96AC")); + ASSERT_TRUE(hasACState(decode_type_t::TCL96AC)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::TCL96AC)); + ASSERT_EQ(kTcl96AcBits, IRsend::defaultBits(decode_type_t::TCL96AC)); + ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::TCL96AC)); } // Tests for decodeTcl112Ac(). @@ -703,3 +710,64 @@ TEST(TestTcl112AcClass, Timers) { "On Timer: Off, Off Timer: 02:00", ac.toString()); } + +// Decode a real Tcl96Ac A/C example from Issue #619 +TEST(TestDecodeTcl96Ac, DecodeRealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + irsend.reset(); + // Tcl96Ac A/C example from Issue #1810 row_data.txt + const uint16_t rawData[99] = { + 1056, 550, + 608, 2182, 608, 1444, 606, 840, 608, 2182, + 608, 360, 612, 2182, 608, 356, 616, 1446, + 608, 354, 618, 366, 608, 366, 606, 356, + 618, 356, 618, 838, 608, 364, 608, 364, + 608, 2182, 608, 360, 612, 840, 608, 838, + 610, 364, 608, 360, 612, 2182, 608, 838, + 608, 838, 608, 2182, 608, 366, 606, 1444, + 608, 358, 614, 1444, 608, 838, 608, 366, + 606, 368, 606, 366, 606, 366, 606, 366, + 608, 364, 608, 342, 632, 840, 606, 340, + 606, 364, 634, 338, 634, 340, 632, 340, + 634, 814, 632, 814, 632, 2156, 634, 2156, + 634}; // UNKNOWN AE10E0CB + + const uint8_t expectedState[kTcl96AcStateLength] = { + 0xB6, 0x23, 0x00, 0x10, 0x85, 0x09, 0x63, 0x34, 0x00, 0x04, 0x00, 0x5A}; + + irsend.sendRaw(rawData, 99, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TCL96AC, irsend.capture.decode_type); + EXPECT_EQ(kTcl96AcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); +} + +// Decode a synthetic Tcl96Ac A/C message +TEST(TestDecodeTcl96Ac, SyntheticExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + irsend.reset(); + + const uint8_t expectedState[kTcl96AcStateLength] = { + 0xB6, 0x23, 0x00, 0x10, 0x85, 0x09, 0x63, 0x34, 0x00, 0x04, 0x00, 0x5A}; + + irsend.sendTcl96Ac(expectedState); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TCL96AC, irsend.capture.decode_type); + EXPECT_EQ(kTcl96AcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Toto_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Toto_test.cpp new file mode 100644 index 000000000..050bd01e6 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Toto_test.cpp @@ -0,0 +1,159 @@ +// Copyright 2022 crankyoldgit (David Conran) + +#include "IRac.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" +#include "gtest/gtest.h" + + +// General housekeeping +TEST(TestToto, Housekeeping) { + ASSERT_EQ("TOTO", typeToString(TOTO)); + ASSERT_FALSE(hasACState(TOTO)); + ASSERT_EQ(kTotoBits, IRsend::defaultBits(decode_type_t::TOTO)); + ASSERT_EQ(kSingleRepeat, IRsend::minRepeats(decode_type_t::TOTO)); +} + +// Tests for decodeToto(). + +// Decode normal Toto messages. +TEST(TestDecodeToto, SyntheticShortDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + // Short Toto 24-bit message. + irsend.reset(); + irsend.sendToto(0x0D0D00); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(TOTO, irsend.capture.decode_type); + EXPECT_EQ(kTotoBits, irsend.capture.bits); + EXPECT_EQ(0x0D0D00, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0x0D00, irsend.capture.command); +} + +// Decode real example via Issue #1806 +TEST(TestDecodeToto, RealShortDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + irsend.reset(); + // Toto Full Flush from Issue #1806 + const uint16_t rawData[163] = { + 6266, 2734, + 598, 540, 598, 1626, 598, 512, 622, 516, 598, 514, 598, 510, 598, 514, + 628, 512, 596, 514, 600, 512, 598, 538, 600, 1622, 600, 512, 598, 540, + 602, 510, 598, 512, 598, 512, 624, 514, 598, 512, 598, 512, 598, 514, + 624, 512, 598, 514, 598, 1652, 596, 514, 598, 1626, 598, 1650, 598, 514, + 598, 512, 598, 540, 598, 514, 596, 1626, 626, 512, 574, 1648, 598, 1650, + 598, 514, 598, 512, 594, 544, 596, 514, + 598, 37996, + 6182, 2764, + 598, 514, 600, 1648, 600, 512, 596, 514, 598, 540, 598, 512, 600, 512, + 598, 512, 624, 514, 598, 514, 598, 512, 596, 1652, 598, 514, 598, 512, + 596, 540, 598, 514, 598, 512, 598, 512, 598, 540, 596, 516, 596, 514, 598, + 512, 574, 564, 598, 1626, 568, 542, 624, 1624, 626, 1622, 598, 514, 596, + 514, 598, 514, 596, 540, 600, 1622, 598, 512, 600, 1650, 598, 1624, 596, + 540, 600, 512, 598, 514, 596, 514, + 622}; // UNKNOWN 43BD67B3 + + irsend.sendRaw(rawData, 163, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(TOTO, irsend.capture.decode_type); + EXPECT_EQ(kTotoBits, irsend.capture.bits); + EXPECT_EQ(0x0D0D00, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0x0D00, irsend.capture.command); +} + +// Decode real example via Issue #1806 +TEST(TestDecodeToto, RealLongDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + irsend.reset(); + // Oscillate Bidet Function from Issue #1806 + const uint16_t rawData[491] = { + 6262, 2738, + 600, 538, 596, 1624, 598, 512, 652, 486, 628, 484, 600, 510, 596, 516, + 650, 488, 622, 488, 626, 484, 598, 540, 600, 1624, 602, 510, 596, 540, + 602, 510, 598, 514, 598, 512, 626, 512, 598, 512, 598, 512, 598, 514, + 626, 510, 598, 514, 598, 512, 598, 1650, 600, 1622, 600, 538, 596, 514, + 600, 510, 596, 514, 596, 542, 598, 514, 598, 1624, 626, 1622, 598, 512, + 600, 512, 620, 516, 598, 512, 598, 514, + 598, 40244, + 6184, 2764, + 598, 514, 598, 1650, 598, 514, 596, 516, 596, 542, 598, 512, 596, 516, + 600, 510, 624, 512, 598, 512, 596, 516, 598, 1652, 600, 512, 598, 512, + 598, 540, 596, 518, 594, 514, 598, 512, 596, 542, 598, 512, 596, 514, + 598, 512, 598, 540, 598, 514, 598, 1622, 624, 1626, 598, 514, 598, 512, + 626, 512, 596, 514, 596, 514, 596, 540, 598, 1624, 600, 1650, 600, 512, + 600, 510, 598, 512, 596, 540, 598, 512, + 600, 40244, + 6186, 2760, + 600, 512, 596, 1626, 624, 514, 598, 512, 600, 512, 598, 512, 626, 512, + 598, 512, 598, 512, 596, 540, 600, 510, 600, 1622, 600, 538, 596, 514, + 596, 514, 598, 514, 624, 514, 596, 516, 596, 514, 600, 512, 622, 514, 600, + 512, 600, 510, 600, 538, 602, 1622, 600, 1648, 626, 512, 572, 512, 598, + 514, 650, 488, 598, 512, 594, 516, 598, 1652, 598, 1626, 598, 514, 624, + 514, 596, 512, 600, 512, 598, 540, + 596, 40246, + 6184, 2736, + 598, 538, 598, 1624, 598, 512, 598, 540, 598, 512, 600, 512, 596, 514, + 600, 538, 626, 486, 598, 514, 596, 514, 652, 1596, 594, 516, 624, 514, + 594, 516, 598, 514, 622, 490, 596, 540, 596, 514, 624, 488, 594, 514, 598, + 538, 598, 512, 598, 514, 594, 516, 596, 540, 600, 1622, 572, 566, 600, + 512, 570, 542, 598, 512, 598, 540, 600, 512, 594, 516, 598, 1652, 600, + 512, 598, 514, 596, 514, 624, 514, + 598, 42468, + 6182, 2764, + 624, 490, 594, 1652, 600, 512, 596, 514, 596, 540, 600, 512, 598, 516, + 596, 514, 598, 538, 598, 516, 598, 512, 570, 1678, 596, 514, 596, 514, + 598, 512, 624, 512, 594, 516, 596, 514, 600, 510, 626, 512, 596, 516, + 594, 516, 598, 538, 598, 512, 596, 514, 596, 514, 596, 1652, 600, 514, + 594, 516, 622, 514, 600, 512, 598, 514, 596, 514, 624, 514, 596, 1626, + 598, 514, 622, 516, 594, 516, 598, 514, + 596, 42496, + 6184, 2764, + 596, 516, 598, 1624, 626, 512, 598, 512, 596, 516, 600, 512, 624, 514, + 598, 514, 594, 516, 596, 516, 620, 516, 600, 1624, 596, 540, 598, 514, + 600, 512, 596, 516, 596, 542, 594, 516, 598, 514, 594, 516, 624, 512, 598, + 512, 596, 514, 596, 514, 624, 514, 596, 516, 598, 1650, 594, 518, 596, + 514, 596, 516, 596, 542, 596, 514, 596, 516, 596, 514, 596, 1652, 598, + 514, 596, 514, 624, 514, 622, 488, 596}; // UNKNOWN 4AC5E8B3 + + + irsend.sendRaw(rawData, 491, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(TOTO, irsend.capture.decode_type); + EXPECT_EQ(kTotoLongBits, irsend.capture.bits); + EXPECT_EQ(0x60600080800, irsend.capture.value); + EXPECT_EQ(0x0600, irsend.capture.address); + EXPECT_EQ(0x0800, irsend.capture.command); +} + +TEST(TestDecodeToto, SyntheticLongDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + // Long Toto 48-bit message. + irsend.reset(); + irsend.sendToto(0x60600080800, kTotoLongBits); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(TOTO, irsend.capture.decode_type); + EXPECT_EQ(kTotoLongBits, irsend.capture.bits); + EXPECT_EQ(0x60600080800, irsend.capture.value); + EXPECT_EQ(0x0600, irsend.capture.address); + EXPECT_EQ(0x0800, irsend.capture.command); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/auto_analyse_raw_data.py b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/auto_analyse_raw_data.py index e061d3c42..69149215d 100755 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/auto_analyse_raw_data.py +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/auto_analyse_raw_data.py @@ -100,7 +100,6 @@ class RawIRMessage(): def add_data_code(self, bin_str, name="", footer=True): """Add the common "data" sequence of code to send the bulk of a message.""" - # pylint: disable=no-self-use code = [] nbits = len(bin_str) code.append(f" // Data Section #{self.section_count}") @@ -115,7 +114,6 @@ class RawIRMessage(): def add_data_decode_code(self, bin_str, name="", footer=True): """Add the common "data" sequence code to decode the bulk of a message.""" - # pylint: disable=no-self-use code = [] nbits = len(bin_str) code.extend([ @@ -139,7 +137,6 @@ class RawIRMessage(): def add_data_byte_code(self, bin_str, name="", ambles=None): """Add the code to send the data from an array.""" - # pylint: disable=no-self-use code = [] nbits = len(bin_str) nbytes = nbits / 8 @@ -173,7 +170,6 @@ class RawIRMessage(): def add_data_byte_decode_code(self, bin_str, name="", ambles=None): """Add the common byte-wise "data" sequence decode code.""" - # pylint: disable=no-self-use code = [] nbits = len(bin_str) nbytes = nbits / 8 diff --git a/lib/lib_basic/IRremoteESP8266/library.json b/lib/lib_basic/IRremoteESP8266/library.json index 1dc044dc3..e221e7cf1 100644 --- a/lib/lib_basic/IRremoteESP8266/library.json +++ b/lib/lib_basic/IRremoteESP8266/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.8.2", + "version": "2.8.4", "keywords": "infrared, ir, remote, esp8266, esp32", "description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)", "repository": diff --git a/lib/lib_basic/TasmotaModbus-3.5.0/examples/modbustest/modbustest.ino b/lib/lib_basic/TasmotaModbus-3.6.0/examples/modbustest/modbustest.ino similarity index 100% rename from lib/lib_basic/TasmotaModbus-3.5.0/examples/modbustest/modbustest.ino rename to lib/lib_basic/TasmotaModbus-3.6.0/examples/modbustest/modbustest.ino diff --git a/lib/lib_basic/TasmotaModbus-3.5.0/keywords.txt b/lib/lib_basic/TasmotaModbus-3.6.0/keywords.txt similarity index 100% rename from lib/lib_basic/TasmotaModbus-3.5.0/keywords.txt rename to lib/lib_basic/TasmotaModbus-3.6.0/keywords.txt diff --git a/lib/lib_basic/TasmotaModbus-3.5.0/library.json b/lib/lib_basic/TasmotaModbus-3.6.0/library.json similarity index 93% rename from lib/lib_basic/TasmotaModbus-3.5.0/library.json rename to lib/lib_basic/TasmotaModbus-3.6.0/library.json index 717fcb75f..a8d88e550 100644 --- a/lib/lib_basic/TasmotaModbus-3.5.0/library.json +++ b/lib/lib_basic/TasmotaModbus-3.6.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaModbus", - "version": "3.5.0", + "version": "3.6.0", "keywords": [ "serial", "io", "TasmotaModbus" ], diff --git a/lib/lib_basic/TasmotaModbus-3.5.0/library.properties b/lib/lib_basic/TasmotaModbus-3.6.0/library.properties similarity index 93% rename from lib/lib_basic/TasmotaModbus-3.5.0/library.properties rename to lib/lib_basic/TasmotaModbus-3.6.0/library.properties index f6e583e03..feab66c7d 100644 --- a/lib/lib_basic/TasmotaModbus-3.5.0/library.properties +++ b/lib/lib_basic/TasmotaModbus-3.6.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaModbus -version=3.5.0 +version=3.6.0 author=Theo Arends maintainer=Theo Arends sentence=Basic modbus wrapper for TasmotaSerial for ESP8266. diff --git a/lib/lib_basic/TasmotaModbus-3.5.0/src/TasmotaModbus.cpp b/lib/lib_basic/TasmotaModbus-3.6.0/src/TasmotaModbus.cpp similarity index 64% rename from lib/lib_basic/TasmotaModbus-3.5.0/src/TasmotaModbus.cpp rename to lib/lib_basic/TasmotaModbus-3.6.0/src/TasmotaModbus.cpp index f543725a5..95db697f5 100644 --- a/lib/lib_basic/TasmotaModbus-3.5.0/src/TasmotaModbus.cpp +++ b/lib/lib_basic/TasmotaModbus-3.6.0/src/TasmotaModbus.cpp @@ -19,8 +19,14 @@ Documentation about modbus protocol: https://www.modbustools.com/modbus.html */ +#include "Arduino.h" #include "TasmotaModbus.h" +extern void AddLog(uint32_t loglevel, PGM_P formatP, ...); +enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; + +//#define TASMOTAMODBUSDEBUG + TasmotaModbus::TasmotaModbus(int receive_pin, int transmit_pin) : TasmotaSerial(receive_pin, transmit_pin, 1) { mb_address = 0; @@ -55,18 +61,21 @@ int TasmotaModbus::Begin(long speed, uint32_t config) return result; } -uint8_t TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t register_count, uint16_t *registers) +uint8_t TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t count, uint16_t *write_data) { uint8_t *frame; uint8_t framepointer = 0; + uint16_t byte_count = count * 2; // In register mode count is nr of registers (2 bytes) + if ((function_code == 1) || (function_code == 2) || (function_code == 15)) byte_count = ((count-1) / 8) + 1; // In bitmode count is nr of bits + if (function_code < 7) { frame = (uint8_t *)malloc(8); // Addres(1), Function(1), Start/Coil Address(2), Registercount or Data (2), CRC(2) } else { - frame = (uint8_t *)malloc(9 + (register_count * 2)); // Addres(1), Function(1), Start/Coil Address(2),Quantity of registers (2), Bytecount(1), Data(1..n), CRC(2) + frame = (uint8_t *)malloc(9 + byte_count); // Addres(1), Function(1), Start/Coil Address(2),Quantity of registers (2), Bytecount(1), Data(1..n), CRC(2) } mb_address = device_address; // Save address for receipt check @@ -77,43 +86,44 @@ uint8_t TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint1 frame[framepointer++] = (uint8_t)(start_address); // LSB if (function_code < 5) { - frame[framepointer++] = (uint8_t)(register_count >> 8); // MSB - frame[framepointer++] = (uint8_t)(register_count); // LSB + frame[framepointer++] = (uint8_t)(count >> 8); // MSB + frame[framepointer++] = (uint8_t)(count); // LSB } else if ((function_code == 5) || (function_code == 6)) { - if (registers == NULL) + if (write_data == NULL) { free(frame); return 13; // Register data not specified } - if (register_count != 1) + if (count != 1) { free(frame); return 12; // Wrong register count } - frame[framepointer++] = (uint8_t)(registers[0] >> 8); // MSB - frame[framepointer++] = (uint8_t)(registers[0]); // LSB + frame[framepointer++] = (uint8_t)(write_data[0] >> 8); // MSB + frame[framepointer++] = (uint8_t)(write_data[0]); // LSB } else if ((function_code == 15) || (function_code == 16)) { - frame[framepointer++] = (uint8_t)(register_count >> 8); // MSB - frame[framepointer++] = (uint8_t)(register_count); // LSB - frame[framepointer++] = register_count * 2; - if (registers == NULL) + frame[framepointer++] = (uint8_t)(count >> 8); // MSB + frame[framepointer++] = (uint8_t)(count); // LSB + + frame[framepointer++] = byte_count; + + if (write_data == NULL) { free(frame); return 13; // Register data not specified } - if (register_count == 0) + if (count == 0) { free(frame); return 12; // Wrong register count } - for (int registerpointer = 0; registerpointer < register_count; registerpointer++) + for (uint16_t bytepointer = 0; bytepointer < byte_count; bytepointer++) { - frame[framepointer++] = (uint8_t)(registers[registerpointer] >> 8); // MSB - frame[framepointer++] = (uint8_t)(registers[registerpointer]); // LSB + frame[framepointer++] = (uint8_t)(write_data[bytepointer/2] >> (bytepointer % 2 ? 0 : 8)); // MSB, LSB, MSB .... } } else @@ -126,6 +136,18 @@ uint8_t TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint1 frame[framepointer++] = (uint8_t)(crc); frame[framepointer++] = (uint8_t)(crc >> 8); +#ifdef TASMOTAMODBUSDEBUG + uint8_t *buf; + uint16_t bufsize=(framepointer + 1) * 3; + buf = (uint8_t *)malloc(bufsize); + memset(buf, 0, bufsize); + uint16_t i; + for (i = 0; i < framepointer;i++) + snprintf((char *)&buf[i*3], (bufsize-i*3), "%02X ",frame[i]); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MBS: Serial Send: %s"), buf); + free(buf); +#endif + flush(); write(frame, framepointer); free(frame); @@ -137,12 +159,13 @@ bool TasmotaModbus::ReceiveReady() return (available() > 4); } -uint8_t TasmotaModbus::ReceiveBuffer(uint8_t *buffer, uint8_t data_count) +uint8_t TasmotaModbus::ReceiveBuffer(uint8_t *buffer, uint8_t register_count, uint16_t byte_count) { mb_len = 0; uint32_t timeout = millis() + 10; uint8_t header_length = 3; - while ((mb_len < (data_count * 2) + header_length + 2) && (millis() < timeout)) { + if (byte_count == 0) byte_count = (register_count * 2); + while ((mb_len < byte_count + header_length + 2) && (millis() < timeout)) { if (available()) { uint8_t data = (uint8_t)read(); if (!mb_len) { // Skip leading data as provided by hardware serial @@ -152,20 +175,6 @@ uint8_t TasmotaModbus::ReceiveBuffer(uint8_t *buffer, uint8_t data_count) } else { buffer[mb_len++] = data; if (3 == mb_len) { - if (buffer[1] & 0x80) { // 01 84 02 f2 f1 - if (0 == buffer[2]) { - return 3; // 3 = Illegal Data Value, - } - return buffer[2]; // 1 = Illegal Function, - // 2 = Illegal Data Address, - // 3 = Illegal Data Value, - // 4 = Slave Error - // 5 = Acknowledge but not finished (no error) - // 6 = Slave Busy - // 8 = Memory Parity error - // 10 = Gateway Path Unavailable - // 11 = Gateway Target device failed to respond - } if ((buffer[1] == 5) || (buffer[1] == 6) || (buffer[1] == 15) || (buffer[1] == 16)) header_length = 4; // Addr, Func, StartAddr } } @@ -175,6 +184,36 @@ uint8_t TasmotaModbus::ReceiveBuffer(uint8_t *buffer, uint8_t data_count) } } +#ifdef TASMOTAMODBUSDEBUG +// RX Logging + uint8_t *buf; + uint16_t bufsize=(mb_len + 1) * 3; + buf = (uint8_t *)malloc(bufsize); + memset(buf, 0, bufsize); + uint16_t i; + for (i = 0; i < mb_len;i++) + snprintf((char *)&buf[i*3], (bufsize-i*3), "%02X ",buffer[i]); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MBS: Serial Received: %s"), buf); + free(buf); +#endif + + if (buffer[1] & 0x80) + { // 01 84 02 f2 f1 + if (0 == buffer[2]) + { + return 3; // 3 = Illegal Data Value, + } + return buffer[2]; // 1 = Illegal Function, + // 2 = Illegal Data Address, + // 3 = Illegal Data Value, + // 4 = Slave Error + // 5 = Acknowledge but not finished (no error) + // 6 = Slave Busy + // 8 = Memory Parity error + // 10 = Gateway Path Unavailable + // 11 = Gateway Target device failed to respond + } + if (mb_len < 6) { return 7; } // 7 = Not enough data /* diff --git a/lib/lib_basic/TasmotaModbus-3.5.0/src/TasmotaModbus.h b/lib/lib_basic/TasmotaModbus-3.6.0/src/TasmotaModbus.h similarity index 85% rename from lib/lib_basic/TasmotaModbus-3.5.0/src/TasmotaModbus.h rename to lib/lib_basic/TasmotaModbus-3.6.0/src/TasmotaModbus.h index f0122b9b0..520bb166d 100644 --- a/lib/lib_basic/TasmotaModbus-3.5.0/src/TasmotaModbus.h +++ b/lib/lib_basic/TasmotaModbus-3.6.0/src/TasmotaModbus.h @@ -53,8 +53,12 @@ class TasmotaModbus : public TasmotaSerial { * 13 = Register data not specified * 14 = To many registers */ - uint8_t Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t register_count, uint16_t *registers = NULL); - uint8_t ReceiveBuffer(uint8_t *buffer, uint8_t register_count); + uint8_t Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t count, uint16_t *writeData = NULL); + // Count is nr of registers for function code 3,4,6 and 16, nr of coils/inputs for function code 1,2 and 15 and must be 1 for function code 5 and 6 + + uint8_t ReceiveBuffer(uint8_t *buffer, uint8_t register_count, uint16_t byte_count = 0); + // Bytecount is mandatory for functioncode 1 and 2 because they can return an odd number of bytes. + uint8_t Receive8BitRegister(uint8_t *value); uint8_t Receive16BitRegister(uint16_t *value); uint8_t Receive32BitRegister(float *value); diff --git a/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp index aa5ab4bf3..2a5928ad3 100644 --- a/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp +++ b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp @@ -570,6 +570,13 @@ boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset, SSD1306_SETCONTRAST }; // 0x81 ssd1306_commandList(init4d, sizeof(init4d)); ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF); + } else if((WIDTH == 72) && (HEIGHT == 40)) { + static const uint8_t PROGMEM init4d[] = { + SSD1306_SETCOMPINS, // 0xDA + 0x12, + SSD1306_SETCONTRAST }; // 0x81 + ssd1306_commandList(init4d, sizeof(init4d)); + ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF); } else { // Other screen varieties -- TBD } @@ -931,6 +938,9 @@ void Adafruit_SSD1306::display(void) { if ((64 == WIDTH) && (48 == HEIGHT)) { // for 64x48, we need to shift by 32 in both directions col_start += 32; col_end += 32; + } else if ((72 == WIDTH) && (40 == HEIGHT)) { // for 72x40, we need to shift by 27 in both directions + col_start += 27; + col_end += 27; } TRANSACTION_START diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp index 1a752eb53..bcef703a6 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp @@ -639,6 +639,9 @@ void Renderer::ep_update_mode(uint8_t mode) { void Renderer::ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode) { } +uint32_t Renderer::get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym) { + return 0; +} // #ifndef USE_DISPLAY_LVGL_ONLY diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h index 74d812529..36196b962 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h @@ -90,6 +90,7 @@ public: virtual LVGL_PARAMS *lvgl_pars(void); virtual void ep_update_mode(uint8_t mode); virtual void ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode); + virtual uint32_t get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym); void setDrawMode(uint8_t mode); uint8_t drawmode; diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index 34b79e838..af5835e3f 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -24,7 +24,7 @@ #include "esp8266toEsp32.h" #endif -// #define UDSP_DEBUG +//#define UDSP_DEBUG const uint16_t udisp_colors[]={UDISP_BLACK,UDISP_WHITE,UDISP_RED,UDISP_GREEN,UDISP_BLUE,UDISP_CYAN,UDISP_MAGENTA,\ UDISP_YELLOW,UDISP_NAVY,UDISP_DARKGREEN,UDISP_DARKCYAN,UDISP_MAROON,UDISP_PURPLE,UDISP_OLIVE,\ @@ -51,6 +51,16 @@ uDisplay::~uDisplay(void) { if (framebuffer) { free(framebuffer); } +#ifdef USE_ESP32_S3 + if (_dmadesc) { + heap_caps_free(_dmadesc); + _dmadesc = nullptr; + _dmadesc_size = 0; + } + if (_i80_bus) { + esp_lcd_del_i80_bus(_i80_bus); + } +#endif // USE_ESP32_S3 } uDisplay::uDisplay(char *lp) : Renderer(800, 600) { @@ -163,6 +173,33 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { spi_miso = next_val(&lp1); spi_speed = next_val(&lp1); + section = 0; + } else if (!strncmp(ibuff, "PAR", 3)) { +#ifdef USE_ESP32_S3 + uint8_t bus = next_val(&lp1); + if (bus == 8) { + interface = _UDSP_PAR8; + } else { + interface = _UDSP_PAR16; + } + reset = next_val(&lp1); + par_cs = next_val(&lp1); + par_rs = next_val(&lp1); + par_wr = next_val(&lp1); + par_rd = next_val(&lp1); + bpanel = next_val(&lp1); + + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + par_dbl[cnt] = next_val(&lp1); + } + + if (interface == _UDSP_PAR16) { + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + par_dbh[cnt] = next_val(&lp1); + } + } + spi_speed = next_val(&lp1); +#endif // USE_ESP32_S3 section = 0; } break; @@ -331,7 +368,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { ep_mode = 1; } - if (lut_cnt[0]>0 && lut_cnt[1]==lut_cnt[2] && lut_cnt[1]==lut_cnt[3] && lut_cnt[1]==lut_cnt[4]) { + if (lut_cnt[0] > 0 && lut_cnt[1] == lut_cnt[2] && lut_cnt[1] == lut_cnt[3] && lut_cnt[1] == lut_cnt[4]) { // 5 table mode ep_mode = 2; } @@ -388,6 +425,30 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { Serial.printf("pa_end: %x\n", i2c_col_end); Serial.printf("WRA : %x\n", saw_3); } + + if (interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { +#ifdef USE_ESP32_S3 + Serial.printf("par mode: %d\n", interface); + Serial.printf("par res: %d\n", reset); + Serial.printf("par cs : %d\n", par_cs); + Serial.printf("par rs : %d\n", par_rs); + Serial.printf("par wr : %d\n", par_wr); + Serial.printf("par rd : %d\n", par_rd); + Serial.printf("par bp : %d\n", bpanel); + + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + Serial.printf("par d%d: %d\n", cnt, par_dbl[cnt]); + } + + if (interface == _UDSP_PAR16) { + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + Serial.printf("par d%d: %d\n", cnt + 8, par_dbh[cnt]); + } + } + Serial.printf("par freq : %d\n", spi_speed); +#endif // USE_ESP32_S3 + + } #endif } @@ -432,6 +493,7 @@ Renderer *uDisplay::Init(void) { } } + if (interface == _UDSP_SPI) { if (bpanel >= 0) { @@ -508,7 +570,7 @@ Renderer *uDisplay::Init(void) { SPI_CS_LOW iob = dsp_cmds[index++]; - spi_command(iob); + ulcd_command(iob); uint8_t args = dsp_cmds[index++]; #ifdef UDSP_DEBUG @@ -520,9 +582,9 @@ Renderer *uDisplay::Init(void) { Serial.printf("%02x ", iob ); #endif if (!allcmd_mode) { - spi_data8(iob); + ulcd_data8(iob); } else { - spi_command(iob); + ulcd_command(iob); } } SPI_CS_HIGH @@ -550,6 +612,148 @@ Renderer *uDisplay::Init(void) { } + if (interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { + +#ifdef USE_ESP32_S3 + + if (bpanel >= 0) { + analogWrite(bpanel, 32); + } + + pinMode(par_cs, OUTPUT); + digitalWrite(par_cs, HIGH); + + pinMode(par_rs, OUTPUT); + digitalWrite(par_rs, HIGH); + + pinMode(par_wr, OUTPUT); + digitalWrite(par_wr, HIGH); + + if (par_rd >= 0) { + pinMode(par_rd, OUTPUT); + digitalWrite(par_rd, HIGH); + } + + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + pinMode(par_dbl[cnt], OUTPUT); + } + + uint8_t bus_width = 8; + + if (interface == _UDSP_PAR16) { + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + pinMode(par_dbh[cnt], OUTPUT); + } + bus_width = 16; + } + + if (reset >= 0) { + pinMode(reset, OUTPUT); + digitalWrite(reset, HIGH); + delay(50); + digitalWrite(reset, LOW); + delay(50); + digitalWrite(reset, HIGH); + delay(200); + } + + esp_lcd_i80_bus_config_t bus_config = { + .dc_gpio_num = par_rs, + .wr_gpio_num = par_wr, + .bus_width = bus_width, + .max_transfer_bytes = 32768 + }; + + if (interface == _UDSP_PAR8) { + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + bus_config.data_gpio_nums[cnt] = par_dbl[cnt]; + } + } else { + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + bus_config.data_gpio_nums[cnt] = par_dbh[cnt]; + } + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + bus_config.data_gpio_nums[cnt + 8] = par_dbl[cnt]; + } + } + + // to disable SPI TRANSACTION + spi_nr = 3; + spi_cs = par_cs; + + _i80_bus = nullptr; + + esp_lcd_new_i80_bus(&bus_config, &_i80_bus); + + _dma_chan = _i80_bus->dma_chan; + + uint32_t div_a, div_b, div_n, clkcnt; + calcClockDiv(&div_a, &div_b, &div_n, &clkcnt, 240*1000*1000, spi_speed*1000000); + lcd_cam_lcd_clock_reg_t lcd_clock; + lcd_clock.lcd_clkcnt_n = std::max(1u, clkcnt - 1); + lcd_clock.lcd_clk_equ_sysclk = (clkcnt == 1); + lcd_clock.lcd_ck_idle_edge = true; + lcd_clock.lcd_ck_out_edge = false; + lcd_clock.lcd_clkm_div_num = div_n; + lcd_clock.lcd_clkm_div_b = div_b; + lcd_clock.lcd_clkm_div_a = div_a; + lcd_clock.lcd_clk_sel = 2; // clock_select: 1=XTAL CLOCK / 2=240MHz / 3=160MHz + lcd_clock.clk_en = true; + _clock_reg_value = lcd_clock.val; + + _alloc_dmadesc(1); + + _dev = &LCD_CAM; + + pb_beginTransaction(); + uint16_t index = 0; + while (1) { + uint8_t iob; + cs_control(0); + + iob = dsp_cmds[index++]; + pb_writeCommand(iob, 8); + + uint8_t args = dsp_cmds[index++]; + #ifdef UDSP_DEBUG + Serial.printf("cmd, args %02x, %d ", iob, args&0x1f); + #endif + for (uint32_t cnt = 0; cnt < (args & 0x1f); cnt++) { + iob = dsp_cmds[index++]; + #ifdef UDSP_DEBUG + Serial.printf("%02x ", iob ); + #endif + pb_writeData(iob, 8); + } + cs_control(1); + #ifdef UDSP_DEBUG + Serial.printf("\n"); + #endif + if (args & 0x80) { // delay after the command + uint32_t delay_ms = 0; + switch (args & 0xE0) { + case 0x80: delay_ms = 150; break; + case 0xA0: delay_ms = 10; break; + case 0xE0: delay_ms = 500; break; + } + if (delay_ms > 0) { + delay(delay_ms); + #ifdef UDSP_DEBUG + Serial.printf("delay %d ms\n", delay_ms); + #endif + } + + } + if (index >= dsp_ncmds) break; + } + + pb_endTransaction(); + + +#endif // USE_ESP32_S3 + + } + // must init luts on epaper if (ep_mode) { Init_EPD(DISPLAY_INIT_FULL); @@ -601,105 +805,148 @@ void uDisplay::DisplayInit(int8_t p, int8_t size, int8_t rot, int8_t font) { } } -void uDisplay::spi_command(uint8_t val) { - if (spi_dc < 0) { - if (spi_nr > 2) { - if (spi_nr == 3) { - write9(val, 0); +void uDisplay::ulcd_command(uint8_t val) { + + if (interface == _UDSP_SPI) { + if (spi_dc < 0) { + if (spi_nr > 2) { + if (spi_nr == 3) { + write9(val, 0); + } else { + write9_slow(val, 0); + } } else { - write9_slow(val, 0); + hw_write9(val, 0); } } else { - hw_write9(val, 0); - } - } else { - SPI_DC_LOW - if (spi_nr > 2) { - if (spi_nr == 3) { - write8(val); + SPI_DC_LOW + if (spi_nr > 2) { + if (spi_nr == 3) { + write8(val); + } else { + write8_slow(val); + } } else { - write8_slow(val); + uspi->write(val); } - } else { - uspi->write(val); + SPI_DC_HIGH } - SPI_DC_HIGH + return; } + +#ifdef USE_ESP32_S3 + if (interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { + pb_writeCommand(val, 8); + } +#endif // USE_ESP32_S3 } -void uDisplay::spi_data8(uint8_t val) { - if (spi_dc < 0) { - if (spi_nr > 2) { - if (spi_nr == 3) { +void uDisplay::ulcd_data8(uint8_t val) { + + if (interface == _UDSP_SPI) { + if (spi_dc < 0) { + if (spi_nr > 2) { + if (spi_nr == 3) { + write9(val, 1); + } else { + write9_slow(val, 1); + } + } else { + hw_write9(val, 1); + } + } else { + if (spi_nr > 2) { + if (spi_nr == 3) { + write8(val); + } else { + write8_slow(val); + } + } else { + uspi->write(val); + } + } + return; + } + +#ifdef USE_ESP32_S3 + if (interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { + pb_writeData(val, 8); + } +#endif // USE_ESP32_S3 +} + +void uDisplay::ulcd_data16(uint16_t val) { + + if (interface == _UDSP_SPI) { + if (spi_dc < 0) { + if (spi_nr > 2) { + write9(val >> 8, 1); write9(val, 1); } else { - write9_slow(val, 1); + hw_write9(val >> 8, 1); + hw_write9(val, 1); } } else { - hw_write9(val, 1); - } - } else { - if (spi_nr > 2) { - if (spi_nr == 3) { - write8(val); + if (spi_nr > 2) { + write16(val); } else { - write8_slow(val); + uspi->write16(val); + } + } + return; + } + +#ifdef USE_ESP32_S3 + if (interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { + pb_writeData(val, 16); + } +#endif // USE_ESP32_S3 +} + +void uDisplay::ulcd_data32(uint32_t val) { + + if (interface == _UDSP_SPI) { + if (spi_dc < 0) { + if (spi_nr > 2) { + write9(val >> 24, 1); + write9(val >> 16, 1); + write9(val >> 8, 1); + write9(val, 1); + } else { + hw_write9(val >> 24, 1); + hw_write9(val >> 16, 1); + hw_write9(val >> 8, 1); + hw_write9(val, 1); } } else { - uspi->write(val); + if (spi_nr > 2) { + write32(val); + } else { + uspi->write32(val); + } } + return; } + +#ifdef USE_ESP32_S3 + if (interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { + pb_writeData(val, 32); + } +#endif // USE_ESP32_S3 } -void uDisplay::spi_data16(uint16_t val) { - if (spi_dc < 0) { - if (spi_nr > 2) { - write9(val >> 8, 1); - write9(val, 1); - } else { - hw_write9(val >> 8, 1); - hw_write9(val, 1); - } - } else { - if (spi_nr > 2) { - write16(val); - } else { - uspi->write16(val); - } - } -} +void uDisplay::ulcd_command_one(uint8_t val) { -void uDisplay::spi_data32(uint32_t val) { - if (spi_dc < 0) { - if (spi_nr > 2) { - write9(val >> 24, 1); - write9(val >> 16, 1); - write9(val >> 8, 1); - write9(val, 1); - } else { - hw_write9(val >> 24, 1); - hw_write9(val >> 16, 1); - hw_write9(val >> 8, 1); - hw_write9(val, 1); - } - } else { - if (spi_nr > 2) { - write32(val); - } else { - uspi->write32(val); - } + if (interface == _UDSP_SPI) { + SPI_BEGIN_TRANSACTION + SPI_CS_LOW + ulcd_command(val); + SPI_CS_HIGH + SPI_END_TRANSACTION } } -void uDisplay::spi_command_one(uint8_t val) { - SPI_BEGIN_TRANSACTION - SPI_CS_LOW - spi_command(val); - SPI_CS_HIGH - SPI_END_TRANSACTION -} - void uDisplay::i2c_command(uint8_t val) { //Serial.printf("%02x\n",val ); wire->beginTransmission(i2caddr); @@ -787,9 +1034,9 @@ void uDisplay::Updateframe(void) { SPI_CS_LOW // below commands are not needed for SH1107 - // spi_command(saw_1 | 0x0); // set low col = 0, 0x00 - // spi_command(i2c_page_start | 0x0); // set hi col = 0, 0x10 - // spi_command(i2c_page_end | 0x0); // set startline line #0, 0x40 + // ulcd_command(saw_1 | 0x0); // set low col = 0, 0x00 + // ulcd_command(i2c_page_start | 0x0); // set hi col = 0, 0x10 + // ulcd_command(i2c_page_end | 0x0); // set startline line #0, 0x40 uint8_t ys = gys >> 3; uint8_t xs = gxs >> 3; @@ -803,13 +1050,13 @@ void uDisplay::Updateframe(void) { uint8_t i, j, k = 0; for ( i = 0; i < ys; i++) { // i = line from 0 to ys // send a bunch of data in one xmission - spi_command(0xB0 + i + m_row); //set page address - spi_command(m_col & 0xf); //set lower column address - spi_command(0x10 | (m_col >> 4)); //set higher column address + ulcd_command(0xB0 + i + m_row); //set page address + ulcd_command(m_col & 0xf); //set lower column address + ulcd_command(0x10 | (m_col >> 4)); //set higher column address for ( j = 0; j < 8; j++) { for ( k = 0; k < xs; k++, p++) { - spi_data8(framebuffer[p]); + ulcd_data8(framebuffer[p]); } } } @@ -828,10 +1075,11 @@ void uDisplay::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { return; } - if (interface != _UDSP_SPI) { + if (framebuffer) { Renderer::drawFastVLine(x, y, h, color); return; } + // Rudimentary clipping if ((x >= _width) || (y >= _height)) return; if ((y + h - 1) >= _height) h = _height - y; @@ -851,9 +1099,9 @@ void uDisplay::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { b = (b * 255) / 31; while (h--) { - spi_data8(r); - spi_data8(g); - spi_data8(b); + ulcd_data8(r); + ulcd_data8(g); + ulcd_data8(b); } } else { while (h--) { @@ -874,7 +1122,7 @@ void uDisplay::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { return; } - if (interface != _UDSP_SPI) { + if (framebuffer) { Renderer::drawFastHLine(x, y, w, color); return; } @@ -899,9 +1147,9 @@ void uDisplay::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { b = (b * 255) / 31; while (w--) { - spi_data8(r); - spi_data8(g); - spi_data8(b); + ulcd_data8(r); + ulcd_data8(g); + ulcd_data8(b); } } else { while (w--) { @@ -932,7 +1180,7 @@ void uDisplay::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t col return; } - if (interface != _UDSP_SPI) { + if (framebuffer) { Renderer::fillRect(x, y, w, h, color); return; } @@ -957,9 +1205,9 @@ void uDisplay::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t col for (y = h; y > 0; y--) { for (x = w; x > 0; x--) { - spi_data8(r); - spi_data8(g); - spi_data8(b); + ulcd_data8(r); + ulcd_data8(g); + ulcd_data8(b); } } @@ -1051,17 +1299,17 @@ void uDisplay::setAddrWindow_int(uint16_t x, uint16_t y, uint16_t w, uint16_t h) y += y_addr_offs[cur_rot]; if (sa_mode != 8) { - uint32_t xa = ((uint32_t)x << 16) | (x+w-1); - uint32_t ya = ((uint32_t)y << 16) | (y+h-1); + uint32_t xa = ((uint32_t)x << 16) | (x + w - 1); + uint32_t ya = ((uint32_t)y << 16) | (y + h - 1); - spi_command(saw_1); - spi_data32(xa); + ulcd_command(saw_1); + ulcd_data32(xa); - spi_command(saw_2); - spi_data32(ya); + ulcd_command(saw_2); + ulcd_data32(ya); if (saw_3 != 0xff) { - spi_command(saw_3); // write to RAM + ulcd_command(saw_3); // write to RAM } } else { uint16_t x2 = x + w - 1, @@ -1071,24 +1319,24 @@ void uDisplay::setAddrWindow_int(uint16_t x, uint16_t y, uint16_t w, uint16_t h) udisp_swap(x,y); udisp_swap(x2,y2); } - spi_command(saw_1); + ulcd_command(saw_1); if (allcmd_mode) { - spi_data8(x); - spi_data8(x2); + ulcd_data8(x); + ulcd_data8(x2); } else { - spi_command(x); - spi_command(x2); + ulcd_command(x); + ulcd_command(x2); } - spi_command(saw_2); + ulcd_command(saw_2); if (allcmd_mode) { - spi_data8(y); - spi_data8(y2); + ulcd_data8(y); + ulcd_data8(y2); } else { - spi_command(y); - spi_command(y2); + ulcd_command(y); + ulcd_command(y2); } if (saw_3 != 0xff) { - spi_command(saw_3); // write to RAM + ulcd_command(saw_3); // write to RAM } } } @@ -1194,9 +1442,15 @@ void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) { } else { // 9 bit and others - lvgl_color_swap(data, len); - while (len--) { - WriteColor(*data++); + if (interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { + #ifdef USE_ESP32_S3 + pb_pushPixels(data, len, true, false); + #endif // USE_ESP32_S3 + } else { + lvgl_color_swap(data, len); + while (len--) { + WriteColor(*data++); + } } } #endif // ESP32 @@ -1226,8 +1480,14 @@ void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) { #endif } else { // 9 bit and others - while (len--) { - WriteColor(*data++); + if (interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { +#ifdef USE_ESP32_S3 + pb_pushPixels(data, len, false, false); +#endif // USE_ESP32_S3 + } else { + while (len--) { + WriteColor(*data++); + } } } } @@ -1244,11 +1504,11 @@ void uDisplay::WriteColor(uint16_t color) { g = (g * 255) / 63; b = (b * 255) / 31; - spi_data8(r); - spi_data8(g); - spi_data8(b); + ulcd_data8(r); + ulcd_data8(g); + ulcd_data8(b); } else { - spi_data16(color); + ulcd_data16(color); } } @@ -1260,13 +1520,11 @@ void uDisplay::drawPixel(int16_t x, int16_t y, uint16_t color) { return; } - if (interface != _UDSP_SPI || bpp < 16) { + if (framebuffer) { Renderer::drawPixel(x, y, color); return; } - - if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) return; @@ -1286,12 +1544,12 @@ void uDisplay::drawPixel(int16_t x, int16_t y, uint16_t color) { void uDisplay::setRotation(uint8_t rotation) { cur_rot = rotation; - if (interface != _UDSP_SPI || bpp < 16) { + if (framebuffer) { Renderer::setRotation(cur_rot); return; } - if (interface == _UDSP_SPI) { + if (interface == _UDSP_SPI || interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { if (ep_mode) { Renderer::setRotation(cur_rot); @@ -1299,17 +1557,17 @@ void uDisplay::setRotation(uint8_t rotation) { } SPI_BEGIN_TRANSACTION SPI_CS_LOW - spi_command(madctrl); + ulcd_command(madctrl); if (!allcmd_mode) { - spi_data8(rot[cur_rot]); + ulcd_data8(rot[cur_rot]); } else { - spi_command(rot[cur_rot]); + ulcd_command(rot[cur_rot]); } if ((sa_mode == 8) && !allcmd_mode) { - spi_command(startline); - spi_data8((cur_rot < 2) ? height() : 0); + ulcd_command(startline); + ulcd_data8((cur_rot < 2) ? height() : 0); } SPI_CS_HIGH @@ -1358,7 +1616,7 @@ void uDisplay::DisplayOnff(int8_t on) { } } else { if (on) { - if (dsp_on != 0xff) spi_command_one(dsp_on); + if (dsp_on != 0xff) ulcd_command_one(dsp_on); if (bpanel >= 0) { #ifdef ESP32 if (!bpmode) { @@ -1376,7 +1634,7 @@ void uDisplay::DisplayOnff(int8_t on) { } } else { - if (dsp_off != 0xff) spi_command_one(dsp_off); + if (dsp_off != 0xff) ulcd_command_one(dsp_off); if (bpanel >= 0) { #ifdef ESP32 if (!bpmode) { @@ -1402,11 +1660,11 @@ void uDisplay::invertDisplay(boolean i) { return; } - if (interface == _UDSP_SPI) { + if (interface == _UDSP_SPI || interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { if (i) { - spi_command_one(inv_on); + ulcd_command_one(inv_on); } else { - spi_command_one(inv_off); + ulcd_command_one(inv_off); } } if (interface == _UDSP_I2C) { @@ -1450,8 +1708,8 @@ void uDisplay::dim10(uint8_t dim, uint16_t dim_gamma) { // dimmer with if (dim_op != 0xff) { // send SPI command if dim configured SPI_BEGIN_TRANSACTION SPI_CS_LOW - spi_command(dim_op); - spi_data8(dimmer8); + ulcd_command(dim_op); + ulcd_data8(dimmer8); SPI_CS_HIGH SPI_END_TRANSACTION } @@ -1571,7 +1829,7 @@ uint32_t uDisplay::next_hex(char **sp) { #include "esp32-hal.h" #include "soc/spi_struct.h" -// since ardunio transferBits ia completely disfunctional +// since ardunio transferBits is completely disfunctional // we use our own hardware driver for 9 bit spi void uDisplay::hw_write9(uint8_t val, uint8_t dc) { @@ -1709,7 +1967,7 @@ void USECACHE uDisplay::write32(uint32_t val) { void uDisplay::spi_data8_EPD(uint8_t val) { SPI_BEGIN_TRANSACTION SPI_CS_LOW - spi_data8(val); + ulcd_data8(val); SPI_CS_HIGH SPI_END_TRANSACTION } @@ -1717,7 +1975,7 @@ void uDisplay::spi_data8_EPD(uint8_t val) { void uDisplay::spi_command_EPD(uint8_t val) { SPI_BEGIN_TRANSACTION SPI_CS_LOW - spi_command(val); + ulcd_command(val); SPI_CS_HIGH SPI_END_TRANSACTION } @@ -2162,6 +2420,422 @@ void uDisplay::pushPixels3DMA(uint8_t* image, uint32_t len) { } } +#ifdef USE_ESP32_S3 +void uDisplay::calcClockDiv(uint32_t* div_a, uint32_t* div_b, uint32_t* div_n, uint32_t* clkcnt, uint32_t baseClock, uint32_t targetFreq) { + uint32_t diff = INT32_MAX; + *div_n = 256; + *div_a = 63; + *div_b = 62; + *clkcnt = 64; + uint32_t start_cnt = std::min(64u, (baseClock / (targetFreq * 2) + 1)); + uint32_t end_cnt = std::max(2u, baseClock / 256u / targetFreq); + if (start_cnt <= 2) { end_cnt = 1; } + for (uint32_t cnt = start_cnt; diff && cnt >= end_cnt; --cnt) + { + float fdiv = (float)baseClock / cnt / targetFreq; + uint32_t n = std::max(2u, (uint32_t)fdiv); + fdiv -= n; + for (uint32_t a = 63; diff && a > 0; --a) + { + uint32_t b = roundf(fdiv * a); + if (a == b && n == 256) { + break; + } + uint32_t freq = baseClock / ((n * cnt) + (float)(b * cnt) / (float)a); + uint32_t d = abs((int)targetFreq - (int)freq); + if (diff <= d) { continue; } + diff = d; + *clkcnt = cnt; + *div_n = n; + *div_b = b; + *div_a = a; + if (b == 0 || a == b) { + break; + } + } + } + if (*div_a == *div_b) + { + *div_b = 0; + *div_n += 1; + } + } + +void uDisplay::_alloc_dmadesc(size_t len) { + if (_dmadesc) heap_caps_free(_dmadesc); + _dmadesc_size = len; + _dmadesc = (lldesc_t*)heap_caps_malloc(sizeof(lldesc_t) * len, MALLOC_CAP_DMA); +} + +void uDisplay::_setup_dma_desc_links(const uint8_t *data, int32_t len) { + static constexpr size_t MAX_DMA_LEN = (4096-4); +/* + if (_dmadesc_size * MAX_DMA_LEN < len) { + _alloc_dmadesc(len / MAX_DMA_LEN + 1); + } + lldesc_t *dmadesc = _dmadesc; + + while (len > MAX_DMA_LEN) { + len -= MAX_DMA_LEN; + dmadesc->buffer = (uint8_t *)data; + data += MAX_DMA_LEN; + *(uint32_t*)dmadesc = MAX_DMA_LEN | MAX_DMA_LEN << 12 | 0x80000000; + dmadesc->next = dmadesc + 1; + dmadesc++; + } + *(uint32_t*)dmadesc = ((len + 3) & ( ~3 )) | len << 12 | 0xC0000000; + dmadesc->buffer = (uint8_t *)data; + dmadesc->next = nullptr; + */ + } + + +void uDisplay::pb_beginTransaction(void) { + auto dev = _dev; + dev->lcd_clock.val = _clock_reg_value; + // int clk_div = std::min(63u, std::max(1u, 120*1000*1000 / (_cfg.freq_write+1))); + // dev->lcd_clock.lcd_clk_sel = 2; // clock_select: 1=XTAL CLOCK / 2=240MHz / 3=160MHz + // dev->lcd_clock.lcd_clkcnt_n = clk_div; + // dev->lcd_clock.lcd_clk_equ_sysclk = 0; + // dev->lcd_clock.lcd_ck_idle_edge = true; + // dev->lcd_clock.lcd_ck_out_edge = false; + + dev->lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE; + // dev->lcd_misc.lcd_cd_idle_edge = 1; + // dev->lcd_misc.lcd_cd_cmd_set = 0; + // dev->lcd_misc.lcd_cd_dummy_set = 0; + // dev->lcd_misc.lcd_cd_data_set = 0; + + dev->lcd_user.val = 0; + // dev->lcd_user.lcd_byte_order = false; + // dev->lcd_user.lcd_bit_order = false; + // dev->lcd_user.lcd_8bits_order = false; + + dev->lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG; + + _cache_flip = _cache[0]; + } + +void uDisplay::pb_endTransaction(void) { + auto dev = _dev; + while (dev->lcd_user.val & LCD_CAM_LCD_START) {} +} + +void uDisplay::pb_wait(void) { + auto dev = _dev; + while (dev->lcd_user.val & LCD_CAM_LCD_START) {} +} + +bool uDisplay::pb_busy(void) { + auto dev = _dev; + return (dev->lcd_user.val & LCD_CAM_LCD_START); +} + +bool uDisplay::pb_writeCommand(uint32_t data, uint_fast8_t bit_length) { + if (interface == _UDSP_PAR8) { + // 8bit bus + auto bytes = bit_length >> 3; + auto dev = _dev; + auto reg_lcd_user = &(dev->lcd_user.val); + dev->lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET; + do { + dev->lcd_cmd_val.lcd_cmd_value = data; + data >>= 8; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + } while (--bytes); + return true; + } else { + // 16 bit bus + if (_has_align_data) { _send_align_data(); } + auto dev = _dev; + auto reg_lcd_user = &(dev->lcd_user.val); + dev->lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET; + dev->lcd_cmd_val.val = data; + + if (bit_length <= 16) { + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + return true; + } + + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + return true; + } + } + + +void uDisplay::pb_writeData(uint32_t data, uint_fast8_t bit_length) { + if (interface == _UDSP_PAR8) { + auto bytes = bit_length >> 3; + auto dev = _dev; + auto reg_lcd_user = &(dev->lcd_user.val); + dev->lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE; + + uint8_t shift = (bytes - 1) * 8; + for (uint32_t cnt = 0; cnt < bytes; cnt++) { + dev->lcd_cmd_val.lcd_cmd_value = (data >> shift) & 0xff; + shift -= 8; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + } + return; + + } else { + auto bytes = bit_length >> 3; + auto dev = _dev; + auto reg_lcd_user = &(dev->lcd_user.val); + dev->lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE; + if (_has_align_data) { + _has_align_data = false; + dev->lcd_cmd_val.val = _align_data | (data << 8); + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + if (--bytes == 0) { return; } + data >>= 8; + } + + if (bytes > 1) { + dev->lcd_cmd_val.val = data; + if (bytes == 4) { + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + return; + } + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + if (bytes == 2) { return; } + data >>= 16; + } + _has_align_data = true; + _align_data = data; + } +} + +void uDisplay::pb_pushPixels(uint16_t* data, uint32_t length, bool swap_bytes, bool use_dma) { + auto dev = _dev; + auto reg_lcd_user = &(dev->lcd_user.val); + dev->lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE; + + if (interface == _UDSP_PAR8) { + if (swap_bytes) { + for (uint32_t cnt = 0; cnt < length; cnt++) { + dev->lcd_cmd_val.lcd_cmd_value = *data; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + dev->lcd_cmd_val.lcd_cmd_value = *data >> 8; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + data++; + } + } else { + for (uint32_t cnt = 0; cnt < length; cnt++) { + dev->lcd_cmd_val.lcd_cmd_value = *data >> 8; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + dev->lcd_cmd_val.lcd_cmd_value = *data; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + data++; + } + } + } else { + if (swap_bytes) { + uint16_t iob; + for (uint32_t cnt = 0; cnt < length; cnt++) { + iob = *data++; + iob = (iob << 8) | (iob >> 8); + dev->lcd_cmd_val.lcd_cmd_value = iob; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + data++; + } + } else { + for (uint32_t cnt = 0; cnt < length; cnt++) { + dev->lcd_cmd_val.lcd_cmd_value = *data++; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + } + } + } +} + + +void uDisplay::pb_writeBytes(const uint8_t* data, uint32_t length, bool use_dma) { + +/* + uint32_t freq = spi_speed * 1000000; + uint32_t slow = (freq< 4000000) ? 2 : (freq < 8000000) ? 1 : 0; + + auto dev = _dev; + do { + auto reg_lcd_user = &(dev->lcd_user.val); + dev->lcd_misc.lcd_cd_cmd_set = 0; + dev->lcd_cmd_val.lcd_cmd_value = data[0] | data[1] << 16; + uint32_t cmd_val = data[2] | data[3] << 16; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; + + if (use_dma) { + if (slow) { ets_delay_us(slow); } + _setup_dma_desc_links(&data[4], length - 4); + gdma_start(_dma_chan, (intptr_t)(_dmadesc)); + length = 0; + } else { + size_t len = length; + if (len > CACHE_SIZE) { + len = (((len - 1) % CACHE_SIZE) + 4) & ~3u; + } + memcpy(_cache_flip, &data[4], (len-4+3)&~3); + _setup_dma_desc_links((const uint8_t*)_cache_flip, len-4); + gdma_start(_dma_chan, (intptr_t)(_dmadesc)); + length -= len; + data += len; + _cache_flip = _cache[(_cache_flip == _cache[0])]; + } + dev->lcd_cmd_val.lcd_cmd_value = cmd_val; + dev->lcd_misc.lcd_cd_data_set = 0; + *reg_lcd_user = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG; + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_START; + } while (length); +*/ +} + + +void uDisplay::_send_align_data(void) { + _has_align_data = false; + auto dev = _dev; + dev->lcd_cmd_val.lcd_cmd_value = _align_data; + auto reg_lcd_user = &(dev->lcd_user.val); + while (*reg_lcd_user & LCD_CAM_LCD_START) {} + *reg_lcd_user = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START; +} + + +void uDisplay::cs_control(bool level) { + auto pin = par_cs; + if (pin < 0) return; + if (level) { + gpio_hi(pin); + } + else { + gpio_lo(pin); + } +} + +void uDisplay::_pb_init_pin(bool read) { + if (read) { + if (interface == _UDSP_PAR8) { + for (size_t i = 0; i < 8; ++i) { + gpio_ll_output_disable(&GPIO, (gpio_num_t)par_dbl[i]); + } + } else { + for (size_t i = 0; i < 8; ++i) { + gpio_ll_output_disable(&GPIO, (gpio_num_t)par_dbl[i]); + } + for (size_t i = 0; i < 8; ++i) { + gpio_ll_output_disable(&GPIO, (gpio_num_t)par_dbh[i]); + } + } + } + else { + auto idx_base = LCD_DATA_OUT0_IDX; + if (interface == _UDSP_PAR8) { + for (size_t i = 0; i < 8; ++i) { + gpio_matrix_out(par_dbl[i], idx_base + i, 0, 0); + } + } else { + for (size_t i = 0; i < 8; ++i) { + gpio_matrix_out(par_dbl[i], idx_base + i, 0, 0); + } + for (size_t i = 0; i < 8; ++i) { + gpio_matrix_out(par_dbh[i], idx_base + 8 + i, 0, 0); + } + } + } +} + +/* read analog value from pin for simple digitizer +X+ = d1 +X- = CS +Y+ = RS +Y- = D0 + +define YP A2 // must be an analog pin, use "An" notation! +#define XM A3 // must be an analog pin, use "An" notation! +#define YM 8 // can be a digital pin +#define XP 9 // can be a digital pin + +*/ +uint32_t uDisplay::get_sr_touch(uint32_t _xp, uint32_t _xm, uint32_t _yp, uint32_t _ym) { + uint32_t aval = 0; + uint16_t xp,yp; + if (pb_busy()) return 0; + + _pb_init_pin(true); + gpio_matrix_out(par_rs, 0x100, 0, 0); + + pinMode(_ym, INPUT_PULLUP); // d0 + pinMode(_yp, INPUT_PULLUP); // rs + + pinMode(_xm, OUTPUT); // cs + pinMode(_xp, OUTPUT); // d1 + digitalWrite(_xm, HIGH); // cs + digitalWrite(_xp, LOW); // d1 + + xp = 4096 - analogRead(_ym); // d0 + + pinMode(_xm, INPUT_PULLUP); // cs + pinMode(_xp, INPUT_PULLUP); // d1 + + pinMode(_ym, OUTPUT); // d0 + pinMode(_yp, OUTPUT); // rs + digitalWrite(_ym, HIGH); // d0 + digitalWrite(_yp, LOW); // rs + + yp = 4096 - analogRead(_xp); // d1 + + aval = (xp << 16) | yp; + + pinMode(_yp, OUTPUT); // rs + pinMode(_xm, OUTPUT); // cs + pinMode(_ym, OUTPUT); // d0 + pinMode(_xp, OUTPUT); // d1 + digitalWrite(_yp, HIGH); // rs + digitalWrite(_xm, HIGH); // cs + + _pb_init_pin(false); + gpio_matrix_out(par_rs, LCD_DC_IDX, 0, 0); + + return aval; +} + + +#if 0 +void TFT_eSPI::startWrite(void) +{ + begin_tft_write(); + lockTransaction = true; // Lock transaction for all sequentially run sketch functions + inTransaction = true; +} + +/*************************************************************************************** +** Function name: endWrite +** Description: end transaction with CS high +***************************************************************************************/ +void TFT_eSPI::endWrite(void) +{ + lockTransaction = false; // Release sketch induced transaction lock + inTransaction = false; + DMA_BUSY_CHECK; // Safety check - user code should have checked this! + end_tft_write(); // Release SPI bus +} +#endif + + +#endif // USE_ESP32_S3 #endif // ESP32 diff --git a/lib/lib_display/UDisplay/uDisplay.h b/lib/lib_display/UDisplay/uDisplay.h index 93ee851e6..8d79bc8bc 100755 --- a/lib/lib_display/UDisplay/uDisplay.h +++ b/lib/lib_display/UDisplay/uDisplay.h @@ -5,12 +5,38 @@ #include #include #include + + +#ifdef ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32S3 +#define USE_ESP32_S3 +#endif +#endif + #ifdef ESP32 #include "driver/spi_master.h" #endif +#ifdef USE_ESP32_S3 +#include +#include "esp_private/gdma.h" +#include +#include +#include +#include +static inline volatile uint32_t* get_gpio_hi_reg(int_fast8_t pin) { return (pin & 32) ? &GPIO.out1_w1ts.val : &GPIO.out_w1ts; } +//static inline volatile uint32_t* get_gpio_hi_reg(int_fast8_t pin) { return (volatile uint32_t*)((pin & 32) ? 0x60004014 : 0x60004008) ; } // workaround Eratta +static inline volatile uint32_t* get_gpio_lo_reg(int_fast8_t pin) { return (pin & 32) ? &GPIO.out1_w1tc.val : &GPIO.out_w1tc; } +//static inline volatile uint32_t* get_gpio_lo_reg(int_fast8_t pin) { return (volatile uint32_t*)((pin & 32) ? 0x60004018 : 0x6000400C) ; } +static inline bool gpio_in(int_fast8_t pin) { return ((pin & 32) ? GPIO.in1.data : GPIO.in) & (1 << (pin & 31)); } +static inline void gpio_hi(int_fast8_t pin) { if (pin >= 0) *get_gpio_hi_reg(pin) = 1 << (pin & 31); } // ESP_LOGI("LGFX", "gpio_hi: %d", pin); } +static inline void gpio_lo(int_fast8_t pin) { if (pin >= 0) *get_gpio_lo_reg(pin) = 1 << (pin & 31); } // ESP_LOGI("LGFX", "gpio_lo: %d", pin); } +#endif + #define _UDSP_I2C 1 #define _UDSP_SPI 2 +#define _UDSP_PAR8 3 +#define _UDSP_PAR16 4 #define UDISP1_WHITE 1 #define UDISP1_BLACK 0 @@ -76,6 +102,22 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR }; #define LUTMAXSIZE 64 +#ifdef USE_ESP32_S3 +struct esp_lcd_i80_bus_t { + int bus_id; // Bus ID, index from 0 + portMUX_TYPE spinlock; // spinlock used to protect i80 bus members(hal, device_list, cur_trans) + lcd_hal_context_t hal; // Hal object + size_t bus_width; // Number of data lines + intr_handle_t intr; // LCD peripheral interrupt handle + void* pm_lock; // Power management lock + size_t num_dma_nodes; // Number of DMA descriptors + uint8_t *format_buffer; // The driver allocates an internal buffer for DMA to do data format transformer + size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source + gdma_channel_handle_t dma_chan; // DMA channel handle +}; +#endif + + class uDisplay : public Renderer { public: uDisplay(char *); @@ -110,11 +152,11 @@ class uDisplay : public Renderer { void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); uint32_t str2c(char **sp, char *vp, uint32_t len); void i2c_command(uint8_t val); - void spi_command_one(uint8_t val); - void spi_command(uint8_t val); - void spi_data8(uint8_t val); - void spi_data16(uint16_t val); - void spi_data32(uint32_t val); + void ulcd_command_one(uint8_t val); + void ulcd_command(uint8_t val); + void ulcd_data8(uint8_t val); + void ulcd_data16(uint16_t val); + void ulcd_data32(uint32_t val); void write8(uint8_t val); void write8_slow(uint8_t val); void write9(uint8_t val, uint8_t dc); @@ -226,6 +268,44 @@ class uDisplay : public Renderer { int16_t rotmap_ymin; int16_t rotmap_ymax; void pushColorsMono(uint16_t *data, uint16_t len, bool rgb16_swap = false); + +#ifdef USE_ESP32_S3 + int8_t par_cs; + int8_t par_rs; + int8_t par_wr; + int8_t par_rd; + + int8_t par_dbl[8]; + int8_t par_dbh[8]; + + esp_lcd_i80_bus_handle_t _i80_bus = nullptr; + gdma_channel_handle_t _dma_chan; + lldesc_t *_dmadesc = nullptr; + uint32_t _dmadesc_size = 0; + uint32_t _clock_reg_value; + void calcClockDiv(uint32_t* div_a, uint32_t* div_b, uint32_t* div_n, uint32_t* clkcnt, uint32_t baseClock, uint32_t targetFreq); + void _alloc_dmadesc(size_t len); + void _setup_dma_desc_links(const uint8_t *data, int32_t len); + void pb_beginTransaction(void); + void pb_endTransaction(void); + void pb_wait(void); + bool pb_busy(void); + void _pb_init_pin(bool); + bool pb_writeCommand(uint32_t data, uint_fast8_t bit_length); + void pb_writeData(uint32_t data, uint_fast8_t bit_length); + void pb_pushPixels(uint16_t* data, uint32_t length, bool swap_bytes, bool use_dma); + void pb_writeBytes(const uint8_t* data, uint32_t length, bool use_dma); + void _send_align_data(void); + volatile lcd_cam_dev_t* _dev; + uint32_t* _cache_flip; + static constexpr size_t CACHE_SIZE = 256; + uint32_t _cache[2][CACHE_SIZE / sizeof(uint32_t)]; + bool _has_align_data; + uint8_t _align_data; + void cs_control(bool level); + uint32_t get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym); +#endif + #ifdef ESP32 // dma section bool DMA_Enabled = false; diff --git a/lib/lib_i2c/Adafruit_SGP40-1.1.0/.gitignore b/lib/lib_i2c/Adafruit_SGP40-1.1.0/.gitignore new file mode 100644 index 000000000..1439065d9 --- /dev/null +++ b/lib/lib_i2c/Adafruit_SGP40-1.1.0/.gitignore @@ -0,0 +1,9 @@ +*~ +doxygen_sqlite3.db +html# osx +.DS_Store + +# doxygen +doxygen_sqlite3.db +html +*.tmp diff --git a/lib/lib_i2c/Adafruit_SGP40-1.1.0/Doxyfile b/lib/lib_i2c/Adafruit_SGP40-1.1.0/Doxyfile new file mode 100644 index 000000000..cc75f93aa --- /dev/null +++ b/lib/lib_i2c/Adafruit_SGP40-1.1.0/Doxyfile @@ -0,0 +1,2492 @@ +# Doxyfile 1.8.13 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Adafruit SGP-40 Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = YES + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = src/Adafruit_SGP40.cpp src/Adafruit_SGP40.h + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /