From fc7c1ac6b7e6f64049b0b34f53908d7f1522f4ac Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 15 Dec 2018 15:55:51 +0100 Subject: [PATCH] Updates for release 6.4.0 Updates for release 6.4.0 --- RELEASENOTES.md | 165 +- arduino/version 2.4.0/boards.txt | 3341 ------- arduino/version 2.4.0/platform.txt | 133 - arduino/version 2.4.1/boards.txt | 3796 -------- arduino/version 2.4.1/platform.txt | 137 - .../MPU6050_6Axis_MotionApps20.h | 16 +- lib/IRremoteESP8266-2.2.1.02/README.md | 74 - lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md | 112 - .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 199 - .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 44 - lib/IRremoteESP8266-2.2.1.02/keywords.txt | 128 - lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h | 207 - .../src/IRremoteESP8266.h | 337 - lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp | 327 - lib/IRremoteESP8266-2.2.1.02/src/IRsend.h | 209 - lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp | 82 - lib/IRremoteESP8266-2.2.1.02/src/IRutils.h | 23 - .../src/ir_Coolix.cpp | 167 - .../src/ir_Daikin.cpp | 347 - lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h | 107 - .../src/ir_Fujitsu.cpp | 221 - lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h | 80 - lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp | 113 - .../src/ir_Kelvinator.cpp | 329 - lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp | 233 - .../src/ir_Mitsubishi.cpp | 349 - .../src/ir_Mitsubishi.h | 65 - lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp | 120 - .../src/ir_Panasonic.cpp | 196 - .../src/ir_Samsung.cpp | 175 - .../src/ir_Trotec.cpp | 151 - lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h | 80 - .../src/ir_Whynter.cpp | 144 - .../test/IRsend_test.cpp | 139 - .../test/IRsend_test.h | 106 - .../test/IRutils_test.cpp | 91 - .../test/ir_Daikin_test.cpp | 419 - .../test/ir_Fujitsu_test.cpp | 207 - .../test/ir_GlobalCache_test.cpp | 68 - .../test/ir_Gree_test.cpp | 192 - .../test/ir_Kelvinator_test.cpp | 432 - .../test/ir_Mitsubishi_test.cpp | 694 -- .../test/ir_Nikai_test.cpp | 210 - .../test/ir_Panasonic_test.cpp | 457 - .../test/ir_Samsung_test.cpp | 276 - .../test/ir_Sherwood_test.cpp | 72 - .../test/ir_Sony_test.cpp | 323 - .../tools/gc_decode.cpp | 106 - .../.github/CONTRIBUTING.md | 0 .../.github/Contributors.md | 2 + .../.github/issue_template.md | 7 +- .../.gitignore | 7 + .../.gitmodules | 1 + lib/IRremoteESP8266-2.5.2.03/.style.yapf | 3 + .../.travis.yml | 4 + .../CPPLINT.cfg | 0 .../LICENSE.txt | 0 lib/IRremoteESP8266-2.5.2.03/README.md | 78 + lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md | 308 + .../examples/IRGCSendDemo/IRGCSendDemo.ino | 29 +- .../examples/IRGCSendDemo/platformio.ini | 0 .../examples/IRGCTCPServer/IRGCTCPServer.ino | 16 +- .../examples/IRGCTCPServer/platformio.ini | 0 .../examples/IRMQTTServer/IRMQTTServer.ino | 866 +- .../examples/IRMQTTServer/platformio.ini | 2 +- .../examples/IRServer/IRServer.ino | 19 +- .../examples/IRServer/platformio.ini | 0 .../examples/IRrecvDemo/IRrecvDemo.ino | 14 +- .../examples/IRrecvDemo/platformio.ini | 0 .../examples/IRrecvDump/IRrecvDump.ino | 4 +- .../examples/IRrecvDump/platformio.ini | 0 .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 262 + .../examples/IRrecvDumpV2/platformio.ini | 0 .../examples/IRsendDemo/IRsendDemo.ino | 13 +- .../examples/IRsendDemo/platformio.ini | 0 .../IRsendProntoDemo/IRsendProntoDemo.ino | 11 +- .../examples/IRsendProntoDemo/platformio.ini | 0 .../JVCPanasonicSendDemo.ino | 29 +- .../JVCPanasonicSendDemo/platformio.ini | 0 .../examples/LGACSend/LGACSend.ino | 18 +- .../examples/LGACSend}/platformio.ini | 0 .../examples/TurnOnArgoAC/TurnOnArgoAC.ino | 24 +- .../examples/TurnOnArgoAC}/platformio.ini | 0 .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 37 +- .../examples/TurnOnDaikinAC}/platformio.ini | 0 .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 50 + .../examples/TurnOnFujitsuAC}/platformio.ini | 0 .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 45 +- .../TurnOnKelvinatorAC}/platformio.ini | 0 .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 33 +- .../TurnOnMitsubishiAC}/platformio.ini | 0 .../TurnOnToshibaAC/TurnOnToshibaAC.ino | 71 + .../examples/TurnOnToshibaAC/platformio.ini | 17 + .../TurnOnTrotecAC/TurnOnTrotecAC.ino | 22 +- .../examples/TurnOnTrotecAC/platformio.ini | 17 + lib/IRremoteESP8266-2.5.2.03/keywords.txt | 1645 ++++ .../library.json | 2 +- .../library.properties | 2 +- .../platformio.ini | 0 lib/IRremoteESP8266-2.5.2.03/pylintrc | 12 + .../src/CPPLINT.cfg | 0 .../src/IRrecv.cpp | 390 +- lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h | 335 + .../src/IRremoteESP8266.h | 601 ++ lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp | 601 ++ lib/IRremoteESP8266-2.5.2.03/src/IRsend.h | 333 + .../src/IRtimer.cpp | 20 +- .../src/IRtimer.h | 3 + lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp | 470 + lib/IRremoteESP8266-2.5.2.03/src/IRutils.h | 41 + .../src/ir_Aiwa.cpp | 40 +- .../src/ir_Argo.cpp | 104 +- .../src/ir_Argo.h | 74 +- .../src/ir_Carrier.cpp | 111 + .../src/ir_Coolix.cpp | 423 + lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h | 139 + .../src/ir_Daikin.cpp | 750 ++ lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h | 208 + .../src/ir_Denon.cpp | 77 +- .../src/ir_Dish.cpp | 80 +- .../src/ir_Electra.cpp | 112 + .../src/ir_Fujitsu.cpp | 519 + lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h | 123 + .../src/ir_GICable.cpp | 116 + .../src/ir_GlobalCache.cpp | 32 +- lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp | 478 + lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h | 130 + lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp | 865 ++ lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h | 297 + .../src/ir_Hitachi.cpp | 424 + lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h | 76 + .../src/ir_JVC.cpp | 95 +- .../src/ir_Kelvinator.cpp | 550 ++ .../src/ir_Kelvinator.h | 60 +- lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp | 290 + .../src/ir_LG.h | 0 .../src/ir_Lasertag.cpp | 122 + .../src/ir_Lutron.cpp | 156 + lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp | 202 + .../src/ir_Magiquest.cpp | 166 + .../src/ir_Magiquest.h | 35 + lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp | 403 + lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h | 103 + .../src/ir_Mitsubishi.cpp | 714 ++ .../src/ir_Mitsubishi.h | 109 + .../src/ir_NEC.cpp | 125 +- lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h | 46 + lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp | 104 + .../src/ir_Panasonic.cpp | 863 ++ .../src/ir_Panasonic.h | 145 + .../src/ir_Pioneer.cpp | 143 + .../src/ir_Pronto.cpp | 31 +- .../src/ir_RC5_RC6.cpp | 228 +- .../src/ir_RCMM.cpp | 116 +- .../src/ir_Samsung.cpp | 590 ++ lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h | 107 + .../src/ir_Sanyo.cpp | 100 +- .../src/ir_Sharp.cpp | 129 +- .../src/ir_Sherwood.cpp | 9 +- .../src/ir_Sony.cpp | 90 +- .../src/ir_Toshiba.cpp | 340 + lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h | 85 + .../src/ir_Trotec.cpp | 127 + lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h | 92 + .../src/ir_Whirlpool.cpp | 149 + .../src/ir_Whynter.cpp | 135 + .../test/IRrecv_test.cpp | 181 +- .../test/IRrecv_test.h | 17 + .../test/IRsend_test.cpp | 290 + .../test/IRsend_test.h | 135 + .../test/IRutils_test.cpp | 352 + .../test/Makefile | 186 +- .../test/ir_Aiwa_test.cpp | 128 +- .../test/ir_Carrier_test.cpp | 225 + .../test/ir_Coolix_test.cpp | 223 +- .../test/ir_Daikin_test.cpp | 838 ++ .../test/ir_Denon_test.cpp | 74 +- .../test/ir_Dish_test.cpp | 129 +- .../test/ir_Electra_test.cpp | 98 + .../test/ir_Fujitsu_test.cpp | 555 ++ .../test/ir_GICable_test.cpp | 161 + .../test/ir_GlobalCache_test.cpp | 71 + .../test/ir_Gree_test.cpp | 527 + .../test/ir_Haier_test.cpp | 989 ++ .../test/ir_Hitachi_test.cpp | 765 ++ .../test/ir_JVC_test.cpp | 91 +- .../test/ir_Kelvinator_test.cpp | 518 + .../test/ir_LG_test.cpp | 202 +- .../test/ir_Lasertag_test.cpp | 342 + .../test/ir_Lutron_test.cpp | 143 + .../test/ir_MWM_test.cpp | 124 + .../test/ir_Magiquest_test.cpp | 162 + .../test/ir_Midea_test.cpp | 651 ++ .../test/ir_Mitsubishi_test.cpp | 1118 +++ .../test/ir_NEC_test.cpp | 151 +- .../test/ir_Nikai_test.cpp | 212 + .../test/ir_Panasonic_test.cpp | 1135 +++ .../test/ir_Pioneer_test.cpp | 152 + .../test/ir_Pronto_test.cpp | 210 +- .../test/ir_RC5_RC6_test.cpp | 341 +- .../test/ir_RCMM_test.cpp | 90 +- .../test/ir_Samsung_test.cpp | 907 ++ .../test/ir_Sanyo_test.cpp | 126 +- .../test/ir_Sharp_test.cpp | 99 +- .../test/ir_Sherwood_test.cpp | 78 + .../test/ir_Sony_test.cpp | 357 + .../test/ir_Toshiba_test.cpp | 664 ++ .../test/ir_Whirlpool_test.cpp | 118 + .../test/ir_Whynter_test.cpp | 73 +- .../tools/Makefile | 72 +- .../tools/RawToGlobalCache.sh | 53 + .../tools/auto_analyse_raw_data.py | 432 + .../tools/auto_analyse_raw_data_test.py | 492 + .../tools/gc_decode.cpp | 109 + lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords | 82 + .../tools/mode2_decode.cpp | 122 + lib/NewPing-1.9.1/README.md | 3 + .../NewPing15SensorsTimer.pde | 78 + .../NewPing3Sensors/NewPing3Sensors.pde | 29 + .../NewPingEventTimer/NewPingEventTimer.pde | 46 + .../NewPingExample/NewPingExample.pde | 22 + .../NewPingTimerMedian/NewPingTimerMedian.pde | 60 + .../examples/TimerExample/TimerExample.pde | 25 + lib/NewPing-1.9.1/keywords.txt | 31 + lib/NewPing-1.9.1/library.properties | 10 + lib/NewPing-1.9.1/src/NewPing.cpp | 365 + lib/NewPing-1.9.1/src/NewPing.h | 275 + .../README.md | 0 .../examples/swsertest/swsertest.ino | 0 .../keywords.txt | 0 .../library.json | 2 +- .../library.properties | 2 +- .../src/TasmotaSerial.cpp | 15 +- .../src/TasmotaSerial.h | 3 +- .../.gitignore | 12 + .../.travis.yml | 43 + .../Arduino/epd2in9-demo/epd2in9-demo.ino | 82 + .../Arduino/libraries/readme.txt | 1 + .../LICENSE | 202 + .../Makefile | 9 + .../README.md | 124 + .../components/epaper-29-ws/component.mk | 2 + .../components/epaper-29-ws/epaper-29-ws.c | 695 ++ .../components/epaper-29-ws/epaper-29-ws.h | 351 + .../components/epaper-29-ws/epaper_font.c | 8615 +++++++++++++++++ .../components/epaper-29-ws/epaper_fonts.h | 36 + .../components/epaper-29-ws/font16.c | 1765 ++++ .../components/epaper-29-ws/font20.c | 2143 ++++ .../components/epaper-29-ws/font8.c | 1005 ++ .../components/epaper-29-ws/imagedata.cpp | 327 + .../components/epaper-29-ws/imagedata.h | 30 + .../docs/Doxyfile | 58 + .../docs/Makefile | 201 + .../docs/README.md | 8 + .../docs/conf.py | 298 + .../docs/gen-dxd.py | 301 + .../docs/index.rst | 9 + .../docs/link-roles.py | 34 + .../docs/repo_util.py | 5 + .../docs/requirements.txt | 6 + .../library.properties | 9 + .../main/README.md | 55 + .../main/component.mk | 4 + .../main/esp-epaper-29-ws.c | 105 + .../main/imagedata.c | 315 + .../main/imagedata.h | 18 + .../pictures/2.9inch_e-Paper_Datasheet.pdf | Bin 0 -> 1125667 bytes .../pictures/e-paper-and-esp-sample-image.jpg | Bin 0 -> 416611 bytes .../pictures/e-paper-and-esp-sample-text.jpg | Bin 0 -> 637704 bytes .../pictures/espresif-logo.bmp | Bin 0 -> 466254 bytes .../pictures/image-conversion-setup.png | Bin 0 -> 40816 bytes .../src/epd2in9.cpp | 317 + .../src/epd2in9.h | 106 + .../src/epdif.cpp | 96 + .../src/epdif.h | 76 + .../src/epdpaint.cpp | 322 + .../src/epdpaint.h | 74 + .../src/font12.c | 1385 +++ .../src/font16.c | 1765 ++++ .../src/font20.c | 2143 ++++ .../src/font24.c | 2521 +++++ .../src/font8.c | 1005 ++ .../src/fonts.h | 75 + sonoff/_changelog.ino | 63 +- sonoff/core_esp8266_timer.c | 10 +- sonoff/core_esp8266_wiring_digital.c | 2 +- sonoff/core_esp8266_wiring_pwm.c | 6 +- sonoff/i18n.h | 21 +- sonoff/language/bg-BG.h | 69 +- sonoff/language/cs-CZ.h | 25 +- sonoff/language/de-DE.h | 39 +- sonoff/language/el-GR.h | 468 +- sonoff/language/en-GB.h | 25 +- sonoff/language/es-AR.h | 29 +- sonoff/language/fr-FR.h | 73 +- sonoff/language/he-HE.h | 25 +- sonoff/language/hu-HU.h | 25 +- sonoff/language/it-IT.h | 25 +- sonoff/language/nl-NL.h | 25 +- sonoff/language/pl-PL.h | 155 +- sonoff/language/pt-BR.h | 25 +- sonoff/language/pt-PT.h | 25 +- sonoff/language/ru-RU.h | 25 +- sonoff/language/sv-SE.h | 609 ++ sonoff/language/tr-TR.h | 25 +- sonoff/language/uk-UK.h | 25 +- sonoff/language/zh-CN.h | 25 +- sonoff/language/zh-TW.h | 25 +- sonoff/my_user_config.h | 37 +- sonoff/settings.h | 36 +- sonoff/settings.ino | 94 +- sonoff/sonoff.h | 42 +- sonoff/sonoff.ino | 257 +- sonoff/sonoff_post.h | 27 +- sonoff/sonoff_template.h | 212 +- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 1402 +-- sonoff/support_features.ino | 388 + sonoff/support_rtc.ino | 421 + sonoff/support_wifi.ino | 594 ++ sonoff/xdrv_01_webserver.ino | 334 +- sonoff/xdrv_02_mqtt.ino | 65 +- sonoff/xdrv_03_energy.ino | 29 +- sonoff/xdrv_04_light.ino | 111 +- sonoff/xdrv_05_irremote.ino | 425 +- sonoff/xdrv_06_snfbridge.ino | 22 +- sonoff/xdrv_07_domoticz.ino | 108 +- sonoff/xdrv_08_serial_bridge.ino | 26 +- sonoff/xdrv_09_timers.ino | 29 +- sonoff/xdrv_10_rules.ino | 59 +- sonoff/xdrv_11_knx.ino | 28 +- sonoff/xdrv_12_home_assistant.ino | 494 +- sonoff/xdrv_13_display.ino | 54 +- sonoff/xdrv_14_mp3.ino | 40 +- sonoff/xdrv_16_tuyadimmer.ino | 408 +- sonoff/xdrv_17_rcswitch.ino | 16 +- sonoff/xdrv_18_armtronix_dimmers.ino | 194 + sonoff/xdrv_19_ps16dz_dimmer.ino | 244 + sonoff/xdrv_interface.ino | 24 +- sonoff/xdsp_01_lcd.ino | 12 +- sonoff/xdsp_02_ssd1306.ino | 14 +- sonoff/xdsp_03_matrix.ino | 53 +- sonoff/xdsp_04_ili9341.ino | 12 +- sonoff/xdsp_05_epaper_29.ino | 342 + sonoff/xdsp_interface.ino | 7 +- sonoff/xnrg_01_hlw8012.ino | 18 +- sonoff/xnrg_02_cse7766.ino | 10 +- sonoff/xnrg_03_pzem004t.ino | 14 +- sonoff/xnrg_05_pzem_ac.ino | 14 +- sonoff/xnrg_06_pzem_dc.ino | 14 +- sonoff/xnrg_interface.ino | 5 + sonoff/xplg_wemohue.ino | 44 +- sonoff/xplg_ws2812.ino | 18 +- sonoff/xsns_01_counter.ino | 16 +- sonoff/xsns_02_analog.ino | 94 + sonoff/xsns_04_snfsc.ino | 6 +- sonoff/xsns_05_ds18b20.ino | 16 +- sonoff/xsns_05_ds18x20.ino | 19 +- sonoff/xsns_05_ds18x20_legacy.ino | 12 +- sonoff/xsns_06_dht.ino | 10 +- sonoff/xsns_07_sht1x.ino | 16 +- sonoff/xsns_08_htu21.ino | 12 +- sonoff/xsns_09_bmp.ino | 31 +- sonoff/xsns_10_bh1750.ino | 15 +- sonoff/xsns_11_veml6070.ino | 4 +- sonoff/xsns_12_ads1115.ino | 6 +- sonoff/xsns_12_ads1115_i2cdev.ino | 6 +- sonoff/xsns_13_ina219.ino | 19 +- sonoff/xsns_14_sht3x.ino | 6 +- sonoff/xsns_15_mhz19.ino | 73 +- sonoff/xsns_16_tsl2561.ino | 10 +- sonoff/xsns_17_senseair.ino | 8 +- sonoff/xsns_18_pms5003.ino | 10 +- sonoff/xsns_19_mgs.ino | 8 +- sonoff/xsns_20_novasds.ino | 152 +- sonoff/xsns_21_sgp30.ino | 6 +- sonoff/xsns_22_sr04.ino | 112 +- sonoff/xsns_23_sdm120.ino | 98 +- sonoff/xsns_24_si1145.ino | 24 +- sonoff/xsns_25_sdm630.ino | 10 +- sonoff/xsns_26_lm75ad.ino | 4 +- sonoff/xsns_27_apds9960.ino | 103 +- sonoff/xsns_28_tm1638.ino | 14 +- sonoff/xsns_29_mcp230xx.ino | 85 +- sonoff/xsns_30_mpr121.ino | 12 +- sonoff/xsns_31_ccs811.ino | 6 +- sonoff/xsns_32_mpu6050.ino | 95 +- sonoff/xsns_33_ds3231.ino | 10 +- sonoff/xsns_34_hx711.ino | 18 +- sonoff/xsns_35_tx20.ino | 10 +- sonoff/xsns_36_mgc3130.ino | 637 ++ sonoff/xsns_37_rfsensor.ino | 669 ++ sonoff/xsns_interface.ino | 65 +- tools/decode-config.html | 295 +- tools/decode-config.md | 199 +- tools/decode-config.py | 2821 +++--- tools/decode-status.py | 18 +- .../fw_efm8bb1/RF-Bridge-EFM8BB1-20180320.hex | 406 - .../fw_efm8bb1/RF-Bridge-EFM8BB1-20180816.hex | 451 - .../fw_efm8bb1/RF-Bridge-EFM8BB1-20181023.hex | 492 - .../fw_efm8bb1/RF-Bridge-EFM8BB1-20181031.hex | 462 - .../fw_efm8bb1/RF-Bridge-EFM8BB1-20181127.hex | 506 + 402 files changed, 70118 insertions(+), 24216 deletions(-) delete mode 100644 arduino/version 2.4.0/boards.txt delete mode 100644 arduino/version 2.4.0/platform.txt delete mode 100644 arduino/version 2.4.1/boards.txt delete mode 100644 arduino/version 2.4.1/platform.txt delete mode 100644 lib/IRremoteESP8266-2.2.1.02/README.md delete mode 100644 lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md delete mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino delete mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino delete mode 100644 lib/IRremoteESP8266-2.2.1.02/keywords.txt delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRsend.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRutils.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.github/CONTRIBUTING.md (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.github/Contributors.md (91%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.github/issue_template.md (84%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.gitignore (88%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.gitmodules (85%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/.style.yapf rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.travis.yml (94%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/CPPLINT.cfg (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/LICENSE.txt (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/README.md create mode 100644 lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRGCSendDemo/IRGCSendDemo.ino (66%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRGCSendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRGCTCPServer/IRGCTCPServer.ino (89%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRGCTCPServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRMQTTServer/IRMQTTServer.ino (55%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRMQTTServer/platformio.ini (96%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRServer/IRServer.ino (88%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDemo/IRrecvDemo.ino (66%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDump/IRrecvDump.ino (96%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDump/platformio.ini (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDumpV2/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRsendDemo/IRsendDemo.ino (87%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRsendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRsendProntoDemo/IRsendProntoDemo.ino (93%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRsendProntoDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino (64%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/JVCPanasonicSendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/LGACSend/LGACSend.ino (95%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC => IRremoteESP8266-2.5.2.03/examples/LGACSend}/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnArgoAC/TurnOnArgoAC.ino (72%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC => IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC}/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino (64%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC => IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC}/platformio.ini (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC => IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC}/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino (63%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC => IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC}/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino (72%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC => IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC}/platformio.ini (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino (74%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.5.2.03/keywords.txt rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/library.json (97%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/library.properties (96%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/platformio.ini (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/pylintrc rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/CPPLINT.cfg (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/IRrecv.cpp (59%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRsend.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/IRtimer.cpp (52%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/IRtimer.h (78%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRutils.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Aiwa.cpp (76%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Argo.cpp (69%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Argo.h (51%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Denon.cpp (59%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Dish.cpp (59%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_GlobalCache.cpp (66%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_JVC.cpp (57%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Kelvinator.h (71%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_LG.h (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_NEC.cpp (53%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Pronto.cpp (81%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_RC5_RC6.cpp (70%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_RCMM.cpp (58%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Sanyo.cpp (70%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Sharp.cpp (68%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Sherwood.cpp (71%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Sony.cpp (62%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/IRrecv_test.cpp (68%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/Makefile (63%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Aiwa_test.cpp (70%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Coolix_test.cpp (60%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Denon_test.cpp (82%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Dish_test.cpp (76%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_JVC_test.cpp (76%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_LG_test.cpp (63%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_NEC_test.cpp (63%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Pronto_test.cpp (81%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_RC5_RC6_test.cpp (70%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_RCMM_test.cpp (72%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Sanyo_test.cpp (63%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Sharp_test.cpp (79%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Whynter_test.cpp (82%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/tools/Makefile (63%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp create mode 100644 lib/NewPing-1.9.1/README.md create mode 100644 lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde create mode 100644 lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde create mode 100644 lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde create mode 100644 lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde create mode 100644 lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde create mode 100644 lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde create mode 100644 lib/NewPing-1.9.1/keywords.txt create mode 100644 lib/NewPing-1.9.1/library.properties create mode 100644 lib/NewPing-1.9.1/src/NewPing.cpp create mode 100644 lib/NewPing-1.9.1/src/NewPing.h rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/README.md (100%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/examples/swsertest/swsertest.ino (100%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/keywords.txt (100%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/library.json (94%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/library.properties (94%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/src/TasmotaSerial.cpp (95%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/src/TasmotaSerial.h (95%) create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/.gitignore create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/.travis.yml create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/Arduino/epd2in9-demo/epd2in9-demo.ino create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/Arduino/libraries/readme.txt create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/LICENSE create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/Makefile create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/README.md create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/component.mk create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper-29-ws.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper-29-ws.h create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper_font.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper_fonts.h create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font16.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font20.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font8.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/imagedata.cpp create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/imagedata.h create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/Doxyfile create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/Makefile create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/README.md create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/conf.py create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/gen-dxd.py create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/index.rst create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/link-roles.py create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/repo_util.py create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/requirements.txt create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/main/README.md create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/main/component.mk create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/main/esp-epaper-29-ws.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/main/imagedata.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/main/imagedata.h create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/2.9inch_e-Paper_Datasheet.pdf create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/e-paper-and-esp-sample-image.jpg create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/e-paper-and-esp-sample-text.jpg create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/espresif-logo.bmp create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/image-conversion-setup.png create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/epd2in9.cpp create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/epd2in9.h create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/epdif.cpp create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/epdif.h create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/epdpaint.cpp create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/epdpaint.h create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/font12.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/font16.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/font20.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/font24.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/font8.c create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/src/fonts.h create mode 100644 sonoff/language/sv-SE.h create mode 100644 sonoff/support_features.ino create mode 100644 sonoff/support_rtc.ino create mode 100644 sonoff/support_wifi.ino create mode 100644 sonoff/xdrv_18_armtronix_dimmers.ino create mode 100644 sonoff/xdrv_19_ps16dz_dimmer.ino create mode 100644 sonoff/xdsp_05_epaper_29.ino create mode 100644 sonoff/xsns_02_analog.ino create mode 100644 sonoff/xsns_36_mgc3130.ino create mode 100644 sonoff/xsns_37_rfsensor.ino delete mode 100644 tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20180320.hex delete mode 100644 tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20180816.hex delete mode 100644 tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20181023.hex delete mode 100644 tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20181031.hex create mode 100644 tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20181127.hex diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2c987308c..72d1ed9b5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -66,19 +66,24 @@ Module | Description 42 Zengge WF017 | Zengge WF017 Wifi RGB(W) Led Controller 43 Sonoff Pow R2 | Sonoff Pow R2 Wifi Smart Switch with Energy Monitoring 44 Sonoff iFan02 | Sonoff iFan02 Wifi Smart Ceiling Fan with Light -45 BlitzWolf SHP2 | BlitzWolf BW-SHP2, BW-SHP6, HomeCube SP1, Gosund SP111 Wifi Smart Switch with Energy Monitoring +45 BlitzWolf SHP | BlitzWolf BW-SHP2, BW-SHP6, HomeCube SP1, Gosund SP111, Teckin SP22 Wifi Smart Switch with Energy Monitoring 46 Shelly 1 | Shelly 1 Open Source Wifi Relay Module 47 Shelly 2 | Shelly 2 Wifi 2-gang Relay Module with Energy Monitoring 48 Xiaomi Philips | Xiaomi Philips Wifi WW Led Bulb 49 Neo Coolcam | Neo Coolcam Wifi Smart Socket 50 ESP Switch | ESP Switch 4-gang Wifi Switch with Leds 51 OBI Socket | OBI Wifi Smart Socket -52 Teckin | Teckin SP20, SP22 Wifi Smart Switch with Energy Monitoring +52 Teckin | Teckin SP20 Wifi Smart Switch with Energy Monitoring 53 AplicWDP303075 | Aplic WDP 303075 CSL Wifi Smart Switch with Energy Monitoring 54 Tuya Dimmer | MIUO (and other Tuya based) Wifi Dimmer for Incandescent Lights and Led +55 Gosund SP1 v23 | Gosund SP1 v2.3 Wifi Smart Switch with Energy Monitoring +56 ARMTR Dimmer | ARMtronix Wifi dimmer for Incandescent Lights and Led +57 SK03 Outdoor | SK03 Outdoor Wifi Smart Switch with Energy Monitoring +58 PS-16-DZ | PS-16-DZ Wifi dimmer for Incandescent Lights and Led +59 Teckin US | Teckin US and ZooZee SA102 Wifi Smart Switch with Energy Monitoring ## Provided Binary Downloads -The following binary downloads have been compiled with ESP8266/Arduino library version **2.3.0** +The following binary downloads have been compiled with ESP8266/Arduino library core version **2.4.2** patched with the Alexa fix. - **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. - **sonoff-classic.bin** = The Classic version allows **initial installation** using either WifiManager, Wps or SmartConfig. @@ -88,14 +93,12 @@ The following binary downloads have been compiled with ESP8266/Arduino library v - **sonoff-display.bin** = The Display version without Wps and SmartConfig configuration but adds display support. - **sonoff-knx.bin** = The Knx version without Wps and SmartConfig configuration and some other features but adds KNX support. -See [Tasmota ESP/Arduino library version related issues](https://github.com/arendst/Sonoff-Tasmota/wiki/Theo's-Tasmota-Tips#20180523---relation-tasmota-and-esp8266arduino-core-version) why these files are still released using ESP/Arduino library version v2.3.0. - ### Available Features and Sensors | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | Remarks |--------------------------------|---------|-------|---------|--------|------|---------|-------- | ESP/Arduino lib v2.3.0 | 343k | 425k | 484k | 490k | 508k | 517k | -| ESP/Arduino lib v2.4.2 | 372k | 451k | 497k | 517k | 533k | 541k | No sleep +| ESP/Arduino lib v2.4.2 | 371k | 449k | 510k | 522k | 538k | 549k | | | | | | | | | | MY_LANGUAGE en-GB | x | x | x | x | x | x | | MQTT_LIBRARY_TYPE PUBSUBCLIENT | x | x | x | x | x | x | @@ -145,6 +148,7 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_CCS811 | - | - | - | - | - | - | | USE_MPU6050 | - | - | - | - | - | - | | USE_DS3231 | - | - | - | - | - | - | +| USE_MGC3130 | - | - | - | - | - | - | | | | | | | | | | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | | USE_SPI | - | - | - | - | - | - | @@ -173,94 +177,67 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_RF_FLASH | - | - | - | x | x | x | | USE_TX20_WIND_SENSOR | - | - | - | x | x | x | | USE_RC_SWITCH | - | - | - | x | x | x | +| USE_RF_SENSOR | - | - | - | - | - | - | | USE_DISPLAY | - | - | - | - | - | - | ## Changelog -Version 6.3.0 20181030 - * Change web Configure Module GPIO drop down list order for better readability - * Change status JSON message providing more switch and retain information - * Change xsns_17_senseair.ino to use TasmotaModbus library - * Change MCP230xx driver - * Change PubSubClient Mqtt library to non-blocking EspEasy version - * Change energy monitoring using energy sensor driver modules - * Change Webserver page handler for easier extension (thx to Adrian Scillato) - * Change pinmode for no-pullup defined switches to pullup when configured as switchmode PUSHBUTTON (=3 and up) (#3896) - * Change default OTA Url to http://thehackbox.org/tasmota/release/sonoff.bin (#4170) - * Remove support for MQTT Client esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO - * Remove commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet - * Remove restart after ntpserver change and force NTP re-sync (#3890) - * Fix showing Period Power in energy threshold messages - * Fix header file execution order by renaming user_config.h to my_user_config.h - * Fix some TSL2561 driver issues (#3681) - * Fix KNX PA exception. Regression from 6.2.1 buffer overflow caused by subStr() (#3700, #3710) - * Fix setting and getting color temperature for Philips Hue emulation (#3733) - * Fix ButtonRetain to not use default topic for clearing retain messages (#3737) - * Fix syslog when emulation is selected (#2109, #3784) - * Fix rule trigger POWER1#STATE execution after restart and SetOption0 is 0 (#3856) - * Fix Home Assistant forced light discovery (#3908) - * Fix invalid configuration restores and decode_config.py crc error when savedata = 0 (#3918) - * Fix timer offset -00:00 causing 12:00 hour offset (#3923) - * Fix I2CScan invalid JSON error message (#3925) - * Fix exception when wrong Domoticz JSON message is received (#3963) - * Fix Sonoff Bridge RfRaw receive (#4080, #4085) - * Fix possible wifi connection error (#4044, #4083) - * Fix invalid JSON floating point result from nan (Not a Number) and inf (Infinity) into null (#4147) - * Fix rule mqtt#connected trigger when mqtt is disabled (#4149) - * Add support for LCD, Matrix, TFT and Oled displays - * Add support for Neo Coolcam Wifi Smart Power Plug - * Add support for Michael Haustein ESP Switch - * Add support for MQTT Client based on lwmqtt to be selected by #define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT - * Add support for Neo Coolcam Wifi Smart Power Plug - * Add support for Michael Haustein ESP Switch - * Add support for MQTT Client based on lwmqtt to be selected by #define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT - * Add support for DS3231 Real Time Clock - * Add support for HX711 Load Cell with optional web GUI scale interface to demonstrate easy GUI plug-in - * Add support for serial 8N2 communication to TasmotaModbus and TasmotaSerial libraries - * Add support for RF transceiving using library RcSwitch (#2702) - * Add support for Shelly 1 and Shelly 2 (#2789) - * Add support for La Crosse TX20 Anemometer (#2654, #3146) - * Add support for MP3 player using DFRobot RB-DFR-562 (#3723) - * Add Support for Xiaomi-Philips Bulbs (#3787) - * Add support for PCA9685 12bit 16pin hardware PWM driver (#3866) - * Add support for EXS Relay V5.0 (#3810) - * Add support for OBI Power Socket (#1988, #3944) - * Add support for Teckin Power Socket with Energy Monitoring (#3950) - * Add support for Pzem-003/017 DC Energy monitoring module (#3694) - * Add support for Pzem-014/016 AC Energy monitoring module (#3694) - * Add support for CSL Aplic WDP 303075 Power Socket with Energy Monitoring (#3991, #3996) - * Add support for Tuya Dimmer (#469, #4075) - * Add command Display to show all settings at once - * Add command SerialSend5 to send raw serial data like "A5074100545293" - * Add command WebRefresh 1000..10000 to control web page refresh in milliseconds. Default is 2345 - * Add command WeightRes 0..3 to control display of decimals for kilogram - * Add command RGBWWTable to support color calibration (#3933) - * Add command Reset 4 (reset to defaults but keep wifi params) and Reset 5 (as reset 4 and also erase flash) (#4061) - * Add command SetOption35 0..255 (seconds) to delay mDNS initialization to control possible Wifi connect problems - * Add command SetOption52 0/1 to control display of optional time offset from UTC in JSON messages (#3629, #3711) - * Add command SetOption53 0/1 to toggle gui display of Hostname and IP address (#1006, #2091) - * Add authentication to HTTP web pages - * Add decimals as input to commands PowerSet, VoltageSet and CurrentSet - * Add tools/decode-config.py by Norbert Richter to decode configuration data. See file for information - * Add define USE_DISPLAYS for selecting image sonoff-display - * Add define USE_BASIC for selecting image sonoff-basic without most sensors - * Add auto reload of main web page to some web restarts - * Add TasmotaModbus library as very basic modbus wrapper for TasmotaSerial - * Add more API callbacks and document API.md - * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) - * Add token %hostname% to command FullTopic (#3018) - * Add Wifi channel number to state message (#3664) - * Add user configurable GPIO02 and GPIO03 on H801 devices (#3692) - * Add toggle function RGBW lights (#3695, #3697) - * Add network information to display start screen (#3704) - * Add sleep to Nova Fitness SDS01X sensor (#2841, #3724, #3749) - * Add Analog input AD0 enabled to sonoff-sensors.bin (#3756, #3757) - * Add power value below 5W to Sonoff Pow R2 and S31 (#3745) - * Add RF Receiver control to module MagicHome to be used on Arilux LC10 (#3792) - * Add userid/password option to decode-status.py (#3796) - * Add delay after restart before processing rule sensor data (#3811) - * Add force_update to Home Assistant discovery (#3873) - * Add rule triggers SWITCH1#BOOT and POWER1#BOOT (#3904, #3910) - * Add Hebrew language file (#3960) - * Add TotalStartTime to Energy JSON message (#3971) - * Add whitespace removal from RfRaw and SerialSend5 (#4020) - * Add support for two BMP/BME sensors (#4195) +Version 6.4.0 20181217 + * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40%. + In case of web page errors clear your browser cache or do Page Reload (F5 or Ctrl+R) + * Change enforcing flashmode dout but it is still mandatory + * Change bootcount update (being first) flash write to 10 seconds after restart + * Change display and epaper drivers + * Change command WebSend Host header field from IP address to hostname (#4331) + * Change log buffer size from 512 to 520 to accommodate http sensor data (#4354) + * Change default WIFI_CONFIG_TOOL from WIFI_WAIT to WIFI_RETRY in my_user_config.h (#4400) + * Change webgui refresh time delay for Save Settings and local OTA Upload (#4423) + * Change SR-04 driver to use NewPing library (#4488) + * Change MCP230xx driver to support interrupt retention over teleperiod (#4547) + * Change support for MPU6050 using DMP (#4581) + * Fix unintended function overload of WifiState + * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart + * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) + * Fix MQTT connection error after restart + * Fix wifi re-scan connection baseline + * Fix possible strncat buffer overflows + * Fix intermittent Pzem sensor energy overflow calculation error + * Fix shelly2 ghost switching caused by lack of pull-up inputs (#4255) + * Fix hardware serial pin configuration. To keep using hardware serial swap current Rx/Tx pin configuration only (#4280) + * Fix MqttRetry values above 255 seconds (#4424) + * Fix WifiManager functionality on initial installation (#4433) + * Fix ArduinoOTA for Core 2.5.0 (#4620) + * Add minutes to commands Timezone to allow all possible world timezones + * Add more strict checks for GPIO selections + * Add code image and optional commit number to version + * Add dynamic delay to main loop providing time for wifi background tasks + * Add additional start-up delay during initial wifi connection + * Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver + * Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver + * Add user definition of defines WIFI_RSSI_THRESHOLD (default 10) and WIFI_RESCAN_MINUTES (default 44) + * Add command SetOption58 0/1 to enable IR raw data info in JSON message (#2116) + * Add command IRSend \|0,\,\,.. to allow raw data transmission (#2116) + * Add command SetOption56 0/1 to enable wifi network scan and select highest RSSI (#3173) + * Add command SetOption57 0/1 to enable wifi network re-scan every 44 minutes with a rssi threshold of 10 to select highest RSSI (#3173) + * Add default sleep 1 to sonoff-basic to lower energy consumption (#4217) + * Add wifi status to Tuya (#4221) + * Add delays to reduce CPU usage at boot time (#4233) + * Add command SetOption24 0/1 to select pressure unit as hPa or mmHg (#4241) + * Add optional hardware serial when GPIO13(Rx) and GPIO15(Tx) are selected removing hardware serial from GPIO01(Tx) and GPIO03(Rx) (#4288) + * Add support for Gosund SP1 v2.3 Power Socket with Energy Monitoring (#4297) + * Add support for Armtronix dimmers. See wiki for info (#4321) + * Add to command WebSend option to send a direct path when command starts with a slash (#4329) + * Add support for LG HVac and IrRemote (#4377) + * Add initial support for Hass sensor discovery (#4380) + * Add support for Fujitsu HVac and IrRemote (#4387) + * Add support for I2C MGC3130 Electric Field Effect sensor by Christian Baars (#3774, #4404) + * Add command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) + * Add CPU average load to state message (#4431) + * Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450) + * Add support for SM Smart Wifi Dimmer PS-16-DZ (#4465) + * Add support for Teckin US Power Socket with Energy Monitoring (#4481) + * Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497) + * Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) + * Add support for GPIO02 for newer Sonoff Basic (#4518) + * Add Announce Switches to MQTT Discovery (#4531) + * Add support for SDM220 (#3610) + * Add support for Manzoku Power Strip (#4590) diff --git a/arduino/version 2.4.0/boards.txt b/arduino/version 2.4.0/boards.txt deleted file mode 100644 index 1f6d47cc6..000000000 --- a/arduino/version 2.4.0/boards.txt +++ /dev/null @@ -1,3341 +0,0 @@ -# -# this file is script-generated and is likely to be overwritten by ./tools/boards.txt.py -# - -menu.BoardModel=Model -menu.UploadSpeed=Upload Speed -menu.UploadTool=Upload Using -menu.CpuFrequency=CPU Frequency -menu.CrystalFreq=Crystal Frequency -menu.FlashSize=Flash Size -menu.FlashMode=Flash Mode -menu.FlashFreq=Flash Frequency -menu.ResetMethod=Reset Method -menu.ESPModule=Module -menu.Debug=Debug port -menu.DebugLevel=Debug Level -menu.LwIPVariant=lwIP Variant -menu.led=Builtin Led - -############################################################## -generic.name=Generic ESP8266 Module -generic.build.board=ESP8266_GENERIC -generic.upload.tool=esptool -generic.upload.maximum_data_size=81920 -generic.upload.wait_for_upload_port=true -generic.serial.disableDTR=true -generic.serial.disableRTS=true -generic.build.mcu=esp8266 -generic.build.core=esp8266 -generic.build.variant=generic -generic.build.spiffs_pagesize=256 -generic.build.debug_port= -generic.build.debug_level= - -generic.menu.UploadTool.esptool=Serial -generic.menu.UploadTool.esptool.upload.tool=esptool -generic.menu.UploadTool.esptool.upload.verbose=-vv -generic.menu.UploadTool.espupload=OTA_upload -generic.menu.UploadTool.espupload.upload.tool=espupload - -generic.menu.CpuFrequency.80=80 MHz -generic.menu.CpuFrequency.80.build.f_cpu=80000000L -generic.menu.CpuFrequency.160=160 MHz -generic.menu.CpuFrequency.160.build.f_cpu=160000000L -generic.menu.ResetMethod.ck=ck -generic.menu.ResetMethod.ck.upload.resetmethod=ck -generic.menu.ResetMethod.nodemcu=nodemcu -generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -generic.menu.CrystalFreq.26=26 MHz -generic.menu.CrystalFreq.40=40 MHz -generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -generic.menu.FlashFreq.40=40MHz -generic.menu.FlashFreq.40.build.flash_freq=40 -generic.menu.FlashFreq.80=80MHz -generic.menu.FlashFreq.80.build.flash_freq=80 -generic.menu.FlashMode.qio=QIO -generic.menu.FlashMode.qio.build.flash_mode=qio -generic.menu.FlashMode.qout=QOUT -generic.menu.FlashMode.qout.build.flash_mode=qout -generic.menu.FlashMode.dio=DIO -generic.menu.FlashMode.dio.build.flash_mode=dio -generic.menu.FlashMode.dout=DOUT -generic.menu.FlashMode.dout.build.flash_mode=dout -generic.menu.FlashSize.512K0=512K (no SPIFFS) -generic.menu.FlashSize.512K0.build.flash_size=512K -generic.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -generic.menu.FlashSize.512K0.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K0.upload.maximum_size=499696 -generic.menu.FlashSize.512K64=512K (64K SPIFFS) -generic.menu.FlashSize.512K64.build.flash_size=512K -generic.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -generic.menu.FlashSize.512K64.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K64.upload.maximum_size=434160 -generic.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -generic.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -generic.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -generic.menu.FlashSize.512K128=512K (128K SPIFFS) -generic.menu.FlashSize.512K128.build.flash_size=512K -generic.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -generic.menu.FlashSize.512K128.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K128.upload.maximum_size=368624 -generic.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -generic.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -generic.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M0=1M (no SPIFFS) -generic.menu.FlashSize.1M0.build.flash_size=1M -generic.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -generic.menu.FlashSize.1M0.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M0.upload.maximum_size=1023984 -generic.menu.FlashSize.1M64=1M (64K SPIFFS) -generic.menu.FlashSize.1M64.build.flash_size=1M -generic.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -generic.menu.FlashSize.1M64.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M64.upload.maximum_size=958448 -generic.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -generic.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M128=1M (128K SPIFFS) -generic.menu.FlashSize.1M128.build.flash_size=1M -generic.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -generic.menu.FlashSize.1M128.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M128.upload.maximum_size=892912 -generic.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -generic.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M144=1M (144K SPIFFS) -generic.menu.FlashSize.1M144.build.flash_size=1M -generic.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -generic.menu.FlashSize.1M144.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M144.upload.maximum_size=876528 -generic.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -generic.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M160=1M (160K SPIFFS) -generic.menu.FlashSize.1M160.build.flash_size=1M -generic.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -generic.menu.FlashSize.1M160.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M160.upload.maximum_size=860144 -generic.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -generic.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M192=1M (192K SPIFFS) -generic.menu.FlashSize.1M192.build.flash_size=1M -generic.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -generic.menu.FlashSize.1M192.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M192.upload.maximum_size=827376 -generic.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -generic.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M256=1M (256K SPIFFS) -generic.menu.FlashSize.1M256.build.flash_size=1M -generic.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -generic.menu.FlashSize.1M256.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M256.upload.maximum_size=761840 -generic.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -generic.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M512=1M (512K SPIFFS) -generic.menu.FlashSize.1M512.build.flash_size=1M -generic.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -generic.menu.FlashSize.1M512.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M512.upload.maximum_size=499696 -generic.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -generic.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -generic.menu.FlashSize.2M=2M (1M SPIFFS) -generic.menu.FlashSize.2M.build.flash_size=2M -generic.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -generic.menu.FlashSize.2M.build.spiffs_pagesize=256 -generic.menu.FlashSize.2M.upload.maximum_size=1044464 -generic.menu.FlashSize.2M.build.spiffs_start=0x100000 -generic.menu.FlashSize.2M.build.spiffs_end=0x1FB000 -generic.menu.FlashSize.2M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.4M1M=4M (1M SPIFFS) -generic.menu.FlashSize.4M1M.build.flash_size=4M -generic.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -generic.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -generic.menu.FlashSize.4M1M.upload.maximum_size=1044464 -generic.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -generic.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -generic.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.4M3M=4M (3M SPIFFS) -generic.menu.FlashSize.4M3M.build.flash_size=4M -generic.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -generic.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -generic.menu.FlashSize.4M3M.upload.maximum_size=1044464 -generic.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -generic.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -generic.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.8M7M=8M (7M SPIFFS) -generic.menu.FlashSize.8M7M.build.flash_size=8M -generic.menu.FlashSize.8M7M.build.flash_ld=eagle.flash.8m.ld -generic.menu.FlashSize.8M7M.build.spiffs_pagesize=256 -generic.menu.FlashSize.8M7M.upload.maximum_size=1044464 -generic.menu.FlashSize.8M7M.build.spiffs_start=0x100000 -generic.menu.FlashSize.8M7M.build.spiffs_end=0x7FB000 -generic.menu.FlashSize.8M7M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.16M15M=16M (15M SPIFFS) -generic.menu.FlashSize.16M15M.build.flash_size=16M -generic.menu.FlashSize.16M15M.build.flash_ld=eagle.flash.16m.ld -generic.menu.FlashSize.16M15M.build.spiffs_pagesize=256 -generic.menu.FlashSize.16M15M.upload.maximum_size=1044464 -generic.menu.FlashSize.16M15M.build.spiffs_start=0x100000 -generic.menu.FlashSize.16M15M.build.spiffs_end=0xFFB000 -generic.menu.FlashSize.16M15M.build.spiffs_blocksize=8192 -generic.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -generic.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -generic.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -generic.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -generic.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -generic.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -generic.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -generic.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -generic.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -generic.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -generic.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.LwIPVariant.OpenSource=v1.4 Open Source -generic.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -generic.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -generic.menu.Debug.Disabled=Disabled -generic.menu.Debug.Disabled.build.debug_port= -generic.menu.Debug.Serial=Serial -generic.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -generic.menu.Debug.Serial1=Serial1 -generic.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -generic.menu.DebugLevel.None____=None -generic.menu.DebugLevel.None____.build.debug_level= -generic.menu.DebugLevel.SSL=SSL -generic.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -generic.menu.DebugLevel.TLS_MEM=TLS_MEM -generic.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -generic.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -generic.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -generic.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -generic.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -generic.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -generic.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -generic.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.CORE=CORE -generic.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -generic.menu.DebugLevel.WIFI=WIFI -generic.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -generic.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -generic.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -generic.menu.DebugLevel.UPDATER=UPDATER -generic.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -generic.menu.DebugLevel.OTA=OTA -generic.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -generic.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -generic.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -generic.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -generic.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -generic.menu.UploadSpeed.115200=115200 -generic.menu.UploadSpeed.115200.upload.speed=115200 -generic.menu.UploadSpeed.9600=9600 -generic.menu.UploadSpeed.9600.upload.speed=9600 -generic.menu.UploadSpeed.57600=57600 -generic.menu.UploadSpeed.57600.upload.speed=57600 -generic.menu.UploadSpeed.230400.linux=230400 -generic.menu.UploadSpeed.230400.macosx=230400 -generic.menu.UploadSpeed.230400.upload.speed=230400 -generic.menu.UploadSpeed.256000.windows=256000 -generic.menu.UploadSpeed.256000.upload.speed=256000 -generic.menu.UploadSpeed.460800.linux=460800 -generic.menu.UploadSpeed.460800.macosx=460800 -generic.menu.UploadSpeed.460800.upload.speed=460800 -generic.menu.UploadSpeed.512000.windows=512000 -generic.menu.UploadSpeed.512000.upload.speed=512000 -generic.menu.UploadSpeed.921600=921600 -generic.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -esp8285.name=Generic ESP8285 Module -esp8285.build.board=ESP8266_ESP01 -esp8285.upload.tool=esptool -esp8285.upload.maximum_data_size=81920 -esp8285.upload.wait_for_upload_port=true -esp8285.serial.disableDTR=true -esp8285.serial.disableRTS=true -esp8285.build.mcu=esp8266 -esp8285.build.core=esp8266 -esp8285.build.variant=generic -esp8285.build.spiffs_pagesize=256 -esp8285.build.debug_port= -esp8285.build.debug_level= -esp8285.menu.CpuFrequency.80=80 MHz -esp8285.menu.CpuFrequency.80.build.f_cpu=80000000L -esp8285.menu.CpuFrequency.160=160 MHz -esp8285.menu.CpuFrequency.160.build.f_cpu=160000000L -esp8285.menu.ResetMethod.ck=ck -esp8285.menu.ResetMethod.ck.upload.resetmethod=ck -esp8285.menu.ResetMethod.nodemcu=nodemcu -esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -esp8285.menu.CrystalFreq.26=26 MHz -esp8285.menu.CrystalFreq.40=40 MHz -esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -esp8285.build.flash_mode=dout -esp8285.build.flash_freq=40 -esp8285.menu.FlashSize.1M0=1M (no SPIFFS) -esp8285.menu.FlashSize.1M0.build.flash_size=1M -esp8285.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -esp8285.menu.FlashSize.1M0.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M0.upload.maximum_size=1023984 -esp8285.menu.FlashSize.1M64=1M (64K SPIFFS) -esp8285.menu.FlashSize.1M64.build.flash_size=1M -esp8285.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -esp8285.menu.FlashSize.1M64.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M64.upload.maximum_size=958448 -esp8285.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -esp8285.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M128=1M (128K SPIFFS) -esp8285.menu.FlashSize.1M128.build.flash_size=1M -esp8285.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -esp8285.menu.FlashSize.1M128.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M128.upload.maximum_size=892912 -esp8285.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -esp8285.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M144=1M (144K SPIFFS) -esp8285.menu.FlashSize.1M144.build.flash_size=1M -esp8285.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -esp8285.menu.FlashSize.1M144.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M144.upload.maximum_size=876528 -esp8285.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -esp8285.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M160=1M (160K SPIFFS) -esp8285.menu.FlashSize.1M160.build.flash_size=1M -esp8285.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -esp8285.menu.FlashSize.1M160.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M160.upload.maximum_size=860144 -esp8285.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -esp8285.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M192=1M (192K SPIFFS) -esp8285.menu.FlashSize.1M192.build.flash_size=1M -esp8285.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -esp8285.menu.FlashSize.1M192.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M192.upload.maximum_size=827376 -esp8285.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -esp8285.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M256=1M (256K SPIFFS) -esp8285.menu.FlashSize.1M256.build.flash_size=1M -esp8285.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -esp8285.menu.FlashSize.1M256.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M256.upload.maximum_size=761840 -esp8285.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -esp8285.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M512=1M (512K SPIFFS) -esp8285.menu.FlashSize.1M512.build.flash_size=1M -esp8285.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -esp8285.menu.FlashSize.1M512.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M512.upload.maximum_size=499696 -esp8285.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -esp8285.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -esp8285.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -esp8285.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -esp8285.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -esp8285.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -esp8285.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -esp8285.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -esp8285.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -esp8285.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -esp8285.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -esp8285.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -esp8285.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.LwIPVariant.OpenSource=v1.4 Open Source -esp8285.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -esp8285.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp8285.menu.Debug.Disabled=Disabled -esp8285.menu.Debug.Disabled.build.debug_port= -esp8285.menu.Debug.Serial=Serial -esp8285.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp8285.menu.Debug.Serial1=Serial1 -esp8285.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp8285.menu.DebugLevel.None____=None -esp8285.menu.DebugLevel.None____.build.debug_level= -esp8285.menu.DebugLevel.SSL=SSL -esp8285.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp8285.menu.DebugLevel.TLS_MEM=TLS_MEM -esp8285.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp8285.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -esp8285.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -esp8285.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -esp8285.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp8285.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp8285.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp8285.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.CORE=CORE -esp8285.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp8285.menu.DebugLevel.WIFI=WIFI -esp8285.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp8285.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -esp8285.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp8285.menu.DebugLevel.UPDATER=UPDATER -esp8285.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp8285.menu.DebugLevel.OTA=OTA -esp8285.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp8285.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -esp8285.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -esp8285.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -esp8285.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp8285.menu.UploadSpeed.115200=115200 -esp8285.menu.UploadSpeed.115200.upload.speed=115200 -esp8285.menu.UploadSpeed.9600=9600 -esp8285.menu.UploadSpeed.9600.upload.speed=9600 -esp8285.menu.UploadSpeed.57600=57600 -esp8285.menu.UploadSpeed.57600.upload.speed=57600 -esp8285.menu.UploadSpeed.230400.linux=230400 -esp8285.menu.UploadSpeed.230400.macosx=230400 -esp8285.menu.UploadSpeed.230400.upload.speed=230400 -esp8285.menu.UploadSpeed.256000.windows=256000 -esp8285.menu.UploadSpeed.256000.upload.speed=256000 -esp8285.menu.UploadSpeed.460800.linux=460800 -esp8285.menu.UploadSpeed.460800.macosx=460800 -esp8285.menu.UploadSpeed.460800.upload.speed=460800 -esp8285.menu.UploadSpeed.512000.windows=512000 -esp8285.menu.UploadSpeed.512000.upload.speed=512000 -esp8285.menu.UploadSpeed.921600=921600 -esp8285.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espduino.name=ESPDuino (ESP-13 Module) -espduino.build.board=ESP8266_ESP13 -espduino.build.variant=ESPDuino -espduino.menu.ResetMethod.v2=ESPduino-V2 -espduino.menu.ResetMethod.v2.upload.resetmethod=nodemcu -espduino.menu.ResetMethod.v1=ESPduino-V1 -espduino.menu.ResetMethod.v1.upload.resetmethod=ck -espduino.menu.UploadTool.esptool=Serial -espduino.menu.UploadTool.esptool.upload.tool=esptool -espduino.menu.UploadTool.esptool.upload.verbose=-vv -espduino.menu.UploadTool.espota=OTA -espduino.menu.UploadTool.espota.upload.tool=espota -espduino.upload.tool=esptool -espduino.upload.maximum_data_size=81920 -espduino.upload.wait_for_upload_port=true -espduino.serial.disableDTR=true -espduino.serial.disableRTS=true -espduino.build.mcu=esp8266 -espduino.build.core=esp8266 -espduino.build.spiffs_pagesize=256 -espduino.build.debug_port= -espduino.build.debug_level= -espduino.menu.CpuFrequency.80=80 MHz -espduino.menu.CpuFrequency.80.build.f_cpu=80000000L -espduino.menu.CpuFrequency.160=160 MHz -espduino.menu.CpuFrequency.160.build.f_cpu=160000000L -espduino.build.flash_mode=dio -espduino.build.flash_freq=40 -espduino.menu.FlashSize.4M1M=4M (1M SPIFFS) -espduino.menu.FlashSize.4M1M.build.flash_size=4M -espduino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espduino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espduino.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espduino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espduino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espduino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espduino.menu.FlashSize.4M3M=4M (3M SPIFFS) -espduino.menu.FlashSize.4M3M.build.flash_size=4M -espduino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espduino.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espduino.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espduino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espduino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espduino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espduino.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -espduino.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espduino.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espduino.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espduino.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -espduino.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espduino.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espduino.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espduino.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -espduino.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espduino.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.LwIPVariant.OpenSource=v1.4 Open Source -espduino.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espduino.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espduino.menu.Debug.Disabled=Disabled -espduino.menu.Debug.Disabled.build.debug_port= -espduino.menu.Debug.Serial=Serial -espduino.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espduino.menu.Debug.Serial1=Serial1 -espduino.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espduino.menu.DebugLevel.None____=None -espduino.menu.DebugLevel.None____.build.debug_level= -espduino.menu.DebugLevel.SSL=SSL -espduino.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espduino.menu.DebugLevel.TLS_MEM=TLS_MEM -espduino.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espduino.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espduino.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espduino.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espduino.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espduino.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espduino.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espduino.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.CORE=CORE -espduino.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espduino.menu.DebugLevel.WIFI=WIFI -espduino.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espduino.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espduino.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espduino.menu.DebugLevel.UPDATER=UPDATER -espduino.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espduino.menu.DebugLevel.OTA=OTA -espduino.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espduino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espduino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espduino.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espduino.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espduino.menu.UploadSpeed.115200=115200 -espduino.menu.UploadSpeed.115200.upload.speed=115200 -espduino.menu.UploadSpeed.9600=9600 -espduino.menu.UploadSpeed.9600.upload.speed=9600 -espduino.menu.UploadSpeed.57600=57600 -espduino.menu.UploadSpeed.57600.upload.speed=57600 -espduino.menu.UploadSpeed.230400.linux=230400 -espduino.menu.UploadSpeed.230400.macosx=230400 -espduino.menu.UploadSpeed.230400.upload.speed=230400 -espduino.menu.UploadSpeed.256000.windows=256000 -espduino.menu.UploadSpeed.256000.upload.speed=256000 -espduino.menu.UploadSpeed.460800.linux=460800 -espduino.menu.UploadSpeed.460800.macosx=460800 -espduino.menu.UploadSpeed.460800.upload.speed=460800 -espduino.menu.UploadSpeed.512000.windows=512000 -espduino.menu.UploadSpeed.512000.upload.speed=512000 -espduino.menu.UploadSpeed.921600=921600 -espduino.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -huzzah.name=Adafruit HUZZAH ESP8266 -huzzah.build.board=ESP8266_ESP12 -huzzah.build.variant=adafruit -huzzah.upload.tool=esptool -huzzah.upload.maximum_data_size=81920 -huzzah.upload.wait_for_upload_port=true -huzzah.serial.disableDTR=true -huzzah.serial.disableRTS=true -huzzah.build.mcu=esp8266 -huzzah.build.core=esp8266 -huzzah.build.spiffs_pagesize=256 -huzzah.build.debug_port= -huzzah.build.debug_level= -huzzah.menu.CpuFrequency.80=80 MHz -huzzah.menu.CpuFrequency.80.build.f_cpu=80000000L -huzzah.menu.CpuFrequency.160=160 MHz -huzzah.menu.CpuFrequency.160.build.f_cpu=160000000L -huzzah.upload.resetmethod=nodemcu -huzzah.build.flash_mode=qio -huzzah.build.flash_freq=40 -huzzah.menu.FlashSize.4M1M=4M (1M SPIFFS) -huzzah.menu.FlashSize.4M1M.build.flash_size=4M -huzzah.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -huzzah.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -huzzah.menu.FlashSize.4M1M.upload.maximum_size=1044464 -huzzah.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -huzzah.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -huzzah.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -huzzah.menu.FlashSize.4M3M=4M (3M SPIFFS) -huzzah.menu.FlashSize.4M3M.build.flash_size=4M -huzzah.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -huzzah.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -huzzah.menu.FlashSize.4M3M.upload.maximum_size=1044464 -huzzah.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -huzzah.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -huzzah.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -huzzah.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -huzzah.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -huzzah.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -huzzah.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -huzzah.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -huzzah.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -huzzah.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -huzzah.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -huzzah.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -huzzah.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -huzzah.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.LwIPVariant.OpenSource=v1.4 Open Source -huzzah.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -huzzah.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -huzzah.menu.Debug.Disabled=Disabled -huzzah.menu.Debug.Disabled.build.debug_port= -huzzah.menu.Debug.Serial=Serial -huzzah.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -huzzah.menu.Debug.Serial1=Serial1 -huzzah.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -huzzah.menu.DebugLevel.None____=None -huzzah.menu.DebugLevel.None____.build.debug_level= -huzzah.menu.DebugLevel.SSL=SSL -huzzah.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -huzzah.menu.DebugLevel.TLS_MEM=TLS_MEM -huzzah.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -huzzah.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -huzzah.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -huzzah.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -huzzah.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -huzzah.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -huzzah.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -huzzah.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.CORE=CORE -huzzah.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -huzzah.menu.DebugLevel.WIFI=WIFI -huzzah.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -huzzah.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -huzzah.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -huzzah.menu.DebugLevel.UPDATER=UPDATER -huzzah.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -huzzah.menu.DebugLevel.OTA=OTA -huzzah.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -huzzah.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -huzzah.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -huzzah.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -huzzah.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -huzzah.menu.UploadSpeed.115200=115200 -huzzah.menu.UploadSpeed.115200.upload.speed=115200 -huzzah.menu.UploadSpeed.9600=9600 -huzzah.menu.UploadSpeed.9600.upload.speed=9600 -huzzah.menu.UploadSpeed.57600=57600 -huzzah.menu.UploadSpeed.57600.upload.speed=57600 -huzzah.menu.UploadSpeed.230400.linux=230400 -huzzah.menu.UploadSpeed.230400.macosx=230400 -huzzah.menu.UploadSpeed.230400.upload.speed=230400 -huzzah.menu.UploadSpeed.256000.windows=256000 -huzzah.menu.UploadSpeed.256000.upload.speed=256000 -huzzah.menu.UploadSpeed.460800.linux=460800 -huzzah.menu.UploadSpeed.460800.macosx=460800 -huzzah.menu.UploadSpeed.460800.upload.speed=460800 -huzzah.menu.UploadSpeed.512000.windows=512000 -huzzah.menu.UploadSpeed.512000.upload.speed=512000 -huzzah.menu.UploadSpeed.921600=921600 -huzzah.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espresso_lite_v1.name=ESPresso Lite 1.0 -espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 -espresso_lite_v1.build.variant=espresso_lite_v1 -espresso_lite_v1.upload.tool=esptool -espresso_lite_v1.upload.maximum_data_size=81920 -espresso_lite_v1.upload.wait_for_upload_port=true -espresso_lite_v1.serial.disableDTR=true -espresso_lite_v1.serial.disableRTS=true -espresso_lite_v1.build.mcu=esp8266 -espresso_lite_v1.build.core=esp8266 -espresso_lite_v1.build.spiffs_pagesize=256 -espresso_lite_v1.build.debug_port= -espresso_lite_v1.build.debug_level= -espresso_lite_v1.menu.CpuFrequency.80=80 MHz -espresso_lite_v1.menu.CpuFrequency.80.build.f_cpu=80000000L -espresso_lite_v1.menu.CpuFrequency.160=160 MHz -espresso_lite_v1.menu.CpuFrequency.160.build.f_cpu=160000000L -espresso_lite_v1.build.flash_mode=dio -espresso_lite_v1.build.flash_freq=40 -espresso_lite_v1.menu.FlashSize.4M1M=4M (1M SPIFFS) -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_size=4M -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.FlashSize.4M3M=4M (3M SPIFFS) -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_size=4M -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.ResetMethod.ck=ck -espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v1.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -espresso_lite_v1.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espresso_lite_v1.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espresso_lite_v1.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espresso_lite_v1.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -espresso_lite_v1.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espresso_lite_v1.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espresso_lite_v1.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espresso_lite_v1.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -espresso_lite_v1.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espresso_lite_v1.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.LwIPVariant.OpenSource=v1.4 Open Source -espresso_lite_v1.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espresso_lite_v1.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v1.menu.Debug.Disabled=Disabled -espresso_lite_v1.menu.Debug.Disabled.build.debug_port= -espresso_lite_v1.menu.Debug.Serial=Serial -espresso_lite_v1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v1.menu.Debug.Serial1=Serial1 -espresso_lite_v1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v1.menu.DebugLevel.None____=None -espresso_lite_v1.menu.DebugLevel.None____.build.debug_level= -espresso_lite_v1.menu.DebugLevel.SSL=SSL -espresso_lite_v1.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v1.menu.DebugLevel.TLS_MEM=TLS_MEM -espresso_lite_v1.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.CORE=CORE -espresso_lite_v1.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v1.menu.DebugLevel.WIFI=WIFI -espresso_lite_v1.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v1.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v1.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v1.menu.DebugLevel.UPDATER=UPDATER -espresso_lite_v1.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v1.menu.DebugLevel.OTA=OTA -espresso_lite_v1.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espresso_lite_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espresso_lite_v1.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v1.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v1.menu.UploadSpeed.115200=115200 -espresso_lite_v1.menu.UploadSpeed.115200.upload.speed=115200 -espresso_lite_v1.menu.UploadSpeed.9600=9600 -espresso_lite_v1.menu.UploadSpeed.9600.upload.speed=9600 -espresso_lite_v1.menu.UploadSpeed.57600=57600 -espresso_lite_v1.menu.UploadSpeed.57600.upload.speed=57600 -espresso_lite_v1.menu.UploadSpeed.230400.linux=230400 -espresso_lite_v1.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v1.menu.UploadSpeed.230400.upload.speed=230400 -espresso_lite_v1.menu.UploadSpeed.256000.windows=256000 -espresso_lite_v1.menu.UploadSpeed.256000.upload.speed=256000 -espresso_lite_v1.menu.UploadSpeed.460800.linux=460800 -espresso_lite_v1.menu.UploadSpeed.460800.macosx=460800 -espresso_lite_v1.menu.UploadSpeed.460800.upload.speed=460800 -espresso_lite_v1.menu.UploadSpeed.512000.windows=512000 -espresso_lite_v1.menu.UploadSpeed.512000.upload.speed=512000 -espresso_lite_v1.menu.UploadSpeed.921600=921600 -espresso_lite_v1.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espresso_lite_v2.name=ESPresso Lite 2.0 -espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 -espresso_lite_v2.build.variant=espresso_lite_v2 -espresso_lite_v2.upload.tool=esptool -espresso_lite_v2.upload.maximum_data_size=81920 -espresso_lite_v2.upload.wait_for_upload_port=true -espresso_lite_v2.serial.disableDTR=true -espresso_lite_v2.serial.disableRTS=true -espresso_lite_v2.build.mcu=esp8266 -espresso_lite_v2.build.core=esp8266 -espresso_lite_v2.build.spiffs_pagesize=256 -espresso_lite_v2.build.debug_port= -espresso_lite_v2.build.debug_level= -espresso_lite_v2.menu.CpuFrequency.80=80 MHz -espresso_lite_v2.menu.CpuFrequency.80.build.f_cpu=80000000L -espresso_lite_v2.menu.CpuFrequency.160=160 MHz -espresso_lite_v2.menu.CpuFrequency.160.build.f_cpu=160000000L -espresso_lite_v2.build.flash_mode=dio -espresso_lite_v2.build.flash_freq=40 -espresso_lite_v2.menu.FlashSize.4M1M=4M (1M SPIFFS) -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_size=4M -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.FlashSize.4M3M=4M (3M SPIFFS) -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_size=4M -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.ResetMethod.ck=ck -espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v2.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -espresso_lite_v2.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espresso_lite_v2.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espresso_lite_v2.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espresso_lite_v2.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -espresso_lite_v2.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espresso_lite_v2.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espresso_lite_v2.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espresso_lite_v2.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -espresso_lite_v2.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espresso_lite_v2.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.LwIPVariant.OpenSource=v1.4 Open Source -espresso_lite_v2.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espresso_lite_v2.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v2.menu.Debug.Disabled=Disabled -espresso_lite_v2.menu.Debug.Disabled.build.debug_port= -espresso_lite_v2.menu.Debug.Serial=Serial -espresso_lite_v2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v2.menu.Debug.Serial1=Serial1 -espresso_lite_v2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v2.menu.DebugLevel.None____=None -espresso_lite_v2.menu.DebugLevel.None____.build.debug_level= -espresso_lite_v2.menu.DebugLevel.SSL=SSL -espresso_lite_v2.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v2.menu.DebugLevel.TLS_MEM=TLS_MEM -espresso_lite_v2.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.CORE=CORE -espresso_lite_v2.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v2.menu.DebugLevel.WIFI=WIFI -espresso_lite_v2.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v2.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v2.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v2.menu.DebugLevel.UPDATER=UPDATER -espresso_lite_v2.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v2.menu.DebugLevel.OTA=OTA -espresso_lite_v2.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espresso_lite_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espresso_lite_v2.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v2.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v2.menu.UploadSpeed.115200=115200 -espresso_lite_v2.menu.UploadSpeed.115200.upload.speed=115200 -espresso_lite_v2.menu.UploadSpeed.9600=9600 -espresso_lite_v2.menu.UploadSpeed.9600.upload.speed=9600 -espresso_lite_v2.menu.UploadSpeed.57600=57600 -espresso_lite_v2.menu.UploadSpeed.57600.upload.speed=57600 -espresso_lite_v2.menu.UploadSpeed.230400.linux=230400 -espresso_lite_v2.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v2.menu.UploadSpeed.230400.upload.speed=230400 -espresso_lite_v2.menu.UploadSpeed.256000.windows=256000 -espresso_lite_v2.menu.UploadSpeed.256000.upload.speed=256000 -espresso_lite_v2.menu.UploadSpeed.460800.linux=460800 -espresso_lite_v2.menu.UploadSpeed.460800.macosx=460800 -espresso_lite_v2.menu.UploadSpeed.460800.upload.speed=460800 -espresso_lite_v2.menu.UploadSpeed.512000.windows=512000 -espresso_lite_v2.menu.UploadSpeed.512000.upload.speed=512000 -espresso_lite_v2.menu.UploadSpeed.921600=921600 -espresso_lite_v2.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -phoenix_v1.name=Phoenix 1.0 -phoenix_v1.build.board=ESP8266_PHOENIX_V1 -phoenix_v1.build.variant=phoenix_v1 -phoenix_v1.upload.tool=esptool -phoenix_v1.upload.maximum_data_size=81920 -phoenix_v1.upload.wait_for_upload_port=true -phoenix_v1.serial.disableDTR=true -phoenix_v1.serial.disableRTS=true -phoenix_v1.build.mcu=esp8266 -phoenix_v1.build.core=esp8266 -phoenix_v1.build.spiffs_pagesize=256 -phoenix_v1.build.debug_port= -phoenix_v1.build.debug_level= -phoenix_v1.menu.CpuFrequency.80=80 MHz -phoenix_v1.menu.CpuFrequency.80.build.f_cpu=80000000L -phoenix_v1.menu.CpuFrequency.160=160 MHz -phoenix_v1.menu.CpuFrequency.160.build.f_cpu=160000000L -phoenix_v1.build.flash_mode=dio -phoenix_v1.build.flash_freq=40 -phoenix_v1.menu.FlashSize.4M1M=4M (1M SPIFFS) -phoenix_v1.menu.FlashSize.4M1M.build.flash_size=4M -phoenix_v1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -phoenix_v1.menu.FlashSize.4M1M.upload.maximum_size=1044464 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -phoenix_v1.menu.FlashSize.4M3M=4M (3M SPIFFS) -phoenix_v1.menu.FlashSize.4M3M.build.flash_size=4M -phoenix_v1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -phoenix_v1.menu.FlashSize.4M3M.upload.maximum_size=1044464 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -phoenix_v1.menu.ResetMethod.ck=ck -phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v1.menu.ResetMethod.nodemcu=nodemcu -phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v1.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -phoenix_v1.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -phoenix_v1.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -phoenix_v1.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -phoenix_v1.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -phoenix_v1.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -phoenix_v1.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -phoenix_v1.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -phoenix_v1.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -phoenix_v1.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -phoenix_v1.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.LwIPVariant.OpenSource=v1.4 Open Source -phoenix_v1.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -phoenix_v1.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v1.menu.Debug.Disabled=Disabled -phoenix_v1.menu.Debug.Disabled.build.debug_port= -phoenix_v1.menu.Debug.Serial=Serial -phoenix_v1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v1.menu.Debug.Serial1=Serial1 -phoenix_v1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v1.menu.DebugLevel.None____=None -phoenix_v1.menu.DebugLevel.None____.build.debug_level= -phoenix_v1.menu.DebugLevel.SSL=SSL -phoenix_v1.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v1.menu.DebugLevel.TLS_MEM=TLS_MEM -phoenix_v1.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -phoenix_v1.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -phoenix_v1.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v1.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.CORE=CORE -phoenix_v1.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v1.menu.DebugLevel.WIFI=WIFI -phoenix_v1.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v1.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -phoenix_v1.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v1.menu.DebugLevel.UPDATER=UPDATER -phoenix_v1.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v1.menu.DebugLevel.OTA=OTA -phoenix_v1.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -phoenix_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -phoenix_v1.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v1.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v1.menu.UploadSpeed.115200=115200 -phoenix_v1.menu.UploadSpeed.115200.upload.speed=115200 -phoenix_v1.menu.UploadSpeed.9600=9600 -phoenix_v1.menu.UploadSpeed.9600.upload.speed=9600 -phoenix_v1.menu.UploadSpeed.57600=57600 -phoenix_v1.menu.UploadSpeed.57600.upload.speed=57600 -phoenix_v1.menu.UploadSpeed.230400.linux=230400 -phoenix_v1.menu.UploadSpeed.230400.macosx=230400 -phoenix_v1.menu.UploadSpeed.230400.upload.speed=230400 -phoenix_v1.menu.UploadSpeed.256000.windows=256000 -phoenix_v1.menu.UploadSpeed.256000.upload.speed=256000 -phoenix_v1.menu.UploadSpeed.460800.linux=460800 -phoenix_v1.menu.UploadSpeed.460800.macosx=460800 -phoenix_v1.menu.UploadSpeed.460800.upload.speed=460800 -phoenix_v1.menu.UploadSpeed.512000.windows=512000 -phoenix_v1.menu.UploadSpeed.512000.upload.speed=512000 -phoenix_v1.menu.UploadSpeed.921600=921600 -phoenix_v1.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -phoenix_v2.name=Phoenix 2.0 -phoenix_v2.build.board=ESP8266_PHOENIX_V2 -phoenix_v2.build.variant=phoenix_v2 -phoenix_v2.upload.tool=esptool -phoenix_v2.upload.maximum_data_size=81920 -phoenix_v2.upload.wait_for_upload_port=true -phoenix_v2.serial.disableDTR=true -phoenix_v2.serial.disableRTS=true -phoenix_v2.build.mcu=esp8266 -phoenix_v2.build.core=esp8266 -phoenix_v2.build.spiffs_pagesize=256 -phoenix_v2.build.debug_port= -phoenix_v2.build.debug_level= -phoenix_v2.menu.CpuFrequency.80=80 MHz -phoenix_v2.menu.CpuFrequency.80.build.f_cpu=80000000L -phoenix_v2.menu.CpuFrequency.160=160 MHz -phoenix_v2.menu.CpuFrequency.160.build.f_cpu=160000000L -phoenix_v2.build.flash_mode=dio -phoenix_v2.build.flash_freq=40 -phoenix_v2.menu.FlashSize.4M1M=4M (1M SPIFFS) -phoenix_v2.menu.FlashSize.4M1M.build.flash_size=4M -phoenix_v2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -phoenix_v2.menu.FlashSize.4M1M.upload.maximum_size=1044464 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -phoenix_v2.menu.FlashSize.4M3M=4M (3M SPIFFS) -phoenix_v2.menu.FlashSize.4M3M.build.flash_size=4M -phoenix_v2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -phoenix_v2.menu.FlashSize.4M3M.upload.maximum_size=1044464 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -phoenix_v2.menu.ResetMethod.ck=ck -phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v2.menu.ResetMethod.nodemcu=nodemcu -phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v2.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -phoenix_v2.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -phoenix_v2.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -phoenix_v2.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -phoenix_v2.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -phoenix_v2.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -phoenix_v2.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -phoenix_v2.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -phoenix_v2.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -phoenix_v2.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -phoenix_v2.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.LwIPVariant.OpenSource=v1.4 Open Source -phoenix_v2.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -phoenix_v2.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v2.menu.Debug.Disabled=Disabled -phoenix_v2.menu.Debug.Disabled.build.debug_port= -phoenix_v2.menu.Debug.Serial=Serial -phoenix_v2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v2.menu.Debug.Serial1=Serial1 -phoenix_v2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v2.menu.DebugLevel.None____=None -phoenix_v2.menu.DebugLevel.None____.build.debug_level= -phoenix_v2.menu.DebugLevel.SSL=SSL -phoenix_v2.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v2.menu.DebugLevel.TLS_MEM=TLS_MEM -phoenix_v2.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -phoenix_v2.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -phoenix_v2.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v2.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.CORE=CORE -phoenix_v2.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v2.menu.DebugLevel.WIFI=WIFI -phoenix_v2.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v2.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -phoenix_v2.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v2.menu.DebugLevel.UPDATER=UPDATER -phoenix_v2.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v2.menu.DebugLevel.OTA=OTA -phoenix_v2.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -phoenix_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -phoenix_v2.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v2.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v2.menu.UploadSpeed.115200=115200 -phoenix_v2.menu.UploadSpeed.115200.upload.speed=115200 -phoenix_v2.menu.UploadSpeed.9600=9600 -phoenix_v2.menu.UploadSpeed.9600.upload.speed=9600 -phoenix_v2.menu.UploadSpeed.57600=57600 -phoenix_v2.menu.UploadSpeed.57600.upload.speed=57600 -phoenix_v2.menu.UploadSpeed.230400.linux=230400 -phoenix_v2.menu.UploadSpeed.230400.macosx=230400 -phoenix_v2.menu.UploadSpeed.230400.upload.speed=230400 -phoenix_v2.menu.UploadSpeed.256000.windows=256000 -phoenix_v2.menu.UploadSpeed.256000.upload.speed=256000 -phoenix_v2.menu.UploadSpeed.460800.linux=460800 -phoenix_v2.menu.UploadSpeed.460800.macosx=460800 -phoenix_v2.menu.UploadSpeed.460800.upload.speed=460800 -phoenix_v2.menu.UploadSpeed.512000.windows=512000 -phoenix_v2.menu.UploadSpeed.512000.upload.speed=512000 -phoenix_v2.menu.UploadSpeed.921600=921600 -phoenix_v2.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -nodemcu.name=NodeMCU 0.9 (ESP-12 Module) -nodemcu.build.board=ESP8266_NODEMCU -nodemcu.build.variant=nodemcu -nodemcu.upload.tool=esptool -nodemcu.upload.maximum_data_size=81920 -nodemcu.upload.wait_for_upload_port=true -nodemcu.serial.disableDTR=true -nodemcu.serial.disableRTS=true -nodemcu.build.mcu=esp8266 -nodemcu.build.core=esp8266 -nodemcu.build.spiffs_pagesize=256 -nodemcu.build.debug_port= -nodemcu.build.debug_level= -nodemcu.menu.CpuFrequency.80=80 MHz -nodemcu.menu.CpuFrequency.80.build.f_cpu=80000000L -nodemcu.menu.CpuFrequency.160=160 MHz -nodemcu.menu.CpuFrequency.160.build.f_cpu=160000000L -nodemcu.upload.resetmethod=nodemcu -nodemcu.build.flash_mode=qio -nodemcu.build.flash_freq=40 -nodemcu.menu.FlashSize.4M1M=4M (1M SPIFFS) -nodemcu.menu.FlashSize.4M1M.build.flash_size=4M -nodemcu.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcu.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -nodemcu.menu.FlashSize.4M1M.upload.maximum_size=1044464 -nodemcu.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -nodemcu.menu.FlashSize.4M3M=4M (3M SPIFFS) -nodemcu.menu.FlashSize.4M3M.build.flash_size=4M -nodemcu.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -nodemcu.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -nodemcu.menu.FlashSize.4M3M.upload.maximum_size=1044464 -nodemcu.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -nodemcu.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -nodemcu.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -nodemcu.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -nodemcu.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -nodemcu.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -nodemcu.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -nodemcu.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -nodemcu.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -nodemcu.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -nodemcu.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -nodemcu.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.LwIPVariant.OpenSource=v1.4 Open Source -nodemcu.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -nodemcu.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcu.menu.Debug.Disabled=Disabled -nodemcu.menu.Debug.Disabled.build.debug_port= -nodemcu.menu.Debug.Serial=Serial -nodemcu.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcu.menu.Debug.Serial1=Serial1 -nodemcu.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcu.menu.DebugLevel.None____=None -nodemcu.menu.DebugLevel.None____.build.debug_level= -nodemcu.menu.DebugLevel.SSL=SSL -nodemcu.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcu.menu.DebugLevel.TLS_MEM=TLS_MEM -nodemcu.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcu.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -nodemcu.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -nodemcu.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -nodemcu.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcu.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.CORE=CORE -nodemcu.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcu.menu.DebugLevel.WIFI=WIFI -nodemcu.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcu.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -nodemcu.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcu.menu.DebugLevel.UPDATER=UPDATER -nodemcu.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcu.menu.DebugLevel.OTA=OTA -nodemcu.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcu.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -nodemcu.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -nodemcu.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcu.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcu.menu.UploadSpeed.115200=115200 -nodemcu.menu.UploadSpeed.115200.upload.speed=115200 -nodemcu.menu.UploadSpeed.9600=9600 -nodemcu.menu.UploadSpeed.9600.upload.speed=9600 -nodemcu.menu.UploadSpeed.57600=57600 -nodemcu.menu.UploadSpeed.57600.upload.speed=57600 -nodemcu.menu.UploadSpeed.230400.linux=230400 -nodemcu.menu.UploadSpeed.230400.macosx=230400 -nodemcu.menu.UploadSpeed.230400.upload.speed=230400 -nodemcu.menu.UploadSpeed.256000.windows=256000 -nodemcu.menu.UploadSpeed.256000.upload.speed=256000 -nodemcu.menu.UploadSpeed.460800.linux=460800 -nodemcu.menu.UploadSpeed.460800.macosx=460800 -nodemcu.menu.UploadSpeed.460800.upload.speed=460800 -nodemcu.menu.UploadSpeed.512000.windows=512000 -nodemcu.menu.UploadSpeed.512000.upload.speed=512000 -nodemcu.menu.UploadSpeed.921600=921600 -nodemcu.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) -nodemcuv2.build.board=ESP8266_NODEMCU -nodemcuv2.build.variant=nodemcu -nodemcuv2.upload.tool=esptool -nodemcuv2.upload.maximum_data_size=81920 -nodemcuv2.upload.wait_for_upload_port=true -nodemcuv2.serial.disableDTR=true -nodemcuv2.serial.disableRTS=true -nodemcuv2.build.mcu=esp8266 -nodemcuv2.build.core=esp8266 -nodemcuv2.build.spiffs_pagesize=256 -nodemcuv2.build.debug_port= -nodemcuv2.build.debug_level= -nodemcuv2.menu.CpuFrequency.80=80 MHz -nodemcuv2.menu.CpuFrequency.80.build.f_cpu=80000000L -nodemcuv2.menu.CpuFrequency.160=160 MHz -nodemcuv2.menu.CpuFrequency.160.build.f_cpu=160000000L -nodemcuv2.upload.resetmethod=nodemcu -nodemcuv2.build.flash_mode=dio -nodemcuv2.build.flash_freq=40 -nodemcuv2.menu.FlashSize.4M1M=4M (1M SPIFFS) -nodemcuv2.menu.FlashSize.4M1M.build.flash_size=4M -nodemcuv2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -nodemcuv2.menu.FlashSize.4M1M.upload.maximum_size=1044464 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -nodemcuv2.menu.FlashSize.4M3M=4M (3M SPIFFS) -nodemcuv2.menu.FlashSize.4M3M.build.flash_size=4M -nodemcuv2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -nodemcuv2.menu.FlashSize.4M3M.upload.maximum_size=1044464 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -nodemcuv2.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -nodemcuv2.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -nodemcuv2.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -nodemcuv2.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -nodemcuv2.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -nodemcuv2.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -nodemcuv2.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -nodemcuv2.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -nodemcuv2.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -nodemcuv2.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -nodemcuv2.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.LwIPVariant.OpenSource=v1.4 Open Source -nodemcuv2.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -nodemcuv2.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcuv2.menu.Debug.Disabled=Disabled -nodemcuv2.menu.Debug.Disabled.build.debug_port= -nodemcuv2.menu.Debug.Serial=Serial -nodemcuv2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcuv2.menu.Debug.Serial1=Serial1 -nodemcuv2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcuv2.menu.DebugLevel.None____=None -nodemcuv2.menu.DebugLevel.None____.build.debug_level= -nodemcuv2.menu.DebugLevel.SSL=SSL -nodemcuv2.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcuv2.menu.DebugLevel.TLS_MEM=TLS_MEM -nodemcuv2.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -nodemcuv2.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -nodemcuv2.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -nodemcuv2.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.CORE=CORE -nodemcuv2.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcuv2.menu.DebugLevel.WIFI=WIFI -nodemcuv2.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcuv2.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -nodemcuv2.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcuv2.menu.DebugLevel.UPDATER=UPDATER -nodemcuv2.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcuv2.menu.DebugLevel.OTA=OTA -nodemcuv2.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcuv2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -nodemcuv2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -nodemcuv2.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcuv2.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcuv2.menu.UploadSpeed.115200=115200 -nodemcuv2.menu.UploadSpeed.115200.upload.speed=115200 -nodemcuv2.menu.UploadSpeed.9600=9600 -nodemcuv2.menu.UploadSpeed.9600.upload.speed=9600 -nodemcuv2.menu.UploadSpeed.57600=57600 -nodemcuv2.menu.UploadSpeed.57600.upload.speed=57600 -nodemcuv2.menu.UploadSpeed.230400.linux=230400 -nodemcuv2.menu.UploadSpeed.230400.macosx=230400 -nodemcuv2.menu.UploadSpeed.230400.upload.speed=230400 -nodemcuv2.menu.UploadSpeed.256000.windows=256000 -nodemcuv2.menu.UploadSpeed.256000.upload.speed=256000 -nodemcuv2.menu.UploadSpeed.460800.linux=460800 -nodemcuv2.menu.UploadSpeed.460800.macosx=460800 -nodemcuv2.menu.UploadSpeed.460800.upload.speed=460800 -nodemcuv2.menu.UploadSpeed.512000.windows=512000 -nodemcuv2.menu.UploadSpeed.512000.upload.speed=512000 -nodemcuv2.menu.UploadSpeed.921600=921600 -nodemcuv2.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) -modwifi.build.board=MOD_WIFI_ESP8266 -modwifi.upload.tool=esptool -modwifi.upload.maximum_data_size=81920 -modwifi.upload.wait_for_upload_port=true -modwifi.serial.disableDTR=true -modwifi.serial.disableRTS=true -modwifi.build.mcu=esp8266 -modwifi.build.core=esp8266 -modwifi.build.variant=generic -modwifi.build.spiffs_pagesize=256 -modwifi.build.debug_port= -modwifi.build.debug_level= -modwifi.menu.CpuFrequency.80=80 MHz -modwifi.menu.CpuFrequency.80.build.f_cpu=80000000L -modwifi.menu.CpuFrequency.160=160 MHz -modwifi.menu.CpuFrequency.160.build.f_cpu=160000000L -modwifi.upload.resetmethod=ck -modwifi.build.flash_mode=qio -modwifi.build.flash_freq=40 -modwifi.menu.FlashSize.2M=2M (1M SPIFFS) -modwifi.menu.FlashSize.2M.build.flash_size=2M -modwifi.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -modwifi.menu.FlashSize.2M.build.spiffs_pagesize=256 -modwifi.menu.FlashSize.2M.upload.maximum_size=1044464 -modwifi.menu.FlashSize.2M.build.spiffs_start=0x100000 -modwifi.menu.FlashSize.2M.build.spiffs_end=0x1FB000 -modwifi.menu.FlashSize.2M.build.spiffs_blocksize=8192 -modwifi.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -modwifi.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -modwifi.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -modwifi.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -modwifi.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -modwifi.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -modwifi.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -modwifi.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -modwifi.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -modwifi.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -modwifi.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.LwIPVariant.OpenSource=v1.4 Open Source -modwifi.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -modwifi.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -modwifi.menu.Debug.Disabled=Disabled -modwifi.menu.Debug.Disabled.build.debug_port= -modwifi.menu.Debug.Serial=Serial -modwifi.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -modwifi.menu.Debug.Serial1=Serial1 -modwifi.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -modwifi.menu.DebugLevel.None____=None -modwifi.menu.DebugLevel.None____.build.debug_level= -modwifi.menu.DebugLevel.SSL=SSL -modwifi.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -modwifi.menu.DebugLevel.TLS_MEM=TLS_MEM -modwifi.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -modwifi.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -modwifi.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -modwifi.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -modwifi.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -modwifi.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -modwifi.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -modwifi.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.CORE=CORE -modwifi.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -modwifi.menu.DebugLevel.WIFI=WIFI -modwifi.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -modwifi.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -modwifi.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -modwifi.menu.DebugLevel.UPDATER=UPDATER -modwifi.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -modwifi.menu.DebugLevel.OTA=OTA -modwifi.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -modwifi.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -modwifi.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -modwifi.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -modwifi.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -modwifi.menu.UploadSpeed.115200=115200 -modwifi.menu.UploadSpeed.115200.upload.speed=115200 -modwifi.menu.UploadSpeed.9600=9600 -modwifi.menu.UploadSpeed.9600.upload.speed=9600 -modwifi.menu.UploadSpeed.57600=57600 -modwifi.menu.UploadSpeed.57600.upload.speed=57600 -modwifi.menu.UploadSpeed.230400.linux=230400 -modwifi.menu.UploadSpeed.230400.macosx=230400 -modwifi.menu.UploadSpeed.230400.upload.speed=230400 -modwifi.menu.UploadSpeed.256000.windows=256000 -modwifi.menu.UploadSpeed.256000.upload.speed=256000 -modwifi.menu.UploadSpeed.460800.linux=460800 -modwifi.menu.UploadSpeed.460800.macosx=460800 -modwifi.menu.UploadSpeed.460800.upload.speed=460800 -modwifi.menu.UploadSpeed.512000.windows=512000 -modwifi.menu.UploadSpeed.512000.upload.speed=512000 -modwifi.menu.UploadSpeed.921600=921600 -modwifi.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -thing.name=SparkFun ESP8266 Thing -thing.build.board=ESP8266_THING -thing.build.variant=thing -thing.upload.tool=esptool -thing.upload.maximum_data_size=81920 -thing.upload.wait_for_upload_port=true -thing.serial.disableDTR=true -thing.serial.disableRTS=true -thing.build.mcu=esp8266 -thing.build.core=esp8266 -thing.build.spiffs_pagesize=256 -thing.build.debug_port= -thing.build.debug_level= -thing.menu.CpuFrequency.80=80 MHz -thing.menu.CpuFrequency.80.build.f_cpu=80000000L -thing.menu.CpuFrequency.160=160 MHz -thing.menu.CpuFrequency.160.build.f_cpu=160000000L -thing.upload.resetmethod=ck -thing.build.flash_mode=qio -thing.build.flash_freq=40 -thing.menu.FlashSize.512K0=512K (no SPIFFS) -thing.menu.FlashSize.512K0.build.flash_size=512K -thing.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -thing.menu.FlashSize.512K0.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K0.upload.maximum_size=499696 -thing.menu.FlashSize.512K64=512K (64K SPIFFS) -thing.menu.FlashSize.512K64.build.flash_size=512K -thing.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -thing.menu.FlashSize.512K64.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K64.upload.maximum_size=434160 -thing.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -thing.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -thing.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -thing.menu.FlashSize.512K128=512K (128K SPIFFS) -thing.menu.FlashSize.512K128.build.flash_size=512K -thing.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -thing.menu.FlashSize.512K128.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K128.upload.maximum_size=368624 -thing.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -thing.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -thing.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -thing.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -thing.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -thing.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -thing.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -thing.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -thing.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -thing.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -thing.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -thing.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -thing.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -thing.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.LwIPVariant.OpenSource=v1.4 Open Source -thing.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -thing.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thing.menu.Debug.Disabled=Disabled -thing.menu.Debug.Disabled.build.debug_port= -thing.menu.Debug.Serial=Serial -thing.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thing.menu.Debug.Serial1=Serial1 -thing.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thing.menu.DebugLevel.None____=None -thing.menu.DebugLevel.None____.build.debug_level= -thing.menu.DebugLevel.SSL=SSL -thing.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -thing.menu.DebugLevel.TLS_MEM=TLS_MEM -thing.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thing.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -thing.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -thing.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -thing.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thing.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thing.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -thing.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.CORE=CORE -thing.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -thing.menu.DebugLevel.WIFI=WIFI -thing.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thing.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -thing.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thing.menu.DebugLevel.UPDATER=UPDATER -thing.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thing.menu.DebugLevel.OTA=OTA -thing.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -thing.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -thing.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -thing.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -thing.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thing.menu.UploadSpeed.115200=115200 -thing.menu.UploadSpeed.115200.upload.speed=115200 -thing.menu.UploadSpeed.9600=9600 -thing.menu.UploadSpeed.9600.upload.speed=9600 -thing.menu.UploadSpeed.57600=57600 -thing.menu.UploadSpeed.57600.upload.speed=57600 -thing.menu.UploadSpeed.230400.linux=230400 -thing.menu.UploadSpeed.230400.macosx=230400 -thing.menu.UploadSpeed.230400.upload.speed=230400 -thing.menu.UploadSpeed.256000.windows=256000 -thing.menu.UploadSpeed.256000.upload.speed=256000 -thing.menu.UploadSpeed.460800.linux=460800 -thing.menu.UploadSpeed.460800.macosx=460800 -thing.menu.UploadSpeed.460800.upload.speed=460800 -thing.menu.UploadSpeed.512000.windows=512000 -thing.menu.UploadSpeed.512000.upload.speed=512000 -thing.menu.UploadSpeed.921600=921600 -thing.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -thingdev.name=SparkFun ESP8266 Thing Dev -thingdev.build.board=ESP8266_THING_DEV -thingdev.build.variant=thing -thingdev.upload.tool=esptool -thingdev.upload.maximum_data_size=81920 -thingdev.upload.wait_for_upload_port=true -thingdev.serial.disableDTR=true -thingdev.serial.disableRTS=true -thingdev.build.mcu=esp8266 -thingdev.build.core=esp8266 -thingdev.build.spiffs_pagesize=256 -thingdev.build.debug_port= -thingdev.build.debug_level= -thingdev.menu.CpuFrequency.80=80 MHz -thingdev.menu.CpuFrequency.80.build.f_cpu=80000000L -thingdev.menu.CpuFrequency.160=160 MHz -thingdev.menu.CpuFrequency.160.build.f_cpu=160000000L -thingdev.upload.resetmethod=nodemcu -thingdev.build.flash_mode=dio -thingdev.build.flash_freq=40 -thingdev.menu.FlashSize.512K0=512K (no SPIFFS) -thingdev.menu.FlashSize.512K0.build.flash_size=512K -thingdev.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -thingdev.menu.FlashSize.512K0.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K0.upload.maximum_size=499696 -thingdev.menu.FlashSize.512K64=512K (64K SPIFFS) -thingdev.menu.FlashSize.512K64.build.flash_size=512K -thingdev.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -thingdev.menu.FlashSize.512K64.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K64.upload.maximum_size=434160 -thingdev.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -thingdev.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -thingdev.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -thingdev.menu.FlashSize.512K128=512K (128K SPIFFS) -thingdev.menu.FlashSize.512K128.build.flash_size=512K -thingdev.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -thingdev.menu.FlashSize.512K128.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K128.upload.maximum_size=368624 -thingdev.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -thingdev.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -thingdev.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -thingdev.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -thingdev.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -thingdev.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -thingdev.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -thingdev.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -thingdev.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -thingdev.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -thingdev.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -thingdev.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -thingdev.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -thingdev.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.LwIPVariant.OpenSource=v1.4 Open Source -thingdev.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -thingdev.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thingdev.menu.Debug.Disabled=Disabled -thingdev.menu.Debug.Disabled.build.debug_port= -thingdev.menu.Debug.Serial=Serial -thingdev.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thingdev.menu.Debug.Serial1=Serial1 -thingdev.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thingdev.menu.DebugLevel.None____=None -thingdev.menu.DebugLevel.None____.build.debug_level= -thingdev.menu.DebugLevel.SSL=SSL -thingdev.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -thingdev.menu.DebugLevel.TLS_MEM=TLS_MEM -thingdev.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thingdev.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -thingdev.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -thingdev.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -thingdev.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thingdev.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thingdev.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -thingdev.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.CORE=CORE -thingdev.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -thingdev.menu.DebugLevel.WIFI=WIFI -thingdev.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thingdev.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -thingdev.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thingdev.menu.DebugLevel.UPDATER=UPDATER -thingdev.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thingdev.menu.DebugLevel.OTA=OTA -thingdev.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -thingdev.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -thingdev.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -thingdev.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -thingdev.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thingdev.menu.UploadSpeed.115200=115200 -thingdev.menu.UploadSpeed.115200.upload.speed=115200 -thingdev.menu.UploadSpeed.9600=9600 -thingdev.menu.UploadSpeed.9600.upload.speed=9600 -thingdev.menu.UploadSpeed.57600=57600 -thingdev.menu.UploadSpeed.57600.upload.speed=57600 -thingdev.menu.UploadSpeed.230400.linux=230400 -thingdev.menu.UploadSpeed.230400.macosx=230400 -thingdev.menu.UploadSpeed.230400.upload.speed=230400 -thingdev.menu.UploadSpeed.256000.windows=256000 -thingdev.menu.UploadSpeed.256000.upload.speed=256000 -thingdev.menu.UploadSpeed.460800.linux=460800 -thingdev.menu.UploadSpeed.460800.macosx=460800 -thingdev.menu.UploadSpeed.460800.upload.speed=460800 -thingdev.menu.UploadSpeed.512000.windows=512000 -thingdev.menu.UploadSpeed.512000.upload.speed=512000 -thingdev.menu.UploadSpeed.921600=921600 -thingdev.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -esp210.name=SweetPea ESP-210 -esp210.build.board=ESP8266_ESP210 -esp210.upload.tool=esptool -esp210.upload.maximum_data_size=81920 -esp210.upload.wait_for_upload_port=true -esp210.serial.disableDTR=true -esp210.serial.disableRTS=true -esp210.build.mcu=esp8266 -esp210.build.core=esp8266 -esp210.build.variant=generic -esp210.build.spiffs_pagesize=256 -esp210.build.debug_port= -esp210.build.debug_level= -esp210.menu.CpuFrequency.80=80 MHz -esp210.menu.CpuFrequency.80.build.f_cpu=80000000L -esp210.menu.CpuFrequency.160=160 MHz -esp210.menu.CpuFrequency.160.build.f_cpu=160000000L -esp210.upload.resetmethod=ck -esp210.build.flash_mode=qio -esp210.build.flash_freq=40 -esp210.menu.FlashSize.4M1M=4M (1M SPIFFS) -esp210.menu.FlashSize.4M1M.build.flash_size=4M -esp210.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -esp210.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -esp210.menu.FlashSize.4M1M.upload.maximum_size=1044464 -esp210.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -esp210.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -esp210.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -esp210.menu.FlashSize.4M3M=4M (3M SPIFFS) -esp210.menu.FlashSize.4M3M.build.flash_size=4M -esp210.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -esp210.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -esp210.menu.FlashSize.4M3M.upload.maximum_size=1044464 -esp210.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -esp210.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -esp210.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -esp210.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -esp210.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -esp210.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -esp210.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -esp210.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -esp210.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -esp210.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -esp210.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -esp210.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -esp210.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -esp210.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.LwIPVariant.OpenSource=v1.4 Open Source -esp210.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -esp210.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp210.menu.Debug.Disabled=Disabled -esp210.menu.Debug.Disabled.build.debug_port= -esp210.menu.Debug.Serial=Serial -esp210.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp210.menu.Debug.Serial1=Serial1 -esp210.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp210.menu.DebugLevel.None____=None -esp210.menu.DebugLevel.None____.build.debug_level= -esp210.menu.DebugLevel.SSL=SSL -esp210.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp210.menu.DebugLevel.TLS_MEM=TLS_MEM -esp210.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp210.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -esp210.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -esp210.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -esp210.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp210.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp210.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp210.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.CORE=CORE -esp210.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp210.menu.DebugLevel.WIFI=WIFI -esp210.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp210.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -esp210.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp210.menu.DebugLevel.UPDATER=UPDATER -esp210.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp210.menu.DebugLevel.OTA=OTA -esp210.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp210.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -esp210.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -esp210.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -esp210.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp210.menu.UploadSpeed.57600=57600 -esp210.menu.UploadSpeed.57600.upload.speed=57600 -esp210.menu.UploadSpeed.9600=9600 -esp210.menu.UploadSpeed.9600.upload.speed=9600 -esp210.menu.UploadSpeed.115200=115200 -esp210.menu.UploadSpeed.115200.upload.speed=115200 -esp210.menu.UploadSpeed.230400.linux=230400 -esp210.menu.UploadSpeed.230400.macosx=230400 -esp210.menu.UploadSpeed.230400.upload.speed=230400 -esp210.menu.UploadSpeed.256000.windows=256000 -esp210.menu.UploadSpeed.256000.upload.speed=256000 -esp210.menu.UploadSpeed.460800.linux=460800 -esp210.menu.UploadSpeed.460800.macosx=460800 -esp210.menu.UploadSpeed.460800.upload.speed=460800 -esp210.menu.UploadSpeed.512000.windows=512000 -esp210.menu.UploadSpeed.512000.upload.speed=512000 -esp210.menu.UploadSpeed.921600=921600 -esp210.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -d1_mini.name=WeMos D1 R2 & mini -d1_mini.build.board=ESP8266_WEMOS_D1MINI -d1_mini.build.variant=d1_mini -d1_mini.upload.tool=esptool -d1_mini.upload.maximum_data_size=81920 -d1_mini.upload.wait_for_upload_port=true -d1_mini.serial.disableDTR=true -d1_mini.serial.disableRTS=true -d1_mini.build.mcu=esp8266 -d1_mini.build.core=esp8266 -d1_mini.build.spiffs_pagesize=256 -d1_mini.build.debug_port= -d1_mini.build.debug_level= -d1_mini.menu.CpuFrequency.80=80 MHz -d1_mini.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini.menu.CpuFrequency.160=160 MHz -d1_mini.menu.CpuFrequency.160.build.f_cpu=160000000L -d1_mini.upload.resetmethod=nodemcu -d1_mini.build.flash_mode=dio -d1_mini.build.flash_freq=40 -d1_mini.menu.FlashSize.4M1M=4M (1M SPIFFS) -d1_mini.menu.FlashSize.4M1M.build.flash_size=4M -d1_mini.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1_mini.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -d1_mini.menu.FlashSize.4M1M.upload.maximum_size=1044464 -d1_mini.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -d1_mini.menu.FlashSize.4M3M=4M (3M SPIFFS) -d1_mini.menu.FlashSize.4M3M.build.flash_size=4M -d1_mini.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -d1_mini.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -d1_mini.menu.FlashSize.4M3M.upload.maximum_size=1044464 -d1_mini.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -d1_mini.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -d1_mini.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1_mini.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1_mini.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1_mini.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -d1_mini.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1_mini.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1_mini.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1_mini.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -d1_mini.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1_mini.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.LwIPVariant.OpenSource=v1.4 Open Source -d1_mini.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1_mini.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini.menu.Debug.Disabled=Disabled -d1_mini.menu.Debug.Disabled.build.debug_port= -d1_mini.menu.Debug.Serial=Serial -d1_mini.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini.menu.Debug.Serial1=Serial1 -d1_mini.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini.menu.DebugLevel.None____=None -d1_mini.menu.DebugLevel.None____.build.debug_level= -d1_mini.menu.DebugLevel.SSL=SSL -d1_mini.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini.menu.DebugLevel.TLS_MEM=TLS_MEM -d1_mini.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1_mini.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1_mini.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1_mini.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.CORE=CORE -d1_mini.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini.menu.DebugLevel.WIFI=WIFI -d1_mini.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1_mini.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini.menu.DebugLevel.UPDATER=UPDATER -d1_mini.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini.menu.DebugLevel.OTA=OTA -d1_mini.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -d1_mini.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -d1_mini.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini.menu.UploadSpeed.921600=921600 -d1_mini.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini.menu.UploadSpeed.9600=9600 -d1_mini.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini.menu.UploadSpeed.57600=57600 -d1_mini.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini.menu.UploadSpeed.115200=115200 -d1_mini.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini.menu.UploadSpeed.230400.linux=230400 -d1_mini.menu.UploadSpeed.230400.macosx=230400 -d1_mini.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini.menu.UploadSpeed.256000.windows=256000 -d1_mini.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini.menu.UploadSpeed.460800.linux=460800 -d1_mini.menu.UploadSpeed.460800.macosx=460800 -d1_mini.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini.menu.UploadSpeed.512000.windows=512000 -d1_mini.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -d1_mini_pro.name=WeMos D1 mini Pro -d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO -d1_mini_pro.build.variant=d1_mini -d1_mini_pro.upload.tool=esptool -d1_mini_pro.upload.maximum_data_size=81920 -d1_mini_pro.upload.wait_for_upload_port=true -d1_mini_pro.serial.disableDTR=true -d1_mini_pro.serial.disableRTS=true -d1_mini_pro.build.mcu=esp8266 -d1_mini_pro.build.core=esp8266 -d1_mini_pro.build.spiffs_pagesize=256 -d1_mini_pro.build.debug_port= -d1_mini_pro.build.debug_level= -d1_mini_pro.menu.CpuFrequency.80=80 MHz -d1_mini_pro.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini_pro.menu.CpuFrequency.160=160 MHz -d1_mini_pro.menu.CpuFrequency.160.build.f_cpu=160000000L -d1_mini_pro.upload.resetmethod=nodemcu -d1_mini_pro.build.flash_mode=dio -d1_mini_pro.build.flash_freq=40 -d1_mini_pro.menu.FlashSize.16M15M=16M (15M SPIFFS) -d1_mini_pro.menu.FlashSize.16M15M.build.flash_size=16M -d1_mini_pro.menu.FlashSize.16M15M.build.flash_ld=eagle.flash.16m.ld -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_pagesize=256 -d1_mini_pro.menu.FlashSize.16M15M.upload.maximum_size=1044464 -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_start=0x100000 -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_end=0xFFB000 -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_blocksize=8192 -d1_mini_pro.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -d1_mini_pro.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1_mini_pro.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1_mini_pro.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1_mini_pro.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -d1_mini_pro.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1_mini_pro.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1_mini_pro.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1_mini_pro.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -d1_mini_pro.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1_mini_pro.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.LwIPVariant.OpenSource=v1.4 Open Source -d1_mini_pro.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1_mini_pro.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_pro.menu.Debug.Disabled=Disabled -d1_mini_pro.menu.Debug.Disabled.build.debug_port= -d1_mini_pro.menu.Debug.Serial=Serial -d1_mini_pro.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_pro.menu.Debug.Serial1=Serial1 -d1_mini_pro.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_pro.menu.DebugLevel.None____=None -d1_mini_pro.menu.DebugLevel.None____.build.debug_level= -d1_mini_pro.menu.DebugLevel.SSL=SSL -d1_mini_pro.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_pro.menu.DebugLevel.TLS_MEM=TLS_MEM -d1_mini_pro.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1_mini_pro.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_pro.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.CORE=CORE -d1_mini_pro.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_pro.menu.DebugLevel.WIFI=WIFI -d1_mini_pro.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_pro.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1_mini_pro.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_pro.menu.DebugLevel.UPDATER=UPDATER -d1_mini_pro.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_pro.menu.DebugLevel.OTA=OTA -d1_mini_pro.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_pro.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -d1_mini_pro.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -d1_mini_pro.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_pro.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_pro.menu.UploadSpeed.921600=921600 -d1_mini_pro.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini_pro.menu.UploadSpeed.9600=9600 -d1_mini_pro.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini_pro.menu.UploadSpeed.57600=57600 -d1_mini_pro.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini_pro.menu.UploadSpeed.115200=115200 -d1_mini_pro.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini_pro.menu.UploadSpeed.230400.linux=230400 -d1_mini_pro.menu.UploadSpeed.230400.macosx=230400 -d1_mini_pro.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini_pro.menu.UploadSpeed.256000.windows=256000 -d1_mini_pro.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini_pro.menu.UploadSpeed.460800.linux=460800 -d1_mini_pro.menu.UploadSpeed.460800.macosx=460800 -d1_mini_pro.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini_pro.menu.UploadSpeed.512000.windows=512000 -d1_mini_pro.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -d1_mini_lite.name=Wemos D1 mini Lite -d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE -d1_mini_lite.build.variant=d1_mini -d1_mini_lite.upload.tool=esptool -d1_mini_lite.upload.maximum_data_size=81920 -d1_mini_lite.upload.wait_for_upload_port=true -d1_mini_lite.serial.disableDTR=true -d1_mini_lite.serial.disableRTS=true -d1_mini_lite.build.mcu=esp8266 -d1_mini_lite.build.core=esp8266 -d1_mini_lite.build.spiffs_pagesize=256 -d1_mini_lite.build.debug_port= -d1_mini_lite.build.debug_level= -d1_mini_lite.menu.CpuFrequency.80=80 MHz -d1_mini_lite.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini_lite.menu.CpuFrequency.160=160 MHz -d1_mini_lite.menu.CpuFrequency.160.build.f_cpu=160000000L -d1_mini_lite.upload.resetmethod=nodemcu -d1_mini_lite.build.flash_mode=dout -d1_mini_lite.build.flash_freq=40 -d1_mini_lite.menu.FlashSize.1M0=1M (no SPIFFS) -d1_mini_lite.menu.FlashSize.1M0.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -d1_mini_lite.menu.FlashSize.1M0.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M0.upload.maximum_size=1023984 -d1_mini_lite.menu.FlashSize.1M64=1M (64K SPIFFS) -d1_mini_lite.menu.FlashSize.1M64.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M64.upload.maximum_size=958448 -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M128=1M (128K SPIFFS) -d1_mini_lite.menu.FlashSize.1M128.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M128.upload.maximum_size=892912 -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M144=1M (144K SPIFFS) -d1_mini_lite.menu.FlashSize.1M144.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M144.upload.maximum_size=876528 -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M160=1M (160K SPIFFS) -d1_mini_lite.menu.FlashSize.1M160.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M160.upload.maximum_size=860144 -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M192=1M (192K SPIFFS) -d1_mini_lite.menu.FlashSize.1M192.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M192.upload.maximum_size=827376 -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M256=1M (256K SPIFFS) -d1_mini_lite.menu.FlashSize.1M256.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M256.upload.maximum_size=761840 -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M512=1M (512K SPIFFS) -d1_mini_lite.menu.FlashSize.1M512.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M512.upload.maximum_size=499696 -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -d1_mini_lite.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -d1_mini_lite.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1_mini_lite.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1_mini_lite.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1_mini_lite.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -d1_mini_lite.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1_mini_lite.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1_mini_lite.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1_mini_lite.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -d1_mini_lite.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1_mini_lite.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.LwIPVariant.OpenSource=v1.4 Open Source -d1_mini_lite.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1_mini_lite.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_lite.menu.Debug.Disabled=Disabled -d1_mini_lite.menu.Debug.Disabled.build.debug_port= -d1_mini_lite.menu.Debug.Serial=Serial -d1_mini_lite.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_lite.menu.Debug.Serial1=Serial1 -d1_mini_lite.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_lite.menu.DebugLevel.None____=None -d1_mini_lite.menu.DebugLevel.None____.build.debug_level= -d1_mini_lite.menu.DebugLevel.SSL=SSL -d1_mini_lite.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_lite.menu.DebugLevel.TLS_MEM=TLS_MEM -d1_mini_lite.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1_mini_lite.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_lite.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.CORE=CORE -d1_mini_lite.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_lite.menu.DebugLevel.WIFI=WIFI -d1_mini_lite.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_lite.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1_mini_lite.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_lite.menu.DebugLevel.UPDATER=UPDATER -d1_mini_lite.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_lite.menu.DebugLevel.OTA=OTA -d1_mini_lite.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_lite.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -d1_mini_lite.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -d1_mini_lite.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_lite.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_lite.menu.UploadSpeed.921600=921600 -d1_mini_lite.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini_lite.menu.UploadSpeed.9600=9600 -d1_mini_lite.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini_lite.menu.UploadSpeed.57600=57600 -d1_mini_lite.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini_lite.menu.UploadSpeed.115200=115200 -d1_mini_lite.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini_lite.menu.UploadSpeed.230400.linux=230400 -d1_mini_lite.menu.UploadSpeed.230400.macosx=230400 -d1_mini_lite.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini_lite.menu.UploadSpeed.256000.windows=256000 -d1_mini_lite.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini_lite.menu.UploadSpeed.460800.linux=460800 -d1_mini_lite.menu.UploadSpeed.460800.macosx=460800 -d1_mini_lite.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini_lite.menu.UploadSpeed.512000.windows=512000 -d1_mini_lite.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -d1.name=WeMos D1 R1 -d1.build.board=ESP8266_WEMOS_D1MINI -d1.build.variant=d1 -d1.upload.tool=esptool -d1.upload.maximum_data_size=81920 -d1.upload.wait_for_upload_port=true -d1.serial.disableDTR=true -d1.serial.disableRTS=true -d1.build.mcu=esp8266 -d1.build.core=esp8266 -d1.build.spiffs_pagesize=256 -d1.build.debug_port= -d1.build.debug_level= -d1.menu.CpuFrequency.80=80 MHz -d1.menu.CpuFrequency.80.build.f_cpu=80000000L -d1.menu.CpuFrequency.160=160 MHz -d1.menu.CpuFrequency.160.build.f_cpu=160000000L -d1.upload.resetmethod=nodemcu -d1.build.flash_mode=dio -d1.build.flash_freq=40 -d1.menu.FlashSize.4M1M=4M (1M SPIFFS) -d1.menu.FlashSize.4M1M.build.flash_size=4M -d1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -d1.menu.FlashSize.4M1M.upload.maximum_size=1044464 -d1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -d1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -d1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -d1.menu.FlashSize.4M3M=4M (3M SPIFFS) -d1.menu.FlashSize.4M3M.build.flash_size=4M -d1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -d1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -d1.menu.FlashSize.4M3M.upload.maximum_size=1044464 -d1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -d1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -d1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -d1.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -d1.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -d1.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -d1.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.LwIPVariant.OpenSource=v1.4 Open Source -d1.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1.menu.Debug.Disabled=Disabled -d1.menu.Debug.Disabled.build.debug_port= -d1.menu.Debug.Serial=Serial -d1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1.menu.Debug.Serial1=Serial1 -d1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1.menu.DebugLevel.None____=None -d1.menu.DebugLevel.None____.build.debug_level= -d1.menu.DebugLevel.SSL=SSL -d1.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1.menu.DebugLevel.TLS_MEM=TLS_MEM -d1.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.CORE=CORE -d1.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1.menu.DebugLevel.WIFI=WIFI -d1.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1.menu.DebugLevel.UPDATER=UPDATER -d1.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1.menu.DebugLevel.OTA=OTA -d1.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -d1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -d1.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1.menu.UploadSpeed.921600=921600 -d1.menu.UploadSpeed.921600.upload.speed=921600 -d1.menu.UploadSpeed.9600=9600 -d1.menu.UploadSpeed.9600.upload.speed=9600 -d1.menu.UploadSpeed.57600=57600 -d1.menu.UploadSpeed.57600.upload.speed=57600 -d1.menu.UploadSpeed.115200=115200 -d1.menu.UploadSpeed.115200.upload.speed=115200 -d1.menu.UploadSpeed.230400.linux=230400 -d1.menu.UploadSpeed.230400.macosx=230400 -d1.menu.UploadSpeed.230400.upload.speed=230400 -d1.menu.UploadSpeed.256000.windows=256000 -d1.menu.UploadSpeed.256000.upload.speed=256000 -d1.menu.UploadSpeed.460800.linux=460800 -d1.menu.UploadSpeed.460800.macosx=460800 -d1.menu.UploadSpeed.460800.upload.speed=460800 -d1.menu.UploadSpeed.512000.windows=512000 -d1.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -espino.name=ESPino (ESP-12 Module) -espino.build.board=ESP8266_ESP12 -espino.build.variant=espino -espino.upload.tool=esptool -espino.upload.maximum_data_size=81920 -espino.upload.wait_for_upload_port=true -espino.serial.disableDTR=true -espino.serial.disableRTS=true -espino.build.mcu=esp8266 -espino.build.core=esp8266 -espino.build.spiffs_pagesize=256 -espino.build.debug_port= -espino.build.debug_level= -espino.menu.CpuFrequency.80=80 MHz -espino.menu.CpuFrequency.80.build.f_cpu=80000000L -espino.menu.CpuFrequency.160=160 MHz -espino.menu.CpuFrequency.160.build.f_cpu=160000000L -espino.menu.ResetMethod.ck=ck -espino.menu.ResetMethod.ck.upload.resetmethod=ck -espino.menu.ResetMethod.nodemcu=nodemcu -espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espino.build.flash_mode=qio -espino.build.flash_freq=40 -espino.menu.FlashSize.4M1M=4M (1M SPIFFS) -espino.menu.FlashSize.4M1M.build.flash_size=4M -espino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espino.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espino.menu.FlashSize.4M3M=4M (3M SPIFFS) -espino.menu.FlashSize.4M3M.build.flash_size=4M -espino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espino.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espino.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espino.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -espino.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espino.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espino.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espino.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -espino.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espino.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espino.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espino.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -espino.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espino.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.LwIPVariant.OpenSource=v1.4 Open Source -espino.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espino.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espino.menu.Debug.Disabled=Disabled -espino.menu.Debug.Disabled.build.debug_port= -espino.menu.Debug.Serial=Serial -espino.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espino.menu.Debug.Serial1=Serial1 -espino.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espino.menu.DebugLevel.None____=None -espino.menu.DebugLevel.None____.build.debug_level= -espino.menu.DebugLevel.SSL=SSL -espino.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espino.menu.DebugLevel.TLS_MEM=TLS_MEM -espino.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espino.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espino.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espino.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espino.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espino.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espino.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espino.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.CORE=CORE -espino.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espino.menu.DebugLevel.WIFI=WIFI -espino.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espino.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espino.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espino.menu.DebugLevel.UPDATER=UPDATER -espino.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espino.menu.DebugLevel.OTA=OTA -espino.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espino.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espino.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espino.menu.UploadSpeed.115200=115200 -espino.menu.UploadSpeed.115200.upload.speed=115200 -espino.menu.UploadSpeed.9600=9600 -espino.menu.UploadSpeed.9600.upload.speed=9600 -espino.menu.UploadSpeed.57600=57600 -espino.menu.UploadSpeed.57600.upload.speed=57600 -espino.menu.UploadSpeed.230400.linux=230400 -espino.menu.UploadSpeed.230400.macosx=230400 -espino.menu.UploadSpeed.230400.upload.speed=230400 -espino.menu.UploadSpeed.256000.windows=256000 -espino.menu.UploadSpeed.256000.upload.speed=256000 -espino.menu.UploadSpeed.460800.linux=460800 -espino.menu.UploadSpeed.460800.macosx=460800 -espino.menu.UploadSpeed.460800.upload.speed=460800 -espino.menu.UploadSpeed.512000.windows=512000 -espino.menu.UploadSpeed.512000.upload.speed=512000 -espino.menu.UploadSpeed.921600=921600 -espino.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espinotee.name=ThaiEasyElec's ESPino -espinotee.build.board=ESP8266_ESP13 -espinotee.build.variant=espinotee -espinotee.upload.tool=esptool -espinotee.upload.maximum_data_size=81920 -espinotee.upload.wait_for_upload_port=true -espinotee.serial.disableDTR=true -espinotee.serial.disableRTS=true -espinotee.build.mcu=esp8266 -espinotee.build.core=esp8266 -espinotee.build.spiffs_pagesize=256 -espinotee.build.debug_port= -espinotee.build.debug_level= -espinotee.menu.CpuFrequency.80=80 MHz -espinotee.menu.CpuFrequency.80.build.f_cpu=80000000L -espinotee.menu.CpuFrequency.160=160 MHz -espinotee.menu.CpuFrequency.160.build.f_cpu=160000000L -espinotee.upload.resetmethod=nodemcu -espinotee.build.flash_mode=qio -espinotee.build.flash_freq=40 -espinotee.menu.FlashSize.4M1M=4M (1M SPIFFS) -espinotee.menu.FlashSize.4M1M.build.flash_size=4M -espinotee.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espinotee.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espinotee.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espinotee.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espinotee.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espinotee.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espinotee.menu.FlashSize.4M3M=4M (3M SPIFFS) -espinotee.menu.FlashSize.4M3M.build.flash_size=4M -espinotee.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espinotee.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espinotee.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espinotee.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espinotee.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espinotee.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espinotee.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -espinotee.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espinotee.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espinotee.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espinotee.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -espinotee.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espinotee.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espinotee.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espinotee.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -espinotee.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espinotee.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.LwIPVariant.OpenSource=v1.4 Open Source -espinotee.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espinotee.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espinotee.menu.Debug.Disabled=Disabled -espinotee.menu.Debug.Disabled.build.debug_port= -espinotee.menu.Debug.Serial=Serial -espinotee.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espinotee.menu.Debug.Serial1=Serial1 -espinotee.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espinotee.menu.DebugLevel.None____=None -espinotee.menu.DebugLevel.None____.build.debug_level= -espinotee.menu.DebugLevel.SSL=SSL -espinotee.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espinotee.menu.DebugLevel.TLS_MEM=TLS_MEM -espinotee.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espinotee.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espinotee.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espinotee.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espinotee.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espinotee.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espinotee.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espinotee.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.CORE=CORE -espinotee.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espinotee.menu.DebugLevel.WIFI=WIFI -espinotee.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espinotee.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espinotee.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espinotee.menu.DebugLevel.UPDATER=UPDATER -espinotee.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espinotee.menu.DebugLevel.OTA=OTA -espinotee.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espinotee.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espinotee.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -espinotee.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espinotee.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espinotee.menu.UploadSpeed.115200=115200 -espinotee.menu.UploadSpeed.115200.upload.speed=115200 -espinotee.menu.UploadSpeed.9600=9600 -espinotee.menu.UploadSpeed.9600.upload.speed=9600 -espinotee.menu.UploadSpeed.57600=57600 -espinotee.menu.UploadSpeed.57600.upload.speed=57600 -espinotee.menu.UploadSpeed.230400.linux=230400 -espinotee.menu.UploadSpeed.230400.macosx=230400 -espinotee.menu.UploadSpeed.230400.upload.speed=230400 -espinotee.menu.UploadSpeed.256000.windows=256000 -espinotee.menu.UploadSpeed.256000.upload.speed=256000 -espinotee.menu.UploadSpeed.460800.linux=460800 -espinotee.menu.UploadSpeed.460800.macosx=460800 -espinotee.menu.UploadSpeed.460800.upload.speed=460800 -espinotee.menu.UploadSpeed.512000.windows=512000 -espinotee.menu.UploadSpeed.512000.upload.speed=512000 -espinotee.menu.UploadSpeed.921600=921600 -espinotee.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -wifinfo.name=WifInfo -wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 -wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 -wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 -wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld -wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 -wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) -wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 -wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 -wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 -wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 -wifinfo.menu.ESPModule.ESP12.build.flash_size=4M -wifinfo.build.board=WIFINFO -wifinfo.build.variant=wifinfo -wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M -wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) -wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 -wifinfo.upload.tool=esptool -wifinfo.upload.maximum_data_size=81920 -wifinfo.upload.wait_for_upload_port=true -wifinfo.serial.disableDTR=true -wifinfo.serial.disableRTS=true -wifinfo.build.mcu=esp8266 -wifinfo.build.core=esp8266 -wifinfo.build.spiffs_pagesize=256 -wifinfo.build.debug_port= -wifinfo.build.debug_level= -wifinfo.menu.CpuFrequency.80=80 MHz -wifinfo.menu.CpuFrequency.80.build.f_cpu=80000000L -wifinfo.menu.CpuFrequency.160=160 MHz -wifinfo.menu.CpuFrequency.160.build.f_cpu=160000000L -wifinfo.build.flash_mode=qio -wifinfo.menu.FlashFreq.40=40MHz -wifinfo.menu.FlashFreq.40.build.flash_freq=40 -wifinfo.menu.FlashFreq.80=80MHz -wifinfo.menu.FlashFreq.80.build.flash_freq=80 -wifinfo.menu.FlashSize.1M0=1M (no SPIFFS) -wifinfo.menu.FlashSize.1M0.build.flash_size=1M -wifinfo.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -wifinfo.menu.FlashSize.1M0.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M0.upload.maximum_size=1023984 -wifinfo.menu.FlashSize.1M64=1M (64K SPIFFS) -wifinfo.menu.FlashSize.1M64.build.flash_size=1M -wifinfo.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -wifinfo.menu.FlashSize.1M64.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M64.upload.maximum_size=958448 -wifinfo.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -wifinfo.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M128=1M (128K SPIFFS) -wifinfo.menu.FlashSize.1M128.build.flash_size=1M -wifinfo.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -wifinfo.menu.FlashSize.1M128.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M128.upload.maximum_size=892912 -wifinfo.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -wifinfo.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M144=1M (144K SPIFFS) -wifinfo.menu.FlashSize.1M144.build.flash_size=1M -wifinfo.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -wifinfo.menu.FlashSize.1M144.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M144.upload.maximum_size=876528 -wifinfo.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -wifinfo.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M160=1M (160K SPIFFS) -wifinfo.menu.FlashSize.1M160.build.flash_size=1M -wifinfo.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -wifinfo.menu.FlashSize.1M160.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M160.upload.maximum_size=860144 -wifinfo.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -wifinfo.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M192=1M (192K SPIFFS) -wifinfo.menu.FlashSize.1M192.build.flash_size=1M -wifinfo.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.FlashSize.1M192.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M192.upload.maximum_size=827376 -wifinfo.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -wifinfo.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M256=1M (256K SPIFFS) -wifinfo.menu.FlashSize.1M256.build.flash_size=1M -wifinfo.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -wifinfo.menu.FlashSize.1M256.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M256.upload.maximum_size=761840 -wifinfo.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -wifinfo.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M512=1M (512K SPIFFS) -wifinfo.menu.FlashSize.1M512.build.flash_size=1M -wifinfo.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -wifinfo.menu.FlashSize.1M512.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M512.upload.maximum_size=499696 -wifinfo.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -wifinfo.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -wifinfo.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -wifinfo.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -wifinfo.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -wifinfo.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -wifinfo.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -wifinfo.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -wifinfo.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -wifinfo.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -wifinfo.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -wifinfo.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -wifinfo.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.LwIPVariant.OpenSource=v1.4 Open Source -wifinfo.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -wifinfo.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifinfo.menu.Debug.Disabled=Disabled -wifinfo.menu.Debug.Disabled.build.debug_port= -wifinfo.menu.Debug.Serial=Serial -wifinfo.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifinfo.menu.Debug.Serial1=Serial1 -wifinfo.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifinfo.menu.DebugLevel.None____=None -wifinfo.menu.DebugLevel.None____.build.debug_level= -wifinfo.menu.DebugLevel.SSL=SSL -wifinfo.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifinfo.menu.DebugLevel.TLS_MEM=TLS_MEM -wifinfo.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifinfo.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -wifinfo.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -wifinfo.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -wifinfo.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifinfo.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.CORE=CORE -wifinfo.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifinfo.menu.DebugLevel.WIFI=WIFI -wifinfo.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifinfo.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -wifinfo.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifinfo.menu.DebugLevel.UPDATER=UPDATER -wifinfo.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifinfo.menu.DebugLevel.OTA=OTA -wifinfo.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifinfo.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -wifinfo.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -wifinfo.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -wifinfo.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifinfo.menu.UploadSpeed.115200=115200 -wifinfo.menu.UploadSpeed.115200.upload.speed=115200 -wifinfo.menu.UploadSpeed.9600=9600 -wifinfo.menu.UploadSpeed.9600.upload.speed=9600 -wifinfo.menu.UploadSpeed.57600=57600 -wifinfo.menu.UploadSpeed.57600.upload.speed=57600 -wifinfo.menu.UploadSpeed.230400.linux=230400 -wifinfo.menu.UploadSpeed.230400.macosx=230400 -wifinfo.menu.UploadSpeed.230400.upload.speed=230400 -wifinfo.menu.UploadSpeed.256000.windows=256000 -wifinfo.menu.UploadSpeed.256000.upload.speed=256000 -wifinfo.menu.UploadSpeed.460800.linux=460800 -wifinfo.menu.UploadSpeed.460800.macosx=460800 -wifinfo.menu.UploadSpeed.460800.upload.speed=460800 -wifinfo.menu.UploadSpeed.512000.windows=512000 -wifinfo.menu.UploadSpeed.512000.upload.speed=512000 -wifinfo.menu.UploadSpeed.921600=921600 -wifinfo.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -arduino-esp8266.name=Arduino -arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO -arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI -arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.primo=Primo -arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi -arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO -arduino-esp8266.build.board=ESP8266_ARDUINO -arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO -arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi -arduino-esp8266.upload.tool=esptool -arduino-esp8266.upload.maximum_data_size=81920 -arduino-esp8266.upload.wait_for_upload_port=true -arduino-esp8266.serial.disableDTR=true -arduino-esp8266.serial.disableRTS=true -arduino-esp8266.build.mcu=esp8266 -arduino-esp8266.build.core=esp8266 -arduino-esp8266.build.variant=generic -arduino-esp8266.build.spiffs_pagesize=256 -arduino-esp8266.build.debug_port= -arduino-esp8266.build.debug_level= -arduino-esp8266.menu.CpuFrequency.80=80 MHz -arduino-esp8266.menu.CpuFrequency.80.build.f_cpu=80000000L -arduino-esp8266.menu.CpuFrequency.160=160 MHz -arduino-esp8266.menu.CpuFrequency.160.build.f_cpu=160000000L -arduino-esp8266.build.flash_mode=qio -arduino-esp8266.build.flash_freq=40 -arduino-esp8266.menu.FlashSize.4M1M=4M (1M SPIFFS) -arduino-esp8266.menu.FlashSize.4M1M.build.flash_size=4M -arduino-esp8266.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -arduino-esp8266.menu.FlashSize.4M1M.upload.maximum_size=1044464 -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.FlashSize.4M3M=4M (3M SPIFFS) -arduino-esp8266.menu.FlashSize.4M3M.build.flash_size=4M -arduino-esp8266.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -arduino-esp8266.menu.FlashSize.4M3M.upload.maximum_size=1044464 -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -arduino-esp8266.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -arduino-esp8266.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -arduino-esp8266.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -arduino-esp8266.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -arduino-esp8266.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -arduino-esp8266.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -arduino-esp8266.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -arduino-esp8266.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -arduino-esp8266.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -arduino-esp8266.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.LwIPVariant.OpenSource=v1.4 Open Source -arduino-esp8266.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -arduino-esp8266.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -arduino-esp8266.menu.Debug.Disabled=Disabled -arduino-esp8266.menu.Debug.Disabled.build.debug_port= -arduino-esp8266.menu.Debug.Serial=Serial -arduino-esp8266.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -arduino-esp8266.menu.Debug.Serial1=Serial1 -arduino-esp8266.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -arduino-esp8266.menu.DebugLevel.None____=None -arduino-esp8266.menu.DebugLevel.None____.build.debug_level= -arduino-esp8266.menu.DebugLevel.SSL=SSL -arduino-esp8266.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -arduino-esp8266.menu.DebugLevel.TLS_MEM=TLS_MEM -arduino-esp8266.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -arduino-esp8266.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -arduino-esp8266.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.CORE=CORE -arduino-esp8266.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -arduino-esp8266.menu.DebugLevel.WIFI=WIFI -arduino-esp8266.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -arduino-esp8266.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -arduino-esp8266.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -arduino-esp8266.menu.DebugLevel.UPDATER=UPDATER -arduino-esp8266.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -arduino-esp8266.menu.DebugLevel.OTA=OTA -arduino-esp8266.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -arduino-esp8266.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -arduino-esp8266.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -arduino-esp8266.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -arduino-esp8266.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -arduino-esp8266.menu.UploadSpeed.115200=115200 -arduino-esp8266.menu.UploadSpeed.115200.upload.speed=115200 -arduino-esp8266.menu.UploadSpeed.9600=9600 -arduino-esp8266.menu.UploadSpeed.9600.upload.speed=9600 -arduino-esp8266.menu.UploadSpeed.57600=57600 -arduino-esp8266.menu.UploadSpeed.57600.upload.speed=57600 -arduino-esp8266.menu.UploadSpeed.230400.linux=230400 -arduino-esp8266.menu.UploadSpeed.230400.macosx=230400 -arduino-esp8266.menu.UploadSpeed.230400.upload.speed=230400 -arduino-esp8266.menu.UploadSpeed.256000.windows=256000 -arduino-esp8266.menu.UploadSpeed.256000.upload.speed=256000 -arduino-esp8266.menu.UploadSpeed.460800.linux=460800 -arduino-esp8266.menu.UploadSpeed.460800.macosx=460800 -arduino-esp8266.menu.UploadSpeed.460800.upload.speed=460800 -arduino-esp8266.menu.UploadSpeed.512000.windows=512000 -arduino-esp8266.menu.UploadSpeed.512000.upload.speed=512000 -arduino-esp8266.menu.UploadSpeed.921600=921600 -arduino-esp8266.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -gen4iod.name=4D Systems gen4 IoD Range -gen4iod.build.board=GEN4_IOD -gen4iod.build.f_cpu=160000000L -gen4iod.build.variant=generic -gen4iod.upload.tool=esptool -gen4iod.upload.maximum_data_size=81920 -gen4iod.upload.wait_for_upload_port=true -gen4iod.serial.disableDTR=true -gen4iod.serial.disableRTS=true -gen4iod.build.mcu=esp8266 -gen4iod.build.core=esp8266 -gen4iod.build.spiffs_pagesize=256 -gen4iod.build.debug_port= -gen4iod.build.debug_level= -gen4iod.menu.CpuFrequency.80=80 MHz -gen4iod.menu.CpuFrequency.80.build.f_cpu=80000000L -gen4iod.menu.CpuFrequency.160=160 MHz -gen4iod.menu.CpuFrequency.160.build.f_cpu=160000000L -gen4iod.build.flash_mode=qio -gen4iod.build.flash_freq=80 -gen4iod.menu.FlashSize.512K0=512K (no SPIFFS) -gen4iod.menu.FlashSize.512K0.build.flash_size=512K -gen4iod.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -gen4iod.menu.FlashSize.512K0.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K0.upload.maximum_size=499696 -gen4iod.menu.FlashSize.512K64=512K (64K SPIFFS) -gen4iod.menu.FlashSize.512K64.build.flash_size=512K -gen4iod.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -gen4iod.menu.FlashSize.512K64.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K64.upload.maximum_size=434160 -gen4iod.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -gen4iod.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -gen4iod.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -gen4iod.menu.FlashSize.512K128=512K (128K SPIFFS) -gen4iod.menu.FlashSize.512K128.build.flash_size=512K -gen4iod.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -gen4iod.menu.FlashSize.512K128.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K128.upload.maximum_size=368624 -gen4iod.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -gen4iod.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -gen4iod.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -gen4iod.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -gen4iod.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -gen4iod.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -gen4iod.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -gen4iod.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -gen4iod.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -gen4iod.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -gen4iod.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -gen4iod.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -gen4iod.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -gen4iod.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.LwIPVariant.OpenSource=v1.4 Open Source -gen4iod.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -gen4iod.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -gen4iod.menu.Debug.Disabled=Disabled -gen4iod.menu.Debug.Disabled.build.debug_port= -gen4iod.menu.Debug.Serial=Serial -gen4iod.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -gen4iod.menu.Debug.Serial1=Serial1 -gen4iod.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -gen4iod.menu.DebugLevel.None____=None -gen4iod.menu.DebugLevel.None____.build.debug_level= -gen4iod.menu.DebugLevel.SSL=SSL -gen4iod.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -gen4iod.menu.DebugLevel.TLS_MEM=TLS_MEM -gen4iod.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -gen4iod.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -gen4iod.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -gen4iod.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -gen4iod.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -gen4iod.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.CORE=CORE -gen4iod.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -gen4iod.menu.DebugLevel.WIFI=WIFI -gen4iod.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -gen4iod.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -gen4iod.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -gen4iod.menu.DebugLevel.UPDATER=UPDATER -gen4iod.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -gen4iod.menu.DebugLevel.OTA=OTA -gen4iod.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -gen4iod.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -gen4iod.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -gen4iod.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -gen4iod.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -gen4iod.menu.UploadSpeed.115200=115200 -gen4iod.menu.UploadSpeed.115200.upload.speed=115200 -gen4iod.menu.UploadSpeed.9600=9600 -gen4iod.menu.UploadSpeed.9600.upload.speed=9600 -gen4iod.menu.UploadSpeed.57600=57600 -gen4iod.menu.UploadSpeed.57600.upload.speed=57600 -gen4iod.menu.UploadSpeed.230400.linux=230400 -gen4iod.menu.UploadSpeed.230400.macosx=230400 -gen4iod.menu.UploadSpeed.230400.upload.speed=230400 -gen4iod.menu.UploadSpeed.256000.windows=256000 -gen4iod.menu.UploadSpeed.256000.upload.speed=256000 -gen4iod.menu.UploadSpeed.460800.linux=460800 -gen4iod.menu.UploadSpeed.460800.macosx=460800 -gen4iod.menu.UploadSpeed.460800.upload.speed=460800 -gen4iod.menu.UploadSpeed.512000.windows=512000 -gen4iod.menu.UploadSpeed.512000.upload.speed=512000 -gen4iod.menu.UploadSpeed.921600=921600 -gen4iod.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -oak.name=DigiStump Oak -oak.build.board=ESP8266_OAK -oak.build.variant=oak -oak.upload.maximum_size=1040368 -oak.upload.tool=esptool -oak.upload.maximum_data_size=81920 -oak.upload.wait_for_upload_port=true -oak.serial.disableDTR=true -oak.serial.disableRTS=true -oak.build.mcu=esp8266 -oak.build.core=esp8266 -oak.build.spiffs_pagesize=256 -oak.build.debug_port= -oak.build.debug_level= -oak.menu.CpuFrequency.80=80 MHz -oak.menu.CpuFrequency.80.build.f_cpu=80000000L -oak.menu.CpuFrequency.160=160 MHz -oak.menu.CpuFrequency.160.build.f_cpu=160000000L -oak.build.flash_mode=dio -oak.build.flash_freq=40 -oak.menu.FlashSize.4M1M=4M (1M SPIFFS) -oak.menu.FlashSize.4M1M.build.flash_size=4M -oak.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -oak.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -oak.menu.FlashSize.4M1M.upload.maximum_size=1044464 -oak.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -oak.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -oak.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -oak.menu.FlashSize.4M3M=4M (3M SPIFFS) -oak.menu.FlashSize.4M3M.build.flash_size=4M -oak.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -oak.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -oak.menu.FlashSize.4M3M.upload.maximum_size=1044464 -oak.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -oak.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -oak.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -oak.menu.LwIPVariant.v2mss536=v2 Prebuilt (MSS=536) -oak.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -oak.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -oak.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -oak.menu.LwIPVariant.v2mss1460=v2 Prebuilt (MSS=1460, unstable) -oak.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -oak.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -oak.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -oak.menu.LwIPVariant.Prebuilt=v1.4 Prebuilt -oak.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -oak.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.LwIPVariant.OpenSource=v1.4 Open Source -oak.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -oak.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -oak.menu.Debug.Disabled=Disabled -oak.menu.Debug.Disabled.build.debug_port= -oak.menu.Debug.Serial=Serial -oak.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -oak.menu.Debug.Serial1=Serial1 -oak.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -oak.menu.DebugLevel.None____=None -oak.menu.DebugLevel.None____.build.debug_level= -oak.menu.DebugLevel.SSL=SSL -oak.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -oak.menu.DebugLevel.TLS_MEM=TLS_MEM -oak.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -oak.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -oak.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -oak.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -oak.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -oak.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -oak.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -oak.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.CORE=CORE -oak.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -oak.menu.DebugLevel.WIFI=WIFI -oak.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -oak.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -oak.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -oak.menu.DebugLevel.UPDATER=UPDATER -oak.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -oak.menu.DebugLevel.OTA=OTA -oak.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -oak.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -oak.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTA.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -oak.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -oak.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -oak.menu.UploadSpeed.921600=921600 -oak.menu.UploadSpeed.921600.upload.speed=921600 -oak.menu.UploadSpeed.9600=9600 -oak.menu.UploadSpeed.9600.upload.speed=9600 -oak.menu.UploadSpeed.57600=57600 -oak.menu.UploadSpeed.57600.upload.speed=57600 -oak.menu.UploadSpeed.115200=115200 -oak.menu.UploadSpeed.115200.upload.speed=115200 -oak.menu.UploadSpeed.230400.linux=230400 -oak.menu.UploadSpeed.230400.macosx=230400 -oak.menu.UploadSpeed.230400.upload.speed=230400 -oak.menu.UploadSpeed.256000.windows=256000 -oak.menu.UploadSpeed.256000.upload.speed=256000 -oak.menu.UploadSpeed.460800.linux=460800 -oak.menu.UploadSpeed.460800.macosx=460800 -oak.menu.UploadSpeed.460800.upload.speed=460800 -oak.menu.UploadSpeed.512000.windows=512000 -oak.menu.UploadSpeed.512000.upload.speed=512000 - diff --git a/arduino/version 2.4.0/platform.txt b/arduino/version 2.4.0/platform.txt deleted file mode 100644 index d284f64da..000000000 --- a/arduino/version 2.4.0/platform.txt +++ /dev/null @@ -1,133 +0,0 @@ - -# ESP8266 platform -# ------------------------------ - -# For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification - -name=ESP8266 Modules -version=2.4.0 - - - - -compiler.warning_flags=-w -compiler.warning_flags.none=-w -compiler.warning_flags.default= -compiler.warning_flags.more=-Wall -compiler.warning_flags.all=-Wall -Wextra - -build.lwip_lib=-llwip_gcc -build.lwip_include=lwip/include -build.lwip_flags=-DLWIP_OPEN_SRC - -compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ -compiler.sdk.path={runtime.platform.path}/tools/sdk -compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf -compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" - -compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections - -compiler.S.cmd=xtensa-lx106-elf-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls - -# compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start -u _printf_float -u _scanf_float -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read -compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read - -compiler.c.elf.cmd=xtensa-lx106-elf-gcc -compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -laxtls -lespnow -lsmartconfig -lairkiss -lmesh -lwpa2 -lstdc++ -lm -lc -lgcc - -compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections - -compiler.as.cmd=xtensa-lx106-elf-as - -compiler.ar.cmd=xtensa-lx106-elf-ar -compiler.ar.flags=cru - -compiler.elf2hex.cmd=esptool -compiler.elf2hex.flags= - -compiler.size.cmd=xtensa-lx106-elf-size - -compiler.esptool.cmd=esptool -compiler.esptool.cmd.windows=esptool.exe - -# This can be overriden in boards.txt -build.extra_flags=-DESP8266 - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags= -compiler.S.extra_flags= -compiler.cpp.extra_flags= -compiler.ar.extra_flags= -compiler.objcopy.eep.extra_flags= -compiler.elf2hex.extra_flags= - -## generate file with git version number -## needs bash, git, and echo - -## windows-compatible version may be added later - - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Create archives -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/arduino.ar" "{object_file}" - -## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/arduino.ar" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" - -## Create eeprom -recipe.objcopy.eep.pattern= - -## Create hex -#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" - -recipe.objcopy.hex.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec - -## Save hex -recipe.output.tmp_file={build.project_name}.bin -recipe.output.save_file={build.project_name}.{build.variant}.bin - -## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* -#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* - -# ------------------------------ - -tools.esptool.cmd=esptool -tools.esptool.cmd.windows=esptool.exe -tools.esptool.path={runtime.tools.esptool.path} -tools.esptool.network_cmd=python -tools.esptool.network_cmd.windows=python.exe - -tools.esptool.upload.protocol=esp -tools.esptool.upload.params.verbose=-vv -tools.esptool.upload.params.quiet= -tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" -ca 0x00000 -cf "{build.path}/{build.project_name}.bin" -tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" - -tools.mkspiffs.cmd=mkspiffs -tools.mkspiffs.cmd.windows=mkspiffs.exe -tools.mkspiffs.path={runtime.tools.mkspiffs.path} - -tools.espupload.cmd=python -tools.espupload.cmd.windows=python.exe -tools.espupload.path={runtime.platform.path}/tools - -tools.espupload.upload.protocol=espupload -tools.espupload.upload.params.verbose= -tools.espupload.upload.params.quiet= -tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" diff --git a/arduino/version 2.4.1/boards.txt b/arduino/version 2.4.1/boards.txt deleted file mode 100644 index 0d948f012..000000000 --- a/arduino/version 2.4.1/boards.txt +++ /dev/null @@ -1,3796 +0,0 @@ -# -# this file is script-generated and is likely to be overwritten by boards.txt.py -# - -menu.BoardModel=Model -menu.UploadSpeed=Upload Speed -menu.UploadTool=Upload Using -menu.CpuFrequency=CPU Frequency -menu.CrystalFreq=Crystal Frequency -menu.FlashSize=Flash Size -menu.FlashMode=Flash Mode -menu.FlashFreq=Flash Frequency -menu.ResetMethod=Reset Method -menu.ESPModule=Module -menu.Debug=Debug port -menu.DebugLevel=Debug Level -menu.LwIPVariant=lwIP Variant -menu.led=Builtin Led -menu.FlashErase=Erase Flash - -############################################################## -generic.name=Generic ESP8266 Module -generic.build.board=ESP8266_GENERIC -generic.upload.tool=esptool -generic.upload.maximum_data_size=81920 -generic.upload.wait_for_upload_port=true -generic.upload.erase_cmd= -generic.serial.disableDTR=true -generic.serial.disableRTS=true -generic.build.mcu=esp8266 -generic.build.core=esp8266 -generic.build.variant=generic -generic.build.spiffs_pagesize=256 -generic.build.debug_port= -generic.build.debug_level= - -generic.menu.UploadTool.esptool=Serial -generic.menu.UploadTool.esptool.upload.tool=esptool -generic.menu.UploadTool.esptool.upload.verbose=-vv -generic.menu.UploadTool.espupload=OTA_upload -generic.menu.UploadTool.espupload.upload.tool=espupload - -generic.menu.CpuFrequency.80=80 MHz -generic.menu.CpuFrequency.80.build.f_cpu=80000000L -generic.menu.CpuFrequency.160=160 MHz -generic.menu.CpuFrequency.160.build.f_cpu=160000000L -generic.menu.ResetMethod.ck=ck -generic.menu.ResetMethod.ck.upload.resetmethod=ck -generic.menu.ResetMethod.nodemcu=nodemcu -generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -generic.menu.ResetMethod.none=none -generic.menu.ResetMethod.none.upload.resetmethod=none -generic.menu.ResetMethod.dtrset=dtrset -generic.menu.ResetMethod.dtrset.upload.resetmethod=dtrset -generic.menu.CrystalFreq.26=26 MHz -generic.menu.CrystalFreq.40=40 MHz -generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -generic.menu.FlashFreq.40=40MHz -generic.menu.FlashFreq.40.build.flash_freq=40 -generic.menu.FlashFreq.80=80MHz -generic.menu.FlashFreq.80.build.flash_freq=80 -generic.menu.FlashMode.qio=QIO -generic.menu.FlashMode.qio.build.flash_mode=qio -generic.menu.FlashMode.qout=QOUT -generic.menu.FlashMode.qout.build.flash_mode=qout -generic.menu.FlashMode.dio=DIO -generic.menu.FlashMode.dio.build.flash_mode=dio -generic.menu.FlashMode.dout=DOUT -generic.menu.FlashMode.dout.build.flash_mode=dout -generic.menu.FlashSize.512K0=512K (no SPIFFS) -generic.menu.FlashSize.512K0.build.flash_size=512K -generic.menu.FlashSize.512K0.build.flash_size_bytes=0x80000 -generic.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -generic.menu.FlashSize.512K0.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K0.upload.maximum_size=499696 -generic.menu.FlashSize.512K0.build.rfcal_addr=0x7C000 -generic.menu.FlashSize.512K64=512K (64K SPIFFS) -generic.menu.FlashSize.512K64.build.flash_size=512K -generic.menu.FlashSize.512K64.build.flash_size_bytes=0x80000 -generic.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -generic.menu.FlashSize.512K64.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K64.upload.maximum_size=434160 -generic.menu.FlashSize.512K64.build.rfcal_addr=0x7C000 -generic.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -generic.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -generic.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -generic.menu.FlashSize.512K128=512K (128K SPIFFS) -generic.menu.FlashSize.512K128.build.flash_size=512K -generic.menu.FlashSize.512K128.build.flash_size_bytes=0x80000 -generic.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -generic.menu.FlashSize.512K128.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K128.upload.maximum_size=368624 -generic.menu.FlashSize.512K128.build.rfcal_addr=0x7C000 -generic.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -generic.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -generic.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M0=1M (no SPIFFS) -generic.menu.FlashSize.1M0.build.flash_size=1M -generic.menu.FlashSize.1M0.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -generic.menu.FlashSize.1M0.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M0.upload.maximum_size=1023984 -generic.menu.FlashSize.1M0.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M64=1M (64K SPIFFS) -generic.menu.FlashSize.1M64.build.flash_size=1M -generic.menu.FlashSize.1M64.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -generic.menu.FlashSize.1M64.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M64.upload.maximum_size=958448 -generic.menu.FlashSize.1M64.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -generic.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M128=1M (128K SPIFFS) -generic.menu.FlashSize.1M128.build.flash_size=1M -generic.menu.FlashSize.1M128.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -generic.menu.FlashSize.1M128.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M128.upload.maximum_size=892912 -generic.menu.FlashSize.1M128.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -generic.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M144=1M (144K SPIFFS) -generic.menu.FlashSize.1M144.build.flash_size=1M -generic.menu.FlashSize.1M144.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -generic.menu.FlashSize.1M144.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M144.upload.maximum_size=876528 -generic.menu.FlashSize.1M144.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -generic.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M160=1M (160K SPIFFS) -generic.menu.FlashSize.1M160.build.flash_size=1M -generic.menu.FlashSize.1M160.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -generic.menu.FlashSize.1M160.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M160.upload.maximum_size=860144 -generic.menu.FlashSize.1M160.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -generic.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M192=1M (192K SPIFFS) -generic.menu.FlashSize.1M192.build.flash_size=1M -generic.menu.FlashSize.1M192.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -generic.menu.FlashSize.1M192.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M192.upload.maximum_size=827376 -generic.menu.FlashSize.1M192.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -generic.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M256=1M (256K SPIFFS) -generic.menu.FlashSize.1M256.build.flash_size=1M -generic.menu.FlashSize.1M256.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -generic.menu.FlashSize.1M256.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M256.upload.maximum_size=761840 -generic.menu.FlashSize.1M256.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -generic.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M512=1M (512K SPIFFS) -generic.menu.FlashSize.1M512.build.flash_size=1M -generic.menu.FlashSize.1M512.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -generic.menu.FlashSize.1M512.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M512.upload.maximum_size=499696 -generic.menu.FlashSize.1M512.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -generic.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -generic.menu.FlashSize.2M=2M (1M SPIFFS) -generic.menu.FlashSize.2M.build.flash_size=2M -generic.menu.FlashSize.2M.build.flash_size_bytes=0x200000 -generic.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -generic.menu.FlashSize.2M.build.spiffs_pagesize=256 -generic.menu.FlashSize.2M.upload.maximum_size=1044464 -generic.menu.FlashSize.2M.build.rfcal_addr=0x1FC000 -generic.menu.FlashSize.2M.build.spiffs_start=0x100000 -generic.menu.FlashSize.2M.build.spiffs_end=0x1FB000 -generic.menu.FlashSize.2M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.4M1M=4M (1M SPIFFS) -generic.menu.FlashSize.4M1M.build.flash_size=4M -generic.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -generic.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -generic.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -generic.menu.FlashSize.4M1M.upload.maximum_size=1044464 -generic.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -generic.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -generic.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -generic.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.4M3M=4M (3M SPIFFS) -generic.menu.FlashSize.4M3M.build.flash_size=4M -generic.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -generic.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -generic.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -generic.menu.FlashSize.4M3M.upload.maximum_size=1044464 -generic.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -generic.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -generic.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -generic.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.8M7M=8M (7M SPIFFS) -generic.menu.FlashSize.8M7M.build.flash_size=8M -generic.menu.FlashSize.8M7M.build.flash_size_bytes=0x800000 -generic.menu.FlashSize.8M7M.build.flash_ld=eagle.flash.8m.ld -generic.menu.FlashSize.8M7M.build.spiffs_pagesize=256 -generic.menu.FlashSize.8M7M.upload.maximum_size=1044464 -generic.menu.FlashSize.8M7M.build.rfcal_addr=0x7FC000 -generic.menu.FlashSize.8M7M.build.spiffs_start=0x100000 -generic.menu.FlashSize.8M7M.build.spiffs_end=0x7FB000 -generic.menu.FlashSize.8M7M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.16M15M=16M (15M SPIFFS) -generic.menu.FlashSize.16M15M.build.flash_size=16M -generic.menu.FlashSize.16M15M.build.flash_size_bytes=0x1000000 -generic.menu.FlashSize.16M15M.build.flash_ld=eagle.flash.16m.ld -generic.menu.FlashSize.16M15M.build.spiffs_pagesize=256 -generic.menu.FlashSize.16M15M.upload.maximum_size=1044464 -generic.menu.FlashSize.16M15M.build.rfcal_addr=0xFFC000 -generic.menu.FlashSize.16M15M.build.spiffs_start=0x100000 -generic.menu.FlashSize.16M15M.build.spiffs_end=0xFFB000 -generic.menu.FlashSize.16M15M.build.spiffs_blocksize=8192 -generic.menu.led.2=2 -generic.menu.led.2.build.led=-DLED_BUILTIN=2 -generic.menu.led.0=0 -generic.menu.led.0.build.led=-DLED_BUILTIN=0 -generic.menu.led.1=1 -generic.menu.led.1.build.led=-DLED_BUILTIN=1 -generic.menu.led.3=3 -generic.menu.led.3.build.led=-DLED_BUILTIN=3 -generic.menu.led.4=4 -generic.menu.led.4.build.led=-DLED_BUILTIN=4 -generic.menu.led.5=5 -generic.menu.led.5.build.led=-DLED_BUILTIN=5 -generic.menu.led.6=6 -generic.menu.led.6.build.led=-DLED_BUILTIN=6 -generic.menu.led.7=7 -generic.menu.led.7.build.led=-DLED_BUILTIN=7 -generic.menu.led.8=8 -generic.menu.led.8.build.led=-DLED_BUILTIN=8 -generic.menu.led.9=9 -generic.menu.led.9.build.led=-DLED_BUILTIN=9 -generic.menu.led.10=10 -generic.menu.led.10.build.led=-DLED_BUILTIN=10 -generic.menu.led.11=11 -generic.menu.led.11.build.led=-DLED_BUILTIN=11 -generic.menu.led.12=12 -generic.menu.led.12.build.led=-DLED_BUILTIN=12 -generic.menu.led.13=13 -generic.menu.led.13.build.led=-DLED_BUILTIN=13 -generic.menu.led.14=14 -generic.menu.led.14.build.led=-DLED_BUILTIN=14 -generic.menu.led.15=15 -generic.menu.led.15.build.led=-DLED_BUILTIN=15 -generic.menu.LwIPVariant.v2mss536=v2 Lower Memory -generic.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -generic.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -generic.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -generic.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -generic.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -generic.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -generic.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -generic.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -generic.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -generic.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.LwIPVariant.OpenSource=v1.4 Compile from source -generic.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -generic.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -generic.menu.Debug.Disabled=Disabled -generic.menu.Debug.Disabled.build.debug_port= -generic.menu.Debug.Serial=Serial -generic.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -generic.menu.Debug.Serial1=Serial1 -generic.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -generic.menu.DebugLevel.None____=None -generic.menu.DebugLevel.None____.build.debug_level= -generic.menu.DebugLevel.SSL=SSL -generic.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -generic.menu.DebugLevel.TLS_MEM=TLS_MEM -generic.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -generic.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -generic.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -generic.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -generic.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -generic.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -generic.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -generic.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.CORE=CORE -generic.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -generic.menu.DebugLevel.WIFI=WIFI -generic.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -generic.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -generic.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -generic.menu.DebugLevel.UPDATER=UPDATER -generic.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -generic.menu.DebugLevel.OTA=OTA -generic.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -generic.menu.DebugLevel.OOM=OOM -generic.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -generic.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -generic.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -generic.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -generic.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -generic.menu.FlashErase.none=Only Sketch -generic.menu.FlashErase.none.upload.erase_cmd= -generic.menu.FlashErase.sdk=Sketch + WiFi Settings -generic.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -generic.menu.FlashErase.all=All Flash Contents -generic.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -generic.menu.UploadSpeed.115200=115200 -generic.menu.UploadSpeed.115200.upload.speed=115200 -generic.menu.UploadSpeed.9600=9600 -generic.menu.UploadSpeed.9600.upload.speed=9600 -generic.menu.UploadSpeed.57600=57600 -generic.menu.UploadSpeed.57600.upload.speed=57600 -generic.menu.UploadSpeed.230400.linux=230400 -generic.menu.UploadSpeed.230400.macosx=230400 -generic.menu.UploadSpeed.230400.upload.speed=230400 -generic.menu.UploadSpeed.256000.windows=256000 -generic.menu.UploadSpeed.256000.upload.speed=256000 -generic.menu.UploadSpeed.460800.linux=460800 -generic.menu.UploadSpeed.460800.macosx=460800 -generic.menu.UploadSpeed.460800.upload.speed=460800 -generic.menu.UploadSpeed.512000.windows=512000 -generic.menu.UploadSpeed.512000.upload.speed=512000 -generic.menu.UploadSpeed.921600=921600 -generic.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -esp8285.name=Generic ESP8285 Module -esp8285.build.board=ESP8266_ESP01 -esp8285.upload.tool=esptool -esp8285.upload.maximum_data_size=81920 -esp8285.upload.wait_for_upload_port=true -esp8285.upload.erase_cmd= -esp8285.serial.disableDTR=true -esp8285.serial.disableRTS=true -esp8285.build.mcu=esp8266 -esp8285.build.core=esp8266 -esp8285.build.variant=generic -esp8285.build.spiffs_pagesize=256 -esp8285.build.debug_port= -esp8285.build.debug_level= -esp8285.menu.CpuFrequency.80=80 MHz -esp8285.menu.CpuFrequency.80.build.f_cpu=80000000L -esp8285.menu.CpuFrequency.160=160 MHz -esp8285.menu.CpuFrequency.160.build.f_cpu=160000000L -esp8285.menu.ResetMethod.ck=ck -esp8285.menu.ResetMethod.ck.upload.resetmethod=ck -esp8285.menu.ResetMethod.nodemcu=nodemcu -esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -esp8285.menu.ResetMethod.none=none -esp8285.menu.ResetMethod.none.upload.resetmethod=none -esp8285.menu.ResetMethod.dtrset=dtrset -esp8285.menu.ResetMethod.dtrset.upload.resetmethod=dtrset -esp8285.menu.CrystalFreq.26=26 MHz -esp8285.menu.CrystalFreq.40=40 MHz -esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -esp8285.build.flash_mode=dout -esp8285.build.flash_freq=40 -esp8285.menu.FlashSize.1M0=1M (no SPIFFS) -esp8285.menu.FlashSize.1M0.build.flash_size=1M -esp8285.menu.FlashSize.1M0.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -esp8285.menu.FlashSize.1M0.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M0.upload.maximum_size=1023984 -esp8285.menu.FlashSize.1M0.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M64=1M (64K SPIFFS) -esp8285.menu.FlashSize.1M64.build.flash_size=1M -esp8285.menu.FlashSize.1M64.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -esp8285.menu.FlashSize.1M64.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M64.upload.maximum_size=958448 -esp8285.menu.FlashSize.1M64.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -esp8285.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M128=1M (128K SPIFFS) -esp8285.menu.FlashSize.1M128.build.flash_size=1M -esp8285.menu.FlashSize.1M128.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -esp8285.menu.FlashSize.1M128.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M128.upload.maximum_size=892912 -esp8285.menu.FlashSize.1M128.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -esp8285.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M144=1M (144K SPIFFS) -esp8285.menu.FlashSize.1M144.build.flash_size=1M -esp8285.menu.FlashSize.1M144.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -esp8285.menu.FlashSize.1M144.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M144.upload.maximum_size=876528 -esp8285.menu.FlashSize.1M144.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -esp8285.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M160=1M (160K SPIFFS) -esp8285.menu.FlashSize.1M160.build.flash_size=1M -esp8285.menu.FlashSize.1M160.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -esp8285.menu.FlashSize.1M160.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M160.upload.maximum_size=860144 -esp8285.menu.FlashSize.1M160.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -esp8285.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M192=1M (192K SPIFFS) -esp8285.menu.FlashSize.1M192.build.flash_size=1M -esp8285.menu.FlashSize.1M192.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -esp8285.menu.FlashSize.1M192.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M192.upload.maximum_size=827376 -esp8285.menu.FlashSize.1M192.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -esp8285.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M256=1M (256K SPIFFS) -esp8285.menu.FlashSize.1M256.build.flash_size=1M -esp8285.menu.FlashSize.1M256.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -esp8285.menu.FlashSize.1M256.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M256.upload.maximum_size=761840 -esp8285.menu.FlashSize.1M256.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -esp8285.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M512=1M (512K SPIFFS) -esp8285.menu.FlashSize.1M512.build.flash_size=1M -esp8285.menu.FlashSize.1M512.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -esp8285.menu.FlashSize.1M512.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M512.upload.maximum_size=499696 -esp8285.menu.FlashSize.1M512.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -esp8285.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -esp8285.menu.led.2=2 -esp8285.menu.led.2.build.led=-DLED_BUILTIN=2 -esp8285.menu.led.0=0 -esp8285.menu.led.0.build.led=-DLED_BUILTIN=0 -esp8285.menu.led.1=1 -esp8285.menu.led.1.build.led=-DLED_BUILTIN=1 -esp8285.menu.led.3=3 -esp8285.menu.led.3.build.led=-DLED_BUILTIN=3 -esp8285.menu.led.4=4 -esp8285.menu.led.4.build.led=-DLED_BUILTIN=4 -esp8285.menu.led.5=5 -esp8285.menu.led.5.build.led=-DLED_BUILTIN=5 -esp8285.menu.led.6=6 -esp8285.menu.led.6.build.led=-DLED_BUILTIN=6 -esp8285.menu.led.7=7 -esp8285.menu.led.7.build.led=-DLED_BUILTIN=7 -esp8285.menu.led.8=8 -esp8285.menu.led.8.build.led=-DLED_BUILTIN=8 -esp8285.menu.led.9=9 -esp8285.menu.led.9.build.led=-DLED_BUILTIN=9 -esp8285.menu.led.10=10 -esp8285.menu.led.10.build.led=-DLED_BUILTIN=10 -esp8285.menu.led.11=11 -esp8285.menu.led.11.build.led=-DLED_BUILTIN=11 -esp8285.menu.led.12=12 -esp8285.menu.led.12.build.led=-DLED_BUILTIN=12 -esp8285.menu.led.13=13 -esp8285.menu.led.13.build.led=-DLED_BUILTIN=13 -esp8285.menu.led.14=14 -esp8285.menu.led.14.build.led=-DLED_BUILTIN=14 -esp8285.menu.led.15=15 -esp8285.menu.led.15.build.led=-DLED_BUILTIN=15 -esp8285.menu.LwIPVariant.v2mss536=v2 Lower Memory -esp8285.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -esp8285.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -esp8285.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -esp8285.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -esp8285.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -esp8285.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -esp8285.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -esp8285.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -esp8285.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -esp8285.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.LwIPVariant.OpenSource=v1.4 Compile from source -esp8285.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -esp8285.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp8285.menu.Debug.Disabled=Disabled -esp8285.menu.Debug.Disabled.build.debug_port= -esp8285.menu.Debug.Serial=Serial -esp8285.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp8285.menu.Debug.Serial1=Serial1 -esp8285.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp8285.menu.DebugLevel.None____=None -esp8285.menu.DebugLevel.None____.build.debug_level= -esp8285.menu.DebugLevel.SSL=SSL -esp8285.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp8285.menu.DebugLevel.TLS_MEM=TLS_MEM -esp8285.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp8285.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -esp8285.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -esp8285.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -esp8285.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp8285.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp8285.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp8285.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.CORE=CORE -esp8285.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp8285.menu.DebugLevel.WIFI=WIFI -esp8285.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp8285.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -esp8285.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp8285.menu.DebugLevel.UPDATER=UPDATER -esp8285.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp8285.menu.DebugLevel.OTA=OTA -esp8285.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp8285.menu.DebugLevel.OOM=OOM -esp8285.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -esp8285.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp8285.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -esp8285.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -esp8285.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp8285.menu.FlashErase.none=Only Sketch -esp8285.menu.FlashErase.none.upload.erase_cmd= -esp8285.menu.FlashErase.sdk=Sketch + WiFi Settings -esp8285.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -esp8285.menu.FlashErase.all=All Flash Contents -esp8285.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -esp8285.menu.UploadSpeed.115200=115200 -esp8285.menu.UploadSpeed.115200.upload.speed=115200 -esp8285.menu.UploadSpeed.9600=9600 -esp8285.menu.UploadSpeed.9600.upload.speed=9600 -esp8285.menu.UploadSpeed.57600=57600 -esp8285.menu.UploadSpeed.57600.upload.speed=57600 -esp8285.menu.UploadSpeed.230400.linux=230400 -esp8285.menu.UploadSpeed.230400.macosx=230400 -esp8285.menu.UploadSpeed.230400.upload.speed=230400 -esp8285.menu.UploadSpeed.256000.windows=256000 -esp8285.menu.UploadSpeed.256000.upload.speed=256000 -esp8285.menu.UploadSpeed.460800.linux=460800 -esp8285.menu.UploadSpeed.460800.macosx=460800 -esp8285.menu.UploadSpeed.460800.upload.speed=460800 -esp8285.menu.UploadSpeed.512000.windows=512000 -esp8285.menu.UploadSpeed.512000.upload.speed=512000 -esp8285.menu.UploadSpeed.921600=921600 -esp8285.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espduino.name=ESPDuino (ESP-13 Module) -espduino.build.board=ESP8266_ESP13 -espduino.build.variant=ESPDuino -espduino.menu.ResetMethod.v2=ESPduino-V2 -espduino.menu.ResetMethod.v2.upload.resetmethod=nodemcu -espduino.menu.ResetMethod.v1=ESPduino-V1 -espduino.menu.ResetMethod.v1.upload.resetmethod=ck -espduino.menu.UploadTool.esptool=Serial -espduino.menu.UploadTool.esptool.upload.tool=esptool -espduino.menu.UploadTool.esptool.upload.verbose=-vv -espduino.menu.UploadTool.espota=OTA -espduino.menu.UploadTool.espota.upload.tool=espota -espduino.upload.tool=esptool -espduino.upload.maximum_data_size=81920 -espduino.upload.wait_for_upload_port=true -espduino.upload.erase_cmd= -espduino.serial.disableDTR=true -espduino.serial.disableRTS=true -espduino.build.mcu=esp8266 -espduino.build.core=esp8266 -espduino.build.spiffs_pagesize=256 -espduino.build.debug_port= -espduino.build.debug_level= -espduino.menu.CpuFrequency.80=80 MHz -espduino.menu.CpuFrequency.80.build.f_cpu=80000000L -espduino.menu.CpuFrequency.160=160 MHz -espduino.menu.CpuFrequency.160.build.f_cpu=160000000L -espduino.build.flash_mode=dio -espduino.build.flash_freq=40 -espduino.menu.FlashSize.4M1M=4M (1M SPIFFS) -espduino.menu.FlashSize.4M1M.build.flash_size=4M -espduino.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espduino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espduino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espduino.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espduino.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espduino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espduino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espduino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espduino.menu.FlashSize.4M3M=4M (3M SPIFFS) -espduino.menu.FlashSize.4M3M.build.flash_size=4M -espduino.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espduino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espduino.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espduino.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espduino.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espduino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espduino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espduino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espduino.menu.LwIPVariant.v2mss536=v2 Lower Memory -espduino.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espduino.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espduino.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espduino.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espduino.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espduino.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espduino.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espduino.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espduino.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espduino.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espduino.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espduino.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espduino.menu.Debug.Disabled=Disabled -espduino.menu.Debug.Disabled.build.debug_port= -espduino.menu.Debug.Serial=Serial -espduino.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espduino.menu.Debug.Serial1=Serial1 -espduino.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espduino.menu.DebugLevel.None____=None -espduino.menu.DebugLevel.None____.build.debug_level= -espduino.menu.DebugLevel.SSL=SSL -espduino.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espduino.menu.DebugLevel.TLS_MEM=TLS_MEM -espduino.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espduino.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espduino.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espduino.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espduino.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espduino.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espduino.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espduino.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.CORE=CORE -espduino.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espduino.menu.DebugLevel.WIFI=WIFI -espduino.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espduino.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espduino.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espduino.menu.DebugLevel.UPDATER=UPDATER -espduino.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espduino.menu.DebugLevel.OTA=OTA -espduino.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espduino.menu.DebugLevel.OOM=OOM -espduino.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espduino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espduino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espduino.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espduino.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espduino.menu.FlashErase.none=Only Sketch -espduino.menu.FlashErase.none.upload.erase_cmd= -espduino.menu.FlashErase.sdk=Sketch + WiFi Settings -espduino.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espduino.menu.FlashErase.all=All Flash Contents -espduino.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espduino.menu.UploadSpeed.115200=115200 -espduino.menu.UploadSpeed.115200.upload.speed=115200 -espduino.menu.UploadSpeed.9600=9600 -espduino.menu.UploadSpeed.9600.upload.speed=9600 -espduino.menu.UploadSpeed.57600=57600 -espduino.menu.UploadSpeed.57600.upload.speed=57600 -espduino.menu.UploadSpeed.230400.linux=230400 -espduino.menu.UploadSpeed.230400.macosx=230400 -espduino.menu.UploadSpeed.230400.upload.speed=230400 -espduino.menu.UploadSpeed.256000.windows=256000 -espduino.menu.UploadSpeed.256000.upload.speed=256000 -espduino.menu.UploadSpeed.460800.linux=460800 -espduino.menu.UploadSpeed.460800.macosx=460800 -espduino.menu.UploadSpeed.460800.upload.speed=460800 -espduino.menu.UploadSpeed.512000.windows=512000 -espduino.menu.UploadSpeed.512000.upload.speed=512000 -espduino.menu.UploadSpeed.921600=921600 -espduino.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -huzzah.name=Adafruit Feather HUZZAH ESP8266 -huzzah.build.board=ESP8266_ESP12 -huzzah.build.variant=adafruit -huzzah.upload.tool=esptool -huzzah.upload.maximum_data_size=81920 -huzzah.upload.wait_for_upload_port=true -huzzah.upload.erase_cmd= -huzzah.serial.disableDTR=true -huzzah.serial.disableRTS=true -huzzah.build.mcu=esp8266 -huzzah.build.core=esp8266 -huzzah.build.spiffs_pagesize=256 -huzzah.build.debug_port= -huzzah.build.debug_level= -huzzah.menu.CpuFrequency.80=80 MHz -huzzah.menu.CpuFrequency.80.build.f_cpu=80000000L -huzzah.menu.CpuFrequency.160=160 MHz -huzzah.menu.CpuFrequency.160.build.f_cpu=160000000L -huzzah.upload.resetmethod=nodemcu -huzzah.build.flash_mode=qio -huzzah.build.flash_freq=40 -huzzah.menu.FlashSize.4M1M=4M (1M SPIFFS) -huzzah.menu.FlashSize.4M1M.build.flash_size=4M -huzzah.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -huzzah.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -huzzah.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -huzzah.menu.FlashSize.4M1M.upload.maximum_size=1044464 -huzzah.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -huzzah.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -huzzah.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -huzzah.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -huzzah.menu.FlashSize.4M3M=4M (3M SPIFFS) -huzzah.menu.FlashSize.4M3M.build.flash_size=4M -huzzah.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -huzzah.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -huzzah.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -huzzah.menu.FlashSize.4M3M.upload.maximum_size=1044464 -huzzah.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -huzzah.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -huzzah.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -huzzah.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -huzzah.menu.LwIPVariant.v2mss536=v2 Lower Memory -huzzah.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -huzzah.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -huzzah.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -huzzah.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -huzzah.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -huzzah.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -huzzah.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -huzzah.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -huzzah.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -huzzah.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.LwIPVariant.OpenSource=v1.4 Compile from source -huzzah.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -huzzah.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -huzzah.menu.Debug.Disabled=Disabled -huzzah.menu.Debug.Disabled.build.debug_port= -huzzah.menu.Debug.Serial=Serial -huzzah.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -huzzah.menu.Debug.Serial1=Serial1 -huzzah.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -huzzah.menu.DebugLevel.None____=None -huzzah.menu.DebugLevel.None____.build.debug_level= -huzzah.menu.DebugLevel.SSL=SSL -huzzah.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -huzzah.menu.DebugLevel.TLS_MEM=TLS_MEM -huzzah.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -huzzah.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -huzzah.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -huzzah.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -huzzah.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -huzzah.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -huzzah.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -huzzah.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.CORE=CORE -huzzah.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -huzzah.menu.DebugLevel.WIFI=WIFI -huzzah.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -huzzah.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -huzzah.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -huzzah.menu.DebugLevel.UPDATER=UPDATER -huzzah.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -huzzah.menu.DebugLevel.OTA=OTA -huzzah.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -huzzah.menu.DebugLevel.OOM=OOM -huzzah.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -huzzah.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -huzzah.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -huzzah.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -huzzah.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -huzzah.menu.FlashErase.none=Only Sketch -huzzah.menu.FlashErase.none.upload.erase_cmd= -huzzah.menu.FlashErase.sdk=Sketch + WiFi Settings -huzzah.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -huzzah.menu.FlashErase.all=All Flash Contents -huzzah.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -huzzah.menu.UploadSpeed.115200=115200 -huzzah.menu.UploadSpeed.115200.upload.speed=115200 -huzzah.menu.UploadSpeed.9600=9600 -huzzah.menu.UploadSpeed.9600.upload.speed=9600 -huzzah.menu.UploadSpeed.57600=57600 -huzzah.menu.UploadSpeed.57600.upload.speed=57600 -huzzah.menu.UploadSpeed.230400.linux=230400 -huzzah.menu.UploadSpeed.230400.macosx=230400 -huzzah.menu.UploadSpeed.230400.upload.speed=230400 -huzzah.menu.UploadSpeed.256000.windows=256000 -huzzah.menu.UploadSpeed.256000.upload.speed=256000 -huzzah.menu.UploadSpeed.460800.linux=460800 -huzzah.menu.UploadSpeed.460800.macosx=460800 -huzzah.menu.UploadSpeed.460800.upload.speed=460800 -huzzah.menu.UploadSpeed.512000.windows=512000 -huzzah.menu.UploadSpeed.512000.upload.speed=512000 -huzzah.menu.UploadSpeed.921600=921600 -huzzah.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espresso_lite_v1.name=ESPresso Lite 1.0 -espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 -espresso_lite_v1.build.variant=espresso_lite_v1 -espresso_lite_v1.upload.tool=esptool -espresso_lite_v1.upload.maximum_data_size=81920 -espresso_lite_v1.upload.wait_for_upload_port=true -espresso_lite_v1.upload.erase_cmd= -espresso_lite_v1.serial.disableDTR=true -espresso_lite_v1.serial.disableRTS=true -espresso_lite_v1.build.mcu=esp8266 -espresso_lite_v1.build.core=esp8266 -espresso_lite_v1.build.spiffs_pagesize=256 -espresso_lite_v1.build.debug_port= -espresso_lite_v1.build.debug_level= -espresso_lite_v1.menu.CpuFrequency.80=80 MHz -espresso_lite_v1.menu.CpuFrequency.80.build.f_cpu=80000000L -espresso_lite_v1.menu.CpuFrequency.160=160 MHz -espresso_lite_v1.menu.CpuFrequency.160.build.f_cpu=160000000L -espresso_lite_v1.build.flash_mode=dio -espresso_lite_v1.build.flash_freq=40 -espresso_lite_v1.menu.FlashSize.4M1M=4M (1M SPIFFS) -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_size=4M -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espresso_lite_v1.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.FlashSize.4M3M=4M (3M SPIFFS) -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_size=4M -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espresso_lite_v1.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.ResetMethod.ck=ck -espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v1.menu.LwIPVariant.v2mss536=v2 Lower Memory -espresso_lite_v1.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espresso_lite_v1.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espresso_lite_v1.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espresso_lite_v1.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espresso_lite_v1.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espresso_lite_v1.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espresso_lite_v1.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espresso_lite_v1.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espresso_lite_v1.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espresso_lite_v1.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espresso_lite_v1.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espresso_lite_v1.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v1.menu.Debug.Disabled=Disabled -espresso_lite_v1.menu.Debug.Disabled.build.debug_port= -espresso_lite_v1.menu.Debug.Serial=Serial -espresso_lite_v1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v1.menu.Debug.Serial1=Serial1 -espresso_lite_v1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v1.menu.DebugLevel.None____=None -espresso_lite_v1.menu.DebugLevel.None____.build.debug_level= -espresso_lite_v1.menu.DebugLevel.SSL=SSL -espresso_lite_v1.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v1.menu.DebugLevel.TLS_MEM=TLS_MEM -espresso_lite_v1.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.CORE=CORE -espresso_lite_v1.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v1.menu.DebugLevel.WIFI=WIFI -espresso_lite_v1.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v1.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v1.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v1.menu.DebugLevel.UPDATER=UPDATER -espresso_lite_v1.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v1.menu.DebugLevel.OTA=OTA -espresso_lite_v1.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v1.menu.DebugLevel.OOM=OOM -espresso_lite_v1.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espresso_lite_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espresso_lite_v1.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v1.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v1.menu.FlashErase.none=Only Sketch -espresso_lite_v1.menu.FlashErase.none.upload.erase_cmd= -espresso_lite_v1.menu.FlashErase.sdk=Sketch + WiFi Settings -espresso_lite_v1.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espresso_lite_v1.menu.FlashErase.all=All Flash Contents -espresso_lite_v1.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espresso_lite_v1.menu.UploadSpeed.115200=115200 -espresso_lite_v1.menu.UploadSpeed.115200.upload.speed=115200 -espresso_lite_v1.menu.UploadSpeed.9600=9600 -espresso_lite_v1.menu.UploadSpeed.9600.upload.speed=9600 -espresso_lite_v1.menu.UploadSpeed.57600=57600 -espresso_lite_v1.menu.UploadSpeed.57600.upload.speed=57600 -espresso_lite_v1.menu.UploadSpeed.230400.linux=230400 -espresso_lite_v1.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v1.menu.UploadSpeed.230400.upload.speed=230400 -espresso_lite_v1.menu.UploadSpeed.256000.windows=256000 -espresso_lite_v1.menu.UploadSpeed.256000.upload.speed=256000 -espresso_lite_v1.menu.UploadSpeed.460800.linux=460800 -espresso_lite_v1.menu.UploadSpeed.460800.macosx=460800 -espresso_lite_v1.menu.UploadSpeed.460800.upload.speed=460800 -espresso_lite_v1.menu.UploadSpeed.512000.windows=512000 -espresso_lite_v1.menu.UploadSpeed.512000.upload.speed=512000 -espresso_lite_v1.menu.UploadSpeed.921600=921600 -espresso_lite_v1.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espresso_lite_v2.name=ESPresso Lite 2.0 -espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 -espresso_lite_v2.build.variant=espresso_lite_v2 -espresso_lite_v2.upload.tool=esptool -espresso_lite_v2.upload.maximum_data_size=81920 -espresso_lite_v2.upload.wait_for_upload_port=true -espresso_lite_v2.upload.erase_cmd= -espresso_lite_v2.serial.disableDTR=true -espresso_lite_v2.serial.disableRTS=true -espresso_lite_v2.build.mcu=esp8266 -espresso_lite_v2.build.core=esp8266 -espresso_lite_v2.build.spiffs_pagesize=256 -espresso_lite_v2.build.debug_port= -espresso_lite_v2.build.debug_level= -espresso_lite_v2.menu.CpuFrequency.80=80 MHz -espresso_lite_v2.menu.CpuFrequency.80.build.f_cpu=80000000L -espresso_lite_v2.menu.CpuFrequency.160=160 MHz -espresso_lite_v2.menu.CpuFrequency.160.build.f_cpu=160000000L -espresso_lite_v2.build.flash_mode=dio -espresso_lite_v2.build.flash_freq=40 -espresso_lite_v2.menu.FlashSize.4M1M=4M (1M SPIFFS) -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_size=4M -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espresso_lite_v2.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.FlashSize.4M3M=4M (3M SPIFFS) -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_size=4M -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espresso_lite_v2.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.ResetMethod.ck=ck -espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v2.menu.LwIPVariant.v2mss536=v2 Lower Memory -espresso_lite_v2.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espresso_lite_v2.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espresso_lite_v2.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espresso_lite_v2.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espresso_lite_v2.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espresso_lite_v2.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espresso_lite_v2.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espresso_lite_v2.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espresso_lite_v2.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espresso_lite_v2.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espresso_lite_v2.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espresso_lite_v2.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v2.menu.Debug.Disabled=Disabled -espresso_lite_v2.menu.Debug.Disabled.build.debug_port= -espresso_lite_v2.menu.Debug.Serial=Serial -espresso_lite_v2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v2.menu.Debug.Serial1=Serial1 -espresso_lite_v2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v2.menu.DebugLevel.None____=None -espresso_lite_v2.menu.DebugLevel.None____.build.debug_level= -espresso_lite_v2.menu.DebugLevel.SSL=SSL -espresso_lite_v2.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v2.menu.DebugLevel.TLS_MEM=TLS_MEM -espresso_lite_v2.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.CORE=CORE -espresso_lite_v2.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v2.menu.DebugLevel.WIFI=WIFI -espresso_lite_v2.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v2.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v2.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v2.menu.DebugLevel.UPDATER=UPDATER -espresso_lite_v2.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v2.menu.DebugLevel.OTA=OTA -espresso_lite_v2.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v2.menu.DebugLevel.OOM=OOM -espresso_lite_v2.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espresso_lite_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espresso_lite_v2.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v2.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v2.menu.FlashErase.none=Only Sketch -espresso_lite_v2.menu.FlashErase.none.upload.erase_cmd= -espresso_lite_v2.menu.FlashErase.sdk=Sketch + WiFi Settings -espresso_lite_v2.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espresso_lite_v2.menu.FlashErase.all=All Flash Contents -espresso_lite_v2.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espresso_lite_v2.menu.UploadSpeed.115200=115200 -espresso_lite_v2.menu.UploadSpeed.115200.upload.speed=115200 -espresso_lite_v2.menu.UploadSpeed.9600=9600 -espresso_lite_v2.menu.UploadSpeed.9600.upload.speed=9600 -espresso_lite_v2.menu.UploadSpeed.57600=57600 -espresso_lite_v2.menu.UploadSpeed.57600.upload.speed=57600 -espresso_lite_v2.menu.UploadSpeed.230400.linux=230400 -espresso_lite_v2.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v2.menu.UploadSpeed.230400.upload.speed=230400 -espresso_lite_v2.menu.UploadSpeed.256000.windows=256000 -espresso_lite_v2.menu.UploadSpeed.256000.upload.speed=256000 -espresso_lite_v2.menu.UploadSpeed.460800.linux=460800 -espresso_lite_v2.menu.UploadSpeed.460800.macosx=460800 -espresso_lite_v2.menu.UploadSpeed.460800.upload.speed=460800 -espresso_lite_v2.menu.UploadSpeed.512000.windows=512000 -espresso_lite_v2.menu.UploadSpeed.512000.upload.speed=512000 -espresso_lite_v2.menu.UploadSpeed.921600=921600 -espresso_lite_v2.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -phoenix_v1.name=Phoenix 1.0 -phoenix_v1.build.board=ESP8266_PHOENIX_V1 -phoenix_v1.build.variant=phoenix_v1 -phoenix_v1.upload.tool=esptool -phoenix_v1.upload.maximum_data_size=81920 -phoenix_v1.upload.wait_for_upload_port=true -phoenix_v1.upload.erase_cmd= -phoenix_v1.serial.disableDTR=true -phoenix_v1.serial.disableRTS=true -phoenix_v1.build.mcu=esp8266 -phoenix_v1.build.core=esp8266 -phoenix_v1.build.spiffs_pagesize=256 -phoenix_v1.build.debug_port= -phoenix_v1.build.debug_level= -phoenix_v1.menu.CpuFrequency.80=80 MHz -phoenix_v1.menu.CpuFrequency.80.build.f_cpu=80000000L -phoenix_v1.menu.CpuFrequency.160=160 MHz -phoenix_v1.menu.CpuFrequency.160.build.f_cpu=160000000L -phoenix_v1.build.flash_mode=dio -phoenix_v1.build.flash_freq=40 -phoenix_v1.menu.FlashSize.4M1M=4M (1M SPIFFS) -phoenix_v1.menu.FlashSize.4M1M.build.flash_size=4M -phoenix_v1.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -phoenix_v1.menu.FlashSize.4M1M.upload.maximum_size=1044464 -phoenix_v1.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -phoenix_v1.menu.FlashSize.4M3M=4M (3M SPIFFS) -phoenix_v1.menu.FlashSize.4M3M.build.flash_size=4M -phoenix_v1.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -phoenix_v1.menu.FlashSize.4M3M.upload.maximum_size=1044464 -phoenix_v1.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -phoenix_v1.menu.ResetMethod.ck=ck -phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v1.menu.ResetMethod.nodemcu=nodemcu -phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v1.menu.LwIPVariant.v2mss536=v2 Lower Memory -phoenix_v1.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -phoenix_v1.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -phoenix_v1.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -phoenix_v1.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -phoenix_v1.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -phoenix_v1.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -phoenix_v1.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -phoenix_v1.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -phoenix_v1.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -phoenix_v1.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.LwIPVariant.OpenSource=v1.4 Compile from source -phoenix_v1.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -phoenix_v1.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v1.menu.Debug.Disabled=Disabled -phoenix_v1.menu.Debug.Disabled.build.debug_port= -phoenix_v1.menu.Debug.Serial=Serial -phoenix_v1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v1.menu.Debug.Serial1=Serial1 -phoenix_v1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v1.menu.DebugLevel.None____=None -phoenix_v1.menu.DebugLevel.None____.build.debug_level= -phoenix_v1.menu.DebugLevel.SSL=SSL -phoenix_v1.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v1.menu.DebugLevel.TLS_MEM=TLS_MEM -phoenix_v1.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -phoenix_v1.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -phoenix_v1.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v1.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.CORE=CORE -phoenix_v1.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v1.menu.DebugLevel.WIFI=WIFI -phoenix_v1.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v1.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -phoenix_v1.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v1.menu.DebugLevel.UPDATER=UPDATER -phoenix_v1.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v1.menu.DebugLevel.OTA=OTA -phoenix_v1.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v1.menu.DebugLevel.OOM=OOM -phoenix_v1.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -phoenix_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -phoenix_v1.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v1.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v1.menu.FlashErase.none=Only Sketch -phoenix_v1.menu.FlashErase.none.upload.erase_cmd= -phoenix_v1.menu.FlashErase.sdk=Sketch + WiFi Settings -phoenix_v1.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -phoenix_v1.menu.FlashErase.all=All Flash Contents -phoenix_v1.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -phoenix_v1.menu.UploadSpeed.115200=115200 -phoenix_v1.menu.UploadSpeed.115200.upload.speed=115200 -phoenix_v1.menu.UploadSpeed.9600=9600 -phoenix_v1.menu.UploadSpeed.9600.upload.speed=9600 -phoenix_v1.menu.UploadSpeed.57600=57600 -phoenix_v1.menu.UploadSpeed.57600.upload.speed=57600 -phoenix_v1.menu.UploadSpeed.230400.linux=230400 -phoenix_v1.menu.UploadSpeed.230400.macosx=230400 -phoenix_v1.menu.UploadSpeed.230400.upload.speed=230400 -phoenix_v1.menu.UploadSpeed.256000.windows=256000 -phoenix_v1.menu.UploadSpeed.256000.upload.speed=256000 -phoenix_v1.menu.UploadSpeed.460800.linux=460800 -phoenix_v1.menu.UploadSpeed.460800.macosx=460800 -phoenix_v1.menu.UploadSpeed.460800.upload.speed=460800 -phoenix_v1.menu.UploadSpeed.512000.windows=512000 -phoenix_v1.menu.UploadSpeed.512000.upload.speed=512000 -phoenix_v1.menu.UploadSpeed.921600=921600 -phoenix_v1.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -phoenix_v2.name=Phoenix 2.0 -phoenix_v2.build.board=ESP8266_PHOENIX_V2 -phoenix_v2.build.variant=phoenix_v2 -phoenix_v2.upload.tool=esptool -phoenix_v2.upload.maximum_data_size=81920 -phoenix_v2.upload.wait_for_upload_port=true -phoenix_v2.upload.erase_cmd= -phoenix_v2.serial.disableDTR=true -phoenix_v2.serial.disableRTS=true -phoenix_v2.build.mcu=esp8266 -phoenix_v2.build.core=esp8266 -phoenix_v2.build.spiffs_pagesize=256 -phoenix_v2.build.debug_port= -phoenix_v2.build.debug_level= -phoenix_v2.menu.CpuFrequency.80=80 MHz -phoenix_v2.menu.CpuFrequency.80.build.f_cpu=80000000L -phoenix_v2.menu.CpuFrequency.160=160 MHz -phoenix_v2.menu.CpuFrequency.160.build.f_cpu=160000000L -phoenix_v2.build.flash_mode=dio -phoenix_v2.build.flash_freq=40 -phoenix_v2.menu.FlashSize.4M1M=4M (1M SPIFFS) -phoenix_v2.menu.FlashSize.4M1M.build.flash_size=4M -phoenix_v2.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -phoenix_v2.menu.FlashSize.4M1M.upload.maximum_size=1044464 -phoenix_v2.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -phoenix_v2.menu.FlashSize.4M3M=4M (3M SPIFFS) -phoenix_v2.menu.FlashSize.4M3M.build.flash_size=4M -phoenix_v2.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -phoenix_v2.menu.FlashSize.4M3M.upload.maximum_size=1044464 -phoenix_v2.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -phoenix_v2.menu.ResetMethod.ck=ck -phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v2.menu.ResetMethod.nodemcu=nodemcu -phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v2.menu.LwIPVariant.v2mss536=v2 Lower Memory -phoenix_v2.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -phoenix_v2.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -phoenix_v2.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -phoenix_v2.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -phoenix_v2.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -phoenix_v2.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -phoenix_v2.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -phoenix_v2.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -phoenix_v2.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -phoenix_v2.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.LwIPVariant.OpenSource=v1.4 Compile from source -phoenix_v2.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -phoenix_v2.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v2.menu.Debug.Disabled=Disabled -phoenix_v2.menu.Debug.Disabled.build.debug_port= -phoenix_v2.menu.Debug.Serial=Serial -phoenix_v2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v2.menu.Debug.Serial1=Serial1 -phoenix_v2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v2.menu.DebugLevel.None____=None -phoenix_v2.menu.DebugLevel.None____.build.debug_level= -phoenix_v2.menu.DebugLevel.SSL=SSL -phoenix_v2.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v2.menu.DebugLevel.TLS_MEM=TLS_MEM -phoenix_v2.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -phoenix_v2.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -phoenix_v2.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v2.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.CORE=CORE -phoenix_v2.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v2.menu.DebugLevel.WIFI=WIFI -phoenix_v2.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v2.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -phoenix_v2.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v2.menu.DebugLevel.UPDATER=UPDATER -phoenix_v2.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v2.menu.DebugLevel.OTA=OTA -phoenix_v2.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v2.menu.DebugLevel.OOM=OOM -phoenix_v2.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -phoenix_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -phoenix_v2.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v2.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v2.menu.FlashErase.none=Only Sketch -phoenix_v2.menu.FlashErase.none.upload.erase_cmd= -phoenix_v2.menu.FlashErase.sdk=Sketch + WiFi Settings -phoenix_v2.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -phoenix_v2.menu.FlashErase.all=All Flash Contents -phoenix_v2.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -phoenix_v2.menu.UploadSpeed.115200=115200 -phoenix_v2.menu.UploadSpeed.115200.upload.speed=115200 -phoenix_v2.menu.UploadSpeed.9600=9600 -phoenix_v2.menu.UploadSpeed.9600.upload.speed=9600 -phoenix_v2.menu.UploadSpeed.57600=57600 -phoenix_v2.menu.UploadSpeed.57600.upload.speed=57600 -phoenix_v2.menu.UploadSpeed.230400.linux=230400 -phoenix_v2.menu.UploadSpeed.230400.macosx=230400 -phoenix_v2.menu.UploadSpeed.230400.upload.speed=230400 -phoenix_v2.menu.UploadSpeed.256000.windows=256000 -phoenix_v2.menu.UploadSpeed.256000.upload.speed=256000 -phoenix_v2.menu.UploadSpeed.460800.linux=460800 -phoenix_v2.menu.UploadSpeed.460800.macosx=460800 -phoenix_v2.menu.UploadSpeed.460800.upload.speed=460800 -phoenix_v2.menu.UploadSpeed.512000.windows=512000 -phoenix_v2.menu.UploadSpeed.512000.upload.speed=512000 -phoenix_v2.menu.UploadSpeed.921600=921600 -phoenix_v2.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -nodemcu.name=NodeMCU 0.9 (ESP-12 Module) -nodemcu.build.board=ESP8266_NODEMCU -nodemcu.build.variant=nodemcu -nodemcu.upload.tool=esptool -nodemcu.upload.maximum_data_size=81920 -nodemcu.upload.wait_for_upload_port=true -nodemcu.upload.erase_cmd= -nodemcu.serial.disableDTR=true -nodemcu.serial.disableRTS=true -nodemcu.build.mcu=esp8266 -nodemcu.build.core=esp8266 -nodemcu.build.spiffs_pagesize=256 -nodemcu.build.debug_port= -nodemcu.build.debug_level= -nodemcu.menu.CpuFrequency.80=80 MHz -nodemcu.menu.CpuFrequency.80.build.f_cpu=80000000L -nodemcu.menu.CpuFrequency.160=160 MHz -nodemcu.menu.CpuFrequency.160.build.f_cpu=160000000L -nodemcu.upload.resetmethod=nodemcu -nodemcu.build.flash_mode=qio -nodemcu.build.flash_freq=40 -nodemcu.menu.FlashSize.4M1M=4M (1M SPIFFS) -nodemcu.menu.FlashSize.4M1M.build.flash_size=4M -nodemcu.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -nodemcu.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcu.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -nodemcu.menu.FlashSize.4M1M.upload.maximum_size=1044464 -nodemcu.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -nodemcu.menu.FlashSize.4M3M=4M (3M SPIFFS) -nodemcu.menu.FlashSize.4M3M.build.flash_size=4M -nodemcu.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -nodemcu.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -nodemcu.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -nodemcu.menu.FlashSize.4M3M.upload.maximum_size=1044464 -nodemcu.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -nodemcu.menu.LwIPVariant.v2mss536=v2 Lower Memory -nodemcu.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -nodemcu.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -nodemcu.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -nodemcu.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -nodemcu.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -nodemcu.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -nodemcu.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -nodemcu.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -nodemcu.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -nodemcu.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.LwIPVariant.OpenSource=v1.4 Compile from source -nodemcu.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -nodemcu.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcu.menu.Debug.Disabled=Disabled -nodemcu.menu.Debug.Disabled.build.debug_port= -nodemcu.menu.Debug.Serial=Serial -nodemcu.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcu.menu.Debug.Serial1=Serial1 -nodemcu.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcu.menu.DebugLevel.None____=None -nodemcu.menu.DebugLevel.None____.build.debug_level= -nodemcu.menu.DebugLevel.SSL=SSL -nodemcu.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcu.menu.DebugLevel.TLS_MEM=TLS_MEM -nodemcu.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcu.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -nodemcu.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -nodemcu.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -nodemcu.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcu.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.CORE=CORE -nodemcu.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcu.menu.DebugLevel.WIFI=WIFI -nodemcu.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcu.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -nodemcu.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcu.menu.DebugLevel.UPDATER=UPDATER -nodemcu.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcu.menu.DebugLevel.OTA=OTA -nodemcu.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcu.menu.DebugLevel.OOM=OOM -nodemcu.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -nodemcu.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcu.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -nodemcu.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcu.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcu.menu.FlashErase.none=Only Sketch -nodemcu.menu.FlashErase.none.upload.erase_cmd= -nodemcu.menu.FlashErase.sdk=Sketch + WiFi Settings -nodemcu.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -nodemcu.menu.FlashErase.all=All Flash Contents -nodemcu.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -nodemcu.menu.UploadSpeed.115200=115200 -nodemcu.menu.UploadSpeed.115200.upload.speed=115200 -nodemcu.menu.UploadSpeed.9600=9600 -nodemcu.menu.UploadSpeed.9600.upload.speed=9600 -nodemcu.menu.UploadSpeed.57600=57600 -nodemcu.menu.UploadSpeed.57600.upload.speed=57600 -nodemcu.menu.UploadSpeed.230400.linux=230400 -nodemcu.menu.UploadSpeed.230400.macosx=230400 -nodemcu.menu.UploadSpeed.230400.upload.speed=230400 -nodemcu.menu.UploadSpeed.256000.windows=256000 -nodemcu.menu.UploadSpeed.256000.upload.speed=256000 -nodemcu.menu.UploadSpeed.460800.linux=460800 -nodemcu.menu.UploadSpeed.460800.macosx=460800 -nodemcu.menu.UploadSpeed.460800.upload.speed=460800 -nodemcu.menu.UploadSpeed.512000.windows=512000 -nodemcu.menu.UploadSpeed.512000.upload.speed=512000 -nodemcu.menu.UploadSpeed.921600=921600 -nodemcu.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) -nodemcuv2.build.board=ESP8266_NODEMCU -nodemcuv2.build.variant=nodemcu -nodemcuv2.upload.tool=esptool -nodemcuv2.upload.maximum_data_size=81920 -nodemcuv2.upload.wait_for_upload_port=true -nodemcuv2.upload.erase_cmd= -nodemcuv2.serial.disableDTR=true -nodemcuv2.serial.disableRTS=true -nodemcuv2.build.mcu=esp8266 -nodemcuv2.build.core=esp8266 -nodemcuv2.build.spiffs_pagesize=256 -nodemcuv2.build.debug_port= -nodemcuv2.build.debug_level= -nodemcuv2.menu.CpuFrequency.80=80 MHz -nodemcuv2.menu.CpuFrequency.80.build.f_cpu=80000000L -nodemcuv2.menu.CpuFrequency.160=160 MHz -nodemcuv2.menu.CpuFrequency.160.build.f_cpu=160000000L -nodemcuv2.upload.resetmethod=nodemcu -nodemcuv2.build.flash_mode=dio -nodemcuv2.build.flash_freq=40 -nodemcuv2.menu.FlashSize.4M1M=4M (1M SPIFFS) -nodemcuv2.menu.FlashSize.4M1M.build.flash_size=4M -nodemcuv2.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -nodemcuv2.menu.FlashSize.4M1M.upload.maximum_size=1044464 -nodemcuv2.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -nodemcuv2.menu.FlashSize.4M3M=4M (3M SPIFFS) -nodemcuv2.menu.FlashSize.4M3M.build.flash_size=4M -nodemcuv2.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -nodemcuv2.menu.FlashSize.4M3M.upload.maximum_size=1044464 -nodemcuv2.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -nodemcuv2.menu.LwIPVariant.v2mss536=v2 Lower Memory -nodemcuv2.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -nodemcuv2.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -nodemcuv2.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -nodemcuv2.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -nodemcuv2.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -nodemcuv2.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -nodemcuv2.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -nodemcuv2.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -nodemcuv2.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -nodemcuv2.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.LwIPVariant.OpenSource=v1.4 Compile from source -nodemcuv2.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -nodemcuv2.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcuv2.menu.Debug.Disabled=Disabled -nodemcuv2.menu.Debug.Disabled.build.debug_port= -nodemcuv2.menu.Debug.Serial=Serial -nodemcuv2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcuv2.menu.Debug.Serial1=Serial1 -nodemcuv2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcuv2.menu.DebugLevel.None____=None -nodemcuv2.menu.DebugLevel.None____.build.debug_level= -nodemcuv2.menu.DebugLevel.SSL=SSL -nodemcuv2.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcuv2.menu.DebugLevel.TLS_MEM=TLS_MEM -nodemcuv2.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -nodemcuv2.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -nodemcuv2.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -nodemcuv2.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.CORE=CORE -nodemcuv2.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcuv2.menu.DebugLevel.WIFI=WIFI -nodemcuv2.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcuv2.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -nodemcuv2.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcuv2.menu.DebugLevel.UPDATER=UPDATER -nodemcuv2.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcuv2.menu.DebugLevel.OTA=OTA -nodemcuv2.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcuv2.menu.DebugLevel.OOM=OOM -nodemcuv2.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -nodemcuv2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcuv2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -nodemcuv2.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcuv2.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcuv2.menu.FlashErase.none=Only Sketch -nodemcuv2.menu.FlashErase.none.upload.erase_cmd= -nodemcuv2.menu.FlashErase.sdk=Sketch + WiFi Settings -nodemcuv2.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -nodemcuv2.menu.FlashErase.all=All Flash Contents -nodemcuv2.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -nodemcuv2.menu.UploadSpeed.115200=115200 -nodemcuv2.menu.UploadSpeed.115200.upload.speed=115200 -nodemcuv2.menu.UploadSpeed.9600=9600 -nodemcuv2.menu.UploadSpeed.9600.upload.speed=9600 -nodemcuv2.menu.UploadSpeed.57600=57600 -nodemcuv2.menu.UploadSpeed.57600.upload.speed=57600 -nodemcuv2.menu.UploadSpeed.230400.linux=230400 -nodemcuv2.menu.UploadSpeed.230400.macosx=230400 -nodemcuv2.menu.UploadSpeed.230400.upload.speed=230400 -nodemcuv2.menu.UploadSpeed.256000.windows=256000 -nodemcuv2.menu.UploadSpeed.256000.upload.speed=256000 -nodemcuv2.menu.UploadSpeed.460800.linux=460800 -nodemcuv2.menu.UploadSpeed.460800.macosx=460800 -nodemcuv2.menu.UploadSpeed.460800.upload.speed=460800 -nodemcuv2.menu.UploadSpeed.512000.windows=512000 -nodemcuv2.menu.UploadSpeed.512000.upload.speed=512000 -nodemcuv2.menu.UploadSpeed.921600=921600 -nodemcuv2.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) -modwifi.build.board=MOD_WIFI_ESP8266 -modwifi.upload.tool=esptool -modwifi.upload.maximum_data_size=81920 -modwifi.upload.wait_for_upload_port=true -modwifi.upload.erase_cmd= -modwifi.serial.disableDTR=true -modwifi.serial.disableRTS=true -modwifi.build.mcu=esp8266 -modwifi.build.core=esp8266 -modwifi.build.variant=generic -modwifi.build.spiffs_pagesize=256 -modwifi.build.debug_port= -modwifi.build.debug_level= -modwifi.menu.CpuFrequency.80=80 MHz -modwifi.menu.CpuFrequency.80.build.f_cpu=80000000L -modwifi.menu.CpuFrequency.160=160 MHz -modwifi.menu.CpuFrequency.160.build.f_cpu=160000000L -modwifi.upload.resetmethod=ck -modwifi.build.flash_mode=qio -modwifi.build.flash_freq=40 -modwifi.menu.FlashSize.2M=2M (1M SPIFFS) -modwifi.menu.FlashSize.2M.build.flash_size=2M -modwifi.menu.FlashSize.2M.build.flash_size_bytes=0x200000 -modwifi.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -modwifi.menu.FlashSize.2M.build.spiffs_pagesize=256 -modwifi.menu.FlashSize.2M.upload.maximum_size=1044464 -modwifi.menu.FlashSize.2M.build.rfcal_addr=0x1FC000 -modwifi.menu.FlashSize.2M.build.spiffs_start=0x100000 -modwifi.menu.FlashSize.2M.build.spiffs_end=0x1FB000 -modwifi.menu.FlashSize.2M.build.spiffs_blocksize=8192 -modwifi.menu.LwIPVariant.v2mss536=v2 Lower Memory -modwifi.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -modwifi.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -modwifi.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -modwifi.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -modwifi.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -modwifi.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -modwifi.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -modwifi.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -modwifi.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -modwifi.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.LwIPVariant.OpenSource=v1.4 Compile from source -modwifi.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -modwifi.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -modwifi.menu.Debug.Disabled=Disabled -modwifi.menu.Debug.Disabled.build.debug_port= -modwifi.menu.Debug.Serial=Serial -modwifi.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -modwifi.menu.Debug.Serial1=Serial1 -modwifi.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -modwifi.menu.DebugLevel.None____=None -modwifi.menu.DebugLevel.None____.build.debug_level= -modwifi.menu.DebugLevel.SSL=SSL -modwifi.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -modwifi.menu.DebugLevel.TLS_MEM=TLS_MEM -modwifi.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -modwifi.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -modwifi.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -modwifi.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -modwifi.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -modwifi.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -modwifi.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -modwifi.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.CORE=CORE -modwifi.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -modwifi.menu.DebugLevel.WIFI=WIFI -modwifi.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -modwifi.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -modwifi.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -modwifi.menu.DebugLevel.UPDATER=UPDATER -modwifi.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -modwifi.menu.DebugLevel.OTA=OTA -modwifi.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -modwifi.menu.DebugLevel.OOM=OOM -modwifi.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -modwifi.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -modwifi.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -modwifi.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -modwifi.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -modwifi.menu.FlashErase.none=Only Sketch -modwifi.menu.FlashErase.none.upload.erase_cmd= -modwifi.menu.FlashErase.sdk=Sketch + WiFi Settings -modwifi.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -modwifi.menu.FlashErase.all=All Flash Contents -modwifi.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -modwifi.menu.UploadSpeed.115200=115200 -modwifi.menu.UploadSpeed.115200.upload.speed=115200 -modwifi.menu.UploadSpeed.9600=9600 -modwifi.menu.UploadSpeed.9600.upload.speed=9600 -modwifi.menu.UploadSpeed.57600=57600 -modwifi.menu.UploadSpeed.57600.upload.speed=57600 -modwifi.menu.UploadSpeed.230400.linux=230400 -modwifi.menu.UploadSpeed.230400.macosx=230400 -modwifi.menu.UploadSpeed.230400.upload.speed=230400 -modwifi.menu.UploadSpeed.256000.windows=256000 -modwifi.menu.UploadSpeed.256000.upload.speed=256000 -modwifi.menu.UploadSpeed.460800.linux=460800 -modwifi.menu.UploadSpeed.460800.macosx=460800 -modwifi.menu.UploadSpeed.460800.upload.speed=460800 -modwifi.menu.UploadSpeed.512000.windows=512000 -modwifi.menu.UploadSpeed.512000.upload.speed=512000 -modwifi.menu.UploadSpeed.921600=921600 -modwifi.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -thing.name=SparkFun ESP8266 Thing -thing.build.board=ESP8266_THING -thing.build.variant=thing -thing.upload.tool=esptool -thing.upload.maximum_data_size=81920 -thing.upload.wait_for_upload_port=true -thing.upload.erase_cmd= -thing.serial.disableDTR=true -thing.serial.disableRTS=true -thing.build.mcu=esp8266 -thing.build.core=esp8266 -thing.build.spiffs_pagesize=256 -thing.build.debug_port= -thing.build.debug_level= -thing.menu.CpuFrequency.80=80 MHz -thing.menu.CpuFrequency.80.build.f_cpu=80000000L -thing.menu.CpuFrequency.160=160 MHz -thing.menu.CpuFrequency.160.build.f_cpu=160000000L -thing.upload.resetmethod=ck -thing.build.flash_mode=qio -thing.build.flash_freq=40 -thing.menu.FlashSize.512K0=512K (no SPIFFS) -thing.menu.FlashSize.512K0.build.flash_size=512K -thing.menu.FlashSize.512K0.build.flash_size_bytes=0x80000 -thing.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -thing.menu.FlashSize.512K0.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K0.upload.maximum_size=499696 -thing.menu.FlashSize.512K0.build.rfcal_addr=0x7C000 -thing.menu.FlashSize.512K64=512K (64K SPIFFS) -thing.menu.FlashSize.512K64.build.flash_size=512K -thing.menu.FlashSize.512K64.build.flash_size_bytes=0x80000 -thing.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -thing.menu.FlashSize.512K64.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K64.upload.maximum_size=434160 -thing.menu.FlashSize.512K64.build.rfcal_addr=0x7C000 -thing.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -thing.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -thing.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -thing.menu.FlashSize.512K128=512K (128K SPIFFS) -thing.menu.FlashSize.512K128.build.flash_size=512K -thing.menu.FlashSize.512K128.build.flash_size_bytes=0x80000 -thing.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -thing.menu.FlashSize.512K128.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K128.upload.maximum_size=368624 -thing.menu.FlashSize.512K128.build.rfcal_addr=0x7C000 -thing.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -thing.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -thing.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -thing.menu.LwIPVariant.v2mss536=v2 Lower Memory -thing.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -thing.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -thing.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -thing.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -thing.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -thing.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -thing.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -thing.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -thing.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -thing.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.LwIPVariant.OpenSource=v1.4 Compile from source -thing.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -thing.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thing.menu.Debug.Disabled=Disabled -thing.menu.Debug.Disabled.build.debug_port= -thing.menu.Debug.Serial=Serial -thing.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thing.menu.Debug.Serial1=Serial1 -thing.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thing.menu.DebugLevel.None____=None -thing.menu.DebugLevel.None____.build.debug_level= -thing.menu.DebugLevel.SSL=SSL -thing.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -thing.menu.DebugLevel.TLS_MEM=TLS_MEM -thing.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thing.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -thing.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -thing.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -thing.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thing.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thing.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -thing.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.CORE=CORE -thing.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -thing.menu.DebugLevel.WIFI=WIFI -thing.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thing.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -thing.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thing.menu.DebugLevel.UPDATER=UPDATER -thing.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thing.menu.DebugLevel.OTA=OTA -thing.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -thing.menu.DebugLevel.OOM=OOM -thing.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -thing.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thing.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -thing.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -thing.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thing.menu.FlashErase.none=Only Sketch -thing.menu.FlashErase.none.upload.erase_cmd= -thing.menu.FlashErase.sdk=Sketch + WiFi Settings -thing.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -thing.menu.FlashErase.all=All Flash Contents -thing.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -thing.menu.UploadSpeed.115200=115200 -thing.menu.UploadSpeed.115200.upload.speed=115200 -thing.menu.UploadSpeed.9600=9600 -thing.menu.UploadSpeed.9600.upload.speed=9600 -thing.menu.UploadSpeed.57600=57600 -thing.menu.UploadSpeed.57600.upload.speed=57600 -thing.menu.UploadSpeed.230400.linux=230400 -thing.menu.UploadSpeed.230400.macosx=230400 -thing.menu.UploadSpeed.230400.upload.speed=230400 -thing.menu.UploadSpeed.256000.windows=256000 -thing.menu.UploadSpeed.256000.upload.speed=256000 -thing.menu.UploadSpeed.460800.linux=460800 -thing.menu.UploadSpeed.460800.macosx=460800 -thing.menu.UploadSpeed.460800.upload.speed=460800 -thing.menu.UploadSpeed.512000.windows=512000 -thing.menu.UploadSpeed.512000.upload.speed=512000 -thing.menu.UploadSpeed.921600=921600 -thing.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -thingdev.name=SparkFun ESP8266 Thing Dev -thingdev.build.board=ESP8266_THING_DEV -thingdev.build.variant=thing -thingdev.upload.tool=esptool -thingdev.upload.maximum_data_size=81920 -thingdev.upload.wait_for_upload_port=true -thingdev.upload.erase_cmd= -thingdev.serial.disableDTR=true -thingdev.serial.disableRTS=true -thingdev.build.mcu=esp8266 -thingdev.build.core=esp8266 -thingdev.build.spiffs_pagesize=256 -thingdev.build.debug_port= -thingdev.build.debug_level= -thingdev.menu.CpuFrequency.80=80 MHz -thingdev.menu.CpuFrequency.80.build.f_cpu=80000000L -thingdev.menu.CpuFrequency.160=160 MHz -thingdev.menu.CpuFrequency.160.build.f_cpu=160000000L -thingdev.upload.resetmethod=nodemcu -thingdev.build.flash_mode=dio -thingdev.build.flash_freq=40 -thingdev.menu.FlashSize.512K0=512K (no SPIFFS) -thingdev.menu.FlashSize.512K0.build.flash_size=512K -thingdev.menu.FlashSize.512K0.build.flash_size_bytes=0x80000 -thingdev.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -thingdev.menu.FlashSize.512K0.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K0.upload.maximum_size=499696 -thingdev.menu.FlashSize.512K0.build.rfcal_addr=0x7C000 -thingdev.menu.FlashSize.512K64=512K (64K SPIFFS) -thingdev.menu.FlashSize.512K64.build.flash_size=512K -thingdev.menu.FlashSize.512K64.build.flash_size_bytes=0x80000 -thingdev.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -thingdev.menu.FlashSize.512K64.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K64.upload.maximum_size=434160 -thingdev.menu.FlashSize.512K64.build.rfcal_addr=0x7C000 -thingdev.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -thingdev.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -thingdev.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -thingdev.menu.FlashSize.512K128=512K (128K SPIFFS) -thingdev.menu.FlashSize.512K128.build.flash_size=512K -thingdev.menu.FlashSize.512K128.build.flash_size_bytes=0x80000 -thingdev.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -thingdev.menu.FlashSize.512K128.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K128.upload.maximum_size=368624 -thingdev.menu.FlashSize.512K128.build.rfcal_addr=0x7C000 -thingdev.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -thingdev.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -thingdev.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -thingdev.menu.LwIPVariant.v2mss536=v2 Lower Memory -thingdev.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -thingdev.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -thingdev.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -thingdev.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -thingdev.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -thingdev.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -thingdev.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -thingdev.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -thingdev.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -thingdev.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.LwIPVariant.OpenSource=v1.4 Compile from source -thingdev.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -thingdev.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thingdev.menu.Debug.Disabled=Disabled -thingdev.menu.Debug.Disabled.build.debug_port= -thingdev.menu.Debug.Serial=Serial -thingdev.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thingdev.menu.Debug.Serial1=Serial1 -thingdev.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thingdev.menu.DebugLevel.None____=None -thingdev.menu.DebugLevel.None____.build.debug_level= -thingdev.menu.DebugLevel.SSL=SSL -thingdev.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -thingdev.menu.DebugLevel.TLS_MEM=TLS_MEM -thingdev.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thingdev.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -thingdev.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -thingdev.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -thingdev.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thingdev.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thingdev.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -thingdev.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.CORE=CORE -thingdev.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -thingdev.menu.DebugLevel.WIFI=WIFI -thingdev.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thingdev.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -thingdev.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thingdev.menu.DebugLevel.UPDATER=UPDATER -thingdev.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thingdev.menu.DebugLevel.OTA=OTA -thingdev.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -thingdev.menu.DebugLevel.OOM=OOM -thingdev.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -thingdev.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thingdev.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -thingdev.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -thingdev.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thingdev.menu.FlashErase.none=Only Sketch -thingdev.menu.FlashErase.none.upload.erase_cmd= -thingdev.menu.FlashErase.sdk=Sketch + WiFi Settings -thingdev.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -thingdev.menu.FlashErase.all=All Flash Contents -thingdev.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -thingdev.menu.UploadSpeed.115200=115200 -thingdev.menu.UploadSpeed.115200.upload.speed=115200 -thingdev.menu.UploadSpeed.9600=9600 -thingdev.menu.UploadSpeed.9600.upload.speed=9600 -thingdev.menu.UploadSpeed.57600=57600 -thingdev.menu.UploadSpeed.57600.upload.speed=57600 -thingdev.menu.UploadSpeed.230400.linux=230400 -thingdev.menu.UploadSpeed.230400.macosx=230400 -thingdev.menu.UploadSpeed.230400.upload.speed=230400 -thingdev.menu.UploadSpeed.256000.windows=256000 -thingdev.menu.UploadSpeed.256000.upload.speed=256000 -thingdev.menu.UploadSpeed.460800.linux=460800 -thingdev.menu.UploadSpeed.460800.macosx=460800 -thingdev.menu.UploadSpeed.460800.upload.speed=460800 -thingdev.menu.UploadSpeed.512000.windows=512000 -thingdev.menu.UploadSpeed.512000.upload.speed=512000 -thingdev.menu.UploadSpeed.921600=921600 -thingdev.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -esp210.name=SweetPea ESP-210 -esp210.build.board=ESP8266_ESP210 -esp210.upload.tool=esptool -esp210.upload.maximum_data_size=81920 -esp210.upload.wait_for_upload_port=true -esp210.upload.erase_cmd= -esp210.serial.disableDTR=true -esp210.serial.disableRTS=true -esp210.build.mcu=esp8266 -esp210.build.core=esp8266 -esp210.build.variant=generic -esp210.build.spiffs_pagesize=256 -esp210.build.debug_port= -esp210.build.debug_level= -esp210.menu.CpuFrequency.80=80 MHz -esp210.menu.CpuFrequency.80.build.f_cpu=80000000L -esp210.menu.CpuFrequency.160=160 MHz -esp210.menu.CpuFrequency.160.build.f_cpu=160000000L -esp210.upload.resetmethod=ck -esp210.build.flash_mode=qio -esp210.build.flash_freq=40 -esp210.menu.FlashSize.4M1M=4M (1M SPIFFS) -esp210.menu.FlashSize.4M1M.build.flash_size=4M -esp210.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -esp210.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -esp210.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -esp210.menu.FlashSize.4M1M.upload.maximum_size=1044464 -esp210.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -esp210.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -esp210.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -esp210.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -esp210.menu.FlashSize.4M3M=4M (3M SPIFFS) -esp210.menu.FlashSize.4M3M.build.flash_size=4M -esp210.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -esp210.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -esp210.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -esp210.menu.FlashSize.4M3M.upload.maximum_size=1044464 -esp210.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -esp210.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -esp210.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -esp210.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -esp210.menu.LwIPVariant.v2mss536=v2 Lower Memory -esp210.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -esp210.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -esp210.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -esp210.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -esp210.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -esp210.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -esp210.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -esp210.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -esp210.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -esp210.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.LwIPVariant.OpenSource=v1.4 Compile from source -esp210.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -esp210.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp210.menu.Debug.Disabled=Disabled -esp210.menu.Debug.Disabled.build.debug_port= -esp210.menu.Debug.Serial=Serial -esp210.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp210.menu.Debug.Serial1=Serial1 -esp210.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp210.menu.DebugLevel.None____=None -esp210.menu.DebugLevel.None____.build.debug_level= -esp210.menu.DebugLevel.SSL=SSL -esp210.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp210.menu.DebugLevel.TLS_MEM=TLS_MEM -esp210.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp210.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -esp210.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -esp210.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -esp210.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp210.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp210.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp210.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.CORE=CORE -esp210.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp210.menu.DebugLevel.WIFI=WIFI -esp210.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp210.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -esp210.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp210.menu.DebugLevel.UPDATER=UPDATER -esp210.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp210.menu.DebugLevel.OTA=OTA -esp210.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp210.menu.DebugLevel.OOM=OOM -esp210.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -esp210.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp210.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -esp210.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -esp210.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp210.menu.FlashErase.none=Only Sketch -esp210.menu.FlashErase.none.upload.erase_cmd= -esp210.menu.FlashErase.sdk=Sketch + WiFi Settings -esp210.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -esp210.menu.FlashErase.all=All Flash Contents -esp210.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -esp210.menu.UploadSpeed.57600=57600 -esp210.menu.UploadSpeed.57600.upload.speed=57600 -esp210.menu.UploadSpeed.9600=9600 -esp210.menu.UploadSpeed.9600.upload.speed=9600 -esp210.menu.UploadSpeed.115200=115200 -esp210.menu.UploadSpeed.115200.upload.speed=115200 -esp210.menu.UploadSpeed.230400.linux=230400 -esp210.menu.UploadSpeed.230400.macosx=230400 -esp210.menu.UploadSpeed.230400.upload.speed=230400 -esp210.menu.UploadSpeed.256000.windows=256000 -esp210.menu.UploadSpeed.256000.upload.speed=256000 -esp210.menu.UploadSpeed.460800.linux=460800 -esp210.menu.UploadSpeed.460800.macosx=460800 -esp210.menu.UploadSpeed.460800.upload.speed=460800 -esp210.menu.UploadSpeed.512000.windows=512000 -esp210.menu.UploadSpeed.512000.upload.speed=512000 -esp210.menu.UploadSpeed.921600=921600 -esp210.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -d1_mini.name=WeMos D1 R2 & mini -d1_mini.build.board=ESP8266_WEMOS_D1MINI -d1_mini.build.variant=d1_mini -d1_mini.upload.tool=esptool -d1_mini.upload.maximum_data_size=81920 -d1_mini.upload.wait_for_upload_port=true -d1_mini.upload.erase_cmd= -d1_mini.serial.disableDTR=true -d1_mini.serial.disableRTS=true -d1_mini.build.mcu=esp8266 -d1_mini.build.core=esp8266 -d1_mini.build.spiffs_pagesize=256 -d1_mini.build.debug_port= -d1_mini.build.debug_level= -d1_mini.menu.CpuFrequency.80=80 MHz -d1_mini.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini.menu.CpuFrequency.160=160 MHz -d1_mini.menu.CpuFrequency.160.build.f_cpu=160000000L -d1_mini.upload.resetmethod=nodemcu -d1_mini.build.flash_mode=dio -d1_mini.build.flash_freq=40 -d1_mini.menu.FlashSize.4M1M=4M (1M SPIFFS) -d1_mini.menu.FlashSize.4M1M.build.flash_size=4M -d1_mini.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -d1_mini.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1_mini.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -d1_mini.menu.FlashSize.4M1M.upload.maximum_size=1044464 -d1_mini.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -d1_mini.menu.FlashSize.4M3M=4M (3M SPIFFS) -d1_mini.menu.FlashSize.4M3M.build.flash_size=4M -d1_mini.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -d1_mini.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -d1_mini.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -d1_mini.menu.FlashSize.4M3M.upload.maximum_size=1044464 -d1_mini.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -d1_mini.menu.LwIPVariant.v2mss536=v2 Lower Memory -d1_mini.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1_mini.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1_mini.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1_mini.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -d1_mini.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1_mini.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1_mini.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1_mini.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -d1_mini.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1_mini.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.LwIPVariant.OpenSource=v1.4 Compile from source -d1_mini.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1_mini.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini.menu.Debug.Disabled=Disabled -d1_mini.menu.Debug.Disabled.build.debug_port= -d1_mini.menu.Debug.Serial=Serial -d1_mini.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini.menu.Debug.Serial1=Serial1 -d1_mini.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini.menu.DebugLevel.None____=None -d1_mini.menu.DebugLevel.None____.build.debug_level= -d1_mini.menu.DebugLevel.SSL=SSL -d1_mini.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini.menu.DebugLevel.TLS_MEM=TLS_MEM -d1_mini.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1_mini.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1_mini.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1_mini.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.CORE=CORE -d1_mini.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini.menu.DebugLevel.WIFI=WIFI -d1_mini.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1_mini.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini.menu.DebugLevel.UPDATER=UPDATER -d1_mini.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini.menu.DebugLevel.OTA=OTA -d1_mini.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini.menu.DebugLevel.OOM=OOM -d1_mini.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1_mini.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1_mini.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini.menu.FlashErase.none=Only Sketch -d1_mini.menu.FlashErase.none.upload.erase_cmd= -d1_mini.menu.FlashErase.sdk=Sketch + WiFi Settings -d1_mini.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini.menu.FlashErase.all=All Flash Contents -d1_mini.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini.menu.UploadSpeed.921600=921600 -d1_mini.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini.menu.UploadSpeed.9600=9600 -d1_mini.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini.menu.UploadSpeed.57600=57600 -d1_mini.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini.menu.UploadSpeed.115200=115200 -d1_mini.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini.menu.UploadSpeed.230400.linux=230400 -d1_mini.menu.UploadSpeed.230400.macosx=230400 -d1_mini.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini.menu.UploadSpeed.256000.windows=256000 -d1_mini.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini.menu.UploadSpeed.460800.linux=460800 -d1_mini.menu.UploadSpeed.460800.macosx=460800 -d1_mini.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini.menu.UploadSpeed.512000.windows=512000 -d1_mini.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -d1_mini_pro.name=WeMos D1 mini Pro -d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO -d1_mini_pro.build.variant=d1_mini -d1_mini_pro.upload.tool=esptool -d1_mini_pro.upload.maximum_data_size=81920 -d1_mini_pro.upload.wait_for_upload_port=true -d1_mini_pro.upload.erase_cmd= -d1_mini_pro.serial.disableDTR=true -d1_mini_pro.serial.disableRTS=true -d1_mini_pro.build.mcu=esp8266 -d1_mini_pro.build.core=esp8266 -d1_mini_pro.build.spiffs_pagesize=256 -d1_mini_pro.build.debug_port= -d1_mini_pro.build.debug_level= -d1_mini_pro.menu.CpuFrequency.80=80 MHz -d1_mini_pro.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini_pro.menu.CpuFrequency.160=160 MHz -d1_mini_pro.menu.CpuFrequency.160.build.f_cpu=160000000L -d1_mini_pro.upload.resetmethod=nodemcu -d1_mini_pro.build.flash_mode=dio -d1_mini_pro.build.flash_freq=40 -d1_mini_pro.menu.FlashSize.16M15M=16M (15M SPIFFS) -d1_mini_pro.menu.FlashSize.16M15M.build.flash_size=16M -d1_mini_pro.menu.FlashSize.16M15M.build.flash_size_bytes=0x1000000 -d1_mini_pro.menu.FlashSize.16M15M.build.flash_ld=eagle.flash.16m.ld -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_pagesize=256 -d1_mini_pro.menu.FlashSize.16M15M.upload.maximum_size=1044464 -d1_mini_pro.menu.FlashSize.16M15M.build.rfcal_addr=0xFFC000 -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_start=0x100000 -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_end=0xFFB000 -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_blocksize=8192 -d1_mini_pro.menu.LwIPVariant.v2mss536=v2 Lower Memory -d1_mini_pro.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1_mini_pro.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1_mini_pro.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1_mini_pro.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -d1_mini_pro.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1_mini_pro.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1_mini_pro.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1_mini_pro.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -d1_mini_pro.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1_mini_pro.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.LwIPVariant.OpenSource=v1.4 Compile from source -d1_mini_pro.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1_mini_pro.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_pro.menu.Debug.Disabled=Disabled -d1_mini_pro.menu.Debug.Disabled.build.debug_port= -d1_mini_pro.menu.Debug.Serial=Serial -d1_mini_pro.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_pro.menu.Debug.Serial1=Serial1 -d1_mini_pro.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_pro.menu.DebugLevel.None____=None -d1_mini_pro.menu.DebugLevel.None____.build.debug_level= -d1_mini_pro.menu.DebugLevel.SSL=SSL -d1_mini_pro.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_pro.menu.DebugLevel.TLS_MEM=TLS_MEM -d1_mini_pro.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1_mini_pro.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_pro.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.CORE=CORE -d1_mini_pro.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_pro.menu.DebugLevel.WIFI=WIFI -d1_mini_pro.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_pro.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1_mini_pro.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_pro.menu.DebugLevel.UPDATER=UPDATER -d1_mini_pro.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_pro.menu.DebugLevel.OTA=OTA -d1_mini_pro.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_pro.menu.DebugLevel.OOM=OOM -d1_mini_pro.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1_mini_pro.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_pro.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1_mini_pro.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_pro.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_pro.menu.FlashErase.none=Only Sketch -d1_mini_pro.menu.FlashErase.none.upload.erase_cmd= -d1_mini_pro.menu.FlashErase.sdk=Sketch + WiFi Settings -d1_mini_pro.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini_pro.menu.FlashErase.all=All Flash Contents -d1_mini_pro.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini_pro.menu.UploadSpeed.921600=921600 -d1_mini_pro.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini_pro.menu.UploadSpeed.9600=9600 -d1_mini_pro.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini_pro.menu.UploadSpeed.57600=57600 -d1_mini_pro.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini_pro.menu.UploadSpeed.115200=115200 -d1_mini_pro.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini_pro.menu.UploadSpeed.230400.linux=230400 -d1_mini_pro.menu.UploadSpeed.230400.macosx=230400 -d1_mini_pro.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini_pro.menu.UploadSpeed.256000.windows=256000 -d1_mini_pro.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini_pro.menu.UploadSpeed.460800.linux=460800 -d1_mini_pro.menu.UploadSpeed.460800.macosx=460800 -d1_mini_pro.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini_pro.menu.UploadSpeed.512000.windows=512000 -d1_mini_pro.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -d1_mini_lite.name=WeMos D1 mini Lite -d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE -d1_mini_lite.build.variant=d1_mini -d1_mini_lite.upload.tool=esptool -d1_mini_lite.upload.maximum_data_size=81920 -d1_mini_lite.upload.wait_for_upload_port=true -d1_mini_lite.upload.erase_cmd= -d1_mini_lite.serial.disableDTR=true -d1_mini_lite.serial.disableRTS=true -d1_mini_lite.build.mcu=esp8266 -d1_mini_lite.build.core=esp8266 -d1_mini_lite.build.spiffs_pagesize=256 -d1_mini_lite.build.debug_port= -d1_mini_lite.build.debug_level= -d1_mini_lite.menu.CpuFrequency.80=80 MHz -d1_mini_lite.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini_lite.menu.CpuFrequency.160=160 MHz -d1_mini_lite.menu.CpuFrequency.160.build.f_cpu=160000000L -d1_mini_lite.upload.resetmethod=nodemcu -d1_mini_lite.build.flash_mode=dout -d1_mini_lite.build.flash_freq=40 -d1_mini_lite.menu.FlashSize.1M0=1M (no SPIFFS) -d1_mini_lite.menu.FlashSize.1M0.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M0.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -d1_mini_lite.menu.FlashSize.1M0.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M0.upload.maximum_size=1023984 -d1_mini_lite.menu.FlashSize.1M0.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M64=1M (64K SPIFFS) -d1_mini_lite.menu.FlashSize.1M64.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M64.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M64.upload.maximum_size=958448 -d1_mini_lite.menu.FlashSize.1M64.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M128=1M (128K SPIFFS) -d1_mini_lite.menu.FlashSize.1M128.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M128.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M128.upload.maximum_size=892912 -d1_mini_lite.menu.FlashSize.1M128.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M144=1M (144K SPIFFS) -d1_mini_lite.menu.FlashSize.1M144.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M144.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M144.upload.maximum_size=876528 -d1_mini_lite.menu.FlashSize.1M144.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M160=1M (160K SPIFFS) -d1_mini_lite.menu.FlashSize.1M160.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M160.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M160.upload.maximum_size=860144 -d1_mini_lite.menu.FlashSize.1M160.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M192=1M (192K SPIFFS) -d1_mini_lite.menu.FlashSize.1M192.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M192.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M192.upload.maximum_size=827376 -d1_mini_lite.menu.FlashSize.1M192.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M256=1M (256K SPIFFS) -d1_mini_lite.menu.FlashSize.1M256.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M256.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M256.upload.maximum_size=761840 -d1_mini_lite.menu.FlashSize.1M256.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M512=1M (512K SPIFFS) -d1_mini_lite.menu.FlashSize.1M512.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M512.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M512.upload.maximum_size=499696 -d1_mini_lite.menu.FlashSize.1M512.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -d1_mini_lite.menu.LwIPVariant.v2mss536=v2 Lower Memory -d1_mini_lite.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1_mini_lite.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1_mini_lite.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1_mini_lite.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -d1_mini_lite.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1_mini_lite.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1_mini_lite.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1_mini_lite.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -d1_mini_lite.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1_mini_lite.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.LwIPVariant.OpenSource=v1.4 Compile from source -d1_mini_lite.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1_mini_lite.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_lite.menu.Debug.Disabled=Disabled -d1_mini_lite.menu.Debug.Disabled.build.debug_port= -d1_mini_lite.menu.Debug.Serial=Serial -d1_mini_lite.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_lite.menu.Debug.Serial1=Serial1 -d1_mini_lite.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_lite.menu.DebugLevel.None____=None -d1_mini_lite.menu.DebugLevel.None____.build.debug_level= -d1_mini_lite.menu.DebugLevel.SSL=SSL -d1_mini_lite.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_lite.menu.DebugLevel.TLS_MEM=TLS_MEM -d1_mini_lite.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1_mini_lite.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_lite.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.CORE=CORE -d1_mini_lite.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_lite.menu.DebugLevel.WIFI=WIFI -d1_mini_lite.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_lite.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1_mini_lite.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_lite.menu.DebugLevel.UPDATER=UPDATER -d1_mini_lite.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_lite.menu.DebugLevel.OTA=OTA -d1_mini_lite.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_lite.menu.DebugLevel.OOM=OOM -d1_mini_lite.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1_mini_lite.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_lite.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1_mini_lite.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_lite.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_lite.menu.FlashErase.none=Only Sketch -d1_mini_lite.menu.FlashErase.none.upload.erase_cmd= -d1_mini_lite.menu.FlashErase.sdk=Sketch + WiFi Settings -d1_mini_lite.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini_lite.menu.FlashErase.all=All Flash Contents -d1_mini_lite.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini_lite.menu.UploadSpeed.921600=921600 -d1_mini_lite.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini_lite.menu.UploadSpeed.9600=9600 -d1_mini_lite.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini_lite.menu.UploadSpeed.57600=57600 -d1_mini_lite.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini_lite.menu.UploadSpeed.115200=115200 -d1_mini_lite.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini_lite.menu.UploadSpeed.230400.linux=230400 -d1_mini_lite.menu.UploadSpeed.230400.macosx=230400 -d1_mini_lite.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini_lite.menu.UploadSpeed.256000.windows=256000 -d1_mini_lite.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini_lite.menu.UploadSpeed.460800.linux=460800 -d1_mini_lite.menu.UploadSpeed.460800.macosx=460800 -d1_mini_lite.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini_lite.menu.UploadSpeed.512000.windows=512000 -d1_mini_lite.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -d1.name=WeMos D1 R1 -d1.build.board=ESP8266_WEMOS_D1R1 -d1.build.variant=d1 -d1.upload.tool=esptool -d1.upload.maximum_data_size=81920 -d1.upload.wait_for_upload_port=true -d1.upload.erase_cmd= -d1.serial.disableDTR=true -d1.serial.disableRTS=true -d1.build.mcu=esp8266 -d1.build.core=esp8266 -d1.build.spiffs_pagesize=256 -d1.build.debug_port= -d1.build.debug_level= -d1.menu.CpuFrequency.80=80 MHz -d1.menu.CpuFrequency.80.build.f_cpu=80000000L -d1.menu.CpuFrequency.160=160 MHz -d1.menu.CpuFrequency.160.build.f_cpu=160000000L -d1.upload.resetmethod=nodemcu -d1.build.flash_mode=dio -d1.build.flash_freq=40 -d1.menu.FlashSize.4M1M=4M (1M SPIFFS) -d1.menu.FlashSize.4M1M.build.flash_size=4M -d1.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -d1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -d1.menu.FlashSize.4M1M.upload.maximum_size=1044464 -d1.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -d1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -d1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -d1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -d1.menu.FlashSize.4M3M=4M (3M SPIFFS) -d1.menu.FlashSize.4M3M.build.flash_size=4M -d1.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -d1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -d1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -d1.menu.FlashSize.4M3M.upload.maximum_size=1044464 -d1.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -d1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -d1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -d1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -d1.menu.LwIPVariant.v2mss536=v2 Lower Memory -d1.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -d1.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -d1.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.LwIPVariant.OpenSource=v1.4 Compile from source -d1.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1.menu.Debug.Disabled=Disabled -d1.menu.Debug.Disabled.build.debug_port= -d1.menu.Debug.Serial=Serial -d1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1.menu.Debug.Serial1=Serial1 -d1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1.menu.DebugLevel.None____=None -d1.menu.DebugLevel.None____.build.debug_level= -d1.menu.DebugLevel.SSL=SSL -d1.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1.menu.DebugLevel.TLS_MEM=TLS_MEM -d1.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.CORE=CORE -d1.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1.menu.DebugLevel.WIFI=WIFI -d1.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1.menu.DebugLevel.UPDATER=UPDATER -d1.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1.menu.DebugLevel.OTA=OTA -d1.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1.menu.DebugLevel.OOM=OOM -d1.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -d1.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1.menu.FlashErase.none=Only Sketch -d1.menu.FlashErase.none.upload.erase_cmd= -d1.menu.FlashErase.sdk=Sketch + WiFi Settings -d1.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1.menu.FlashErase.all=All Flash Contents -d1.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1.menu.UploadSpeed.921600=921600 -d1.menu.UploadSpeed.921600.upload.speed=921600 -d1.menu.UploadSpeed.9600=9600 -d1.menu.UploadSpeed.9600.upload.speed=9600 -d1.menu.UploadSpeed.57600=57600 -d1.menu.UploadSpeed.57600.upload.speed=57600 -d1.menu.UploadSpeed.115200=115200 -d1.menu.UploadSpeed.115200.upload.speed=115200 -d1.menu.UploadSpeed.230400.linux=230400 -d1.menu.UploadSpeed.230400.macosx=230400 -d1.menu.UploadSpeed.230400.upload.speed=230400 -d1.menu.UploadSpeed.256000.windows=256000 -d1.menu.UploadSpeed.256000.upload.speed=256000 -d1.menu.UploadSpeed.460800.linux=460800 -d1.menu.UploadSpeed.460800.macosx=460800 -d1.menu.UploadSpeed.460800.upload.speed=460800 -d1.menu.UploadSpeed.512000.windows=512000 -d1.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -espino.name=ESPino (ESP-12 Module) -espino.build.board=ESP8266_ESP12 -espino.build.variant=espino -espino.upload.tool=esptool -espino.upload.maximum_data_size=81920 -espino.upload.wait_for_upload_port=true -espino.upload.erase_cmd= -espino.serial.disableDTR=true -espino.serial.disableRTS=true -espino.build.mcu=esp8266 -espino.build.core=esp8266 -espino.build.spiffs_pagesize=256 -espino.build.debug_port= -espino.build.debug_level= -espino.menu.CpuFrequency.80=80 MHz -espino.menu.CpuFrequency.80.build.f_cpu=80000000L -espino.menu.CpuFrequency.160=160 MHz -espino.menu.CpuFrequency.160.build.f_cpu=160000000L -espino.menu.ResetMethod.ck=ck -espino.menu.ResetMethod.ck.upload.resetmethod=ck -espino.menu.ResetMethod.nodemcu=nodemcu -espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espino.build.flash_mode=qio -espino.build.flash_freq=40 -espino.menu.FlashSize.4M1M=4M (1M SPIFFS) -espino.menu.FlashSize.4M1M.build.flash_size=4M -espino.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espino.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espino.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espino.menu.FlashSize.4M3M=4M (3M SPIFFS) -espino.menu.FlashSize.4M3M.build.flash_size=4M -espino.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espino.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espino.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espino.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espino.menu.LwIPVariant.v2mss536=v2 Lower Memory -espino.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espino.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espino.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espino.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espino.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espino.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espino.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espino.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espino.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espino.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espino.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espino.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espino.menu.Debug.Disabled=Disabled -espino.menu.Debug.Disabled.build.debug_port= -espino.menu.Debug.Serial=Serial -espino.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espino.menu.Debug.Serial1=Serial1 -espino.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espino.menu.DebugLevel.None____=None -espino.menu.DebugLevel.None____.build.debug_level= -espino.menu.DebugLevel.SSL=SSL -espino.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espino.menu.DebugLevel.TLS_MEM=TLS_MEM -espino.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espino.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espino.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espino.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espino.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espino.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espino.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espino.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.CORE=CORE -espino.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espino.menu.DebugLevel.WIFI=WIFI -espino.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espino.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espino.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espino.menu.DebugLevel.UPDATER=UPDATER -espino.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espino.menu.DebugLevel.OTA=OTA -espino.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espino.menu.DebugLevel.OOM=OOM -espino.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espino.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espino.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espino.menu.FlashErase.none=Only Sketch -espino.menu.FlashErase.none.upload.erase_cmd= -espino.menu.FlashErase.sdk=Sketch + WiFi Settings -espino.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espino.menu.FlashErase.all=All Flash Contents -espino.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espino.menu.UploadSpeed.115200=115200 -espino.menu.UploadSpeed.115200.upload.speed=115200 -espino.menu.UploadSpeed.9600=9600 -espino.menu.UploadSpeed.9600.upload.speed=9600 -espino.menu.UploadSpeed.57600=57600 -espino.menu.UploadSpeed.57600.upload.speed=57600 -espino.menu.UploadSpeed.230400.linux=230400 -espino.menu.UploadSpeed.230400.macosx=230400 -espino.menu.UploadSpeed.230400.upload.speed=230400 -espino.menu.UploadSpeed.256000.windows=256000 -espino.menu.UploadSpeed.256000.upload.speed=256000 -espino.menu.UploadSpeed.460800.linux=460800 -espino.menu.UploadSpeed.460800.macosx=460800 -espino.menu.UploadSpeed.460800.upload.speed=460800 -espino.menu.UploadSpeed.512000.windows=512000 -espino.menu.UploadSpeed.512000.upload.speed=512000 -espino.menu.UploadSpeed.921600=921600 -espino.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espinotee.name=ThaiEasyElec's ESPino -espinotee.build.board=ESP8266_ESP13 -espinotee.build.variant=espinotee -espinotee.upload.tool=esptool -espinotee.upload.maximum_data_size=81920 -espinotee.upload.wait_for_upload_port=true -espinotee.upload.erase_cmd= -espinotee.serial.disableDTR=true -espinotee.serial.disableRTS=true -espinotee.build.mcu=esp8266 -espinotee.build.core=esp8266 -espinotee.build.spiffs_pagesize=256 -espinotee.build.debug_port= -espinotee.build.debug_level= -espinotee.menu.CpuFrequency.80=80 MHz -espinotee.menu.CpuFrequency.80.build.f_cpu=80000000L -espinotee.menu.CpuFrequency.160=160 MHz -espinotee.menu.CpuFrequency.160.build.f_cpu=160000000L -espinotee.upload.resetmethod=nodemcu -espinotee.build.flash_mode=qio -espinotee.build.flash_freq=40 -espinotee.menu.FlashSize.4M1M=4M (1M SPIFFS) -espinotee.menu.FlashSize.4M1M.build.flash_size=4M -espinotee.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espinotee.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espinotee.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espinotee.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espinotee.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espinotee.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espinotee.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espinotee.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espinotee.menu.FlashSize.4M3M=4M (3M SPIFFS) -espinotee.menu.FlashSize.4M3M.build.flash_size=4M -espinotee.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espinotee.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espinotee.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espinotee.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espinotee.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espinotee.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espinotee.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espinotee.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espinotee.menu.LwIPVariant.v2mss536=v2 Lower Memory -espinotee.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espinotee.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espinotee.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espinotee.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espinotee.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espinotee.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espinotee.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espinotee.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espinotee.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espinotee.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espinotee.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espinotee.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espinotee.menu.Debug.Disabled=Disabled -espinotee.menu.Debug.Disabled.build.debug_port= -espinotee.menu.Debug.Serial=Serial -espinotee.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espinotee.menu.Debug.Serial1=Serial1 -espinotee.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espinotee.menu.DebugLevel.None____=None -espinotee.menu.DebugLevel.None____.build.debug_level= -espinotee.menu.DebugLevel.SSL=SSL -espinotee.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espinotee.menu.DebugLevel.TLS_MEM=TLS_MEM -espinotee.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espinotee.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espinotee.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espinotee.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espinotee.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espinotee.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espinotee.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espinotee.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.CORE=CORE -espinotee.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espinotee.menu.DebugLevel.WIFI=WIFI -espinotee.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espinotee.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espinotee.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espinotee.menu.DebugLevel.UPDATER=UPDATER -espinotee.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espinotee.menu.DebugLevel.OTA=OTA -espinotee.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espinotee.menu.DebugLevel.OOM=OOM -espinotee.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espinotee.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espinotee.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -espinotee.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espinotee.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espinotee.menu.FlashErase.none=Only Sketch -espinotee.menu.FlashErase.none.upload.erase_cmd= -espinotee.menu.FlashErase.sdk=Sketch + WiFi Settings -espinotee.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espinotee.menu.FlashErase.all=All Flash Contents -espinotee.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espinotee.menu.UploadSpeed.115200=115200 -espinotee.menu.UploadSpeed.115200.upload.speed=115200 -espinotee.menu.UploadSpeed.9600=9600 -espinotee.menu.UploadSpeed.9600.upload.speed=9600 -espinotee.menu.UploadSpeed.57600=57600 -espinotee.menu.UploadSpeed.57600.upload.speed=57600 -espinotee.menu.UploadSpeed.230400.linux=230400 -espinotee.menu.UploadSpeed.230400.macosx=230400 -espinotee.menu.UploadSpeed.230400.upload.speed=230400 -espinotee.menu.UploadSpeed.256000.windows=256000 -espinotee.menu.UploadSpeed.256000.upload.speed=256000 -espinotee.menu.UploadSpeed.460800.linux=460800 -espinotee.menu.UploadSpeed.460800.macosx=460800 -espinotee.menu.UploadSpeed.460800.upload.speed=460800 -espinotee.menu.UploadSpeed.512000.windows=512000 -espinotee.menu.UploadSpeed.512000.upload.speed=512000 -espinotee.menu.UploadSpeed.921600=921600 -espinotee.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -wifinfo.name=WifInfo -wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 -wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 -wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 -wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld -wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 -wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) -wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 -wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 -wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 -wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 -wifinfo.menu.ESPModule.ESP12.build.flash_size=4M -wifinfo.build.board=WIFINFO -wifinfo.build.variant=wifinfo -wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M -wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) -wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 -wifinfo.upload.tool=esptool -wifinfo.upload.maximum_data_size=81920 -wifinfo.upload.wait_for_upload_port=true -wifinfo.upload.erase_cmd= -wifinfo.serial.disableDTR=true -wifinfo.serial.disableRTS=true -wifinfo.build.mcu=esp8266 -wifinfo.build.core=esp8266 -wifinfo.build.spiffs_pagesize=256 -wifinfo.build.debug_port= -wifinfo.build.debug_level= -wifinfo.menu.CpuFrequency.80=80 MHz -wifinfo.menu.CpuFrequency.80.build.f_cpu=80000000L -wifinfo.menu.CpuFrequency.160=160 MHz -wifinfo.menu.CpuFrequency.160.build.f_cpu=160000000L -wifinfo.upload.resetmethod=nodemcu -wifinfo.build.flash_mode=qio -wifinfo.menu.FlashFreq.40=40MHz -wifinfo.menu.FlashFreq.40.build.flash_freq=40 -wifinfo.menu.FlashFreq.80=80MHz -wifinfo.menu.FlashFreq.80.build.flash_freq=80 -wifinfo.menu.FlashSize.1M0=1M (no SPIFFS) -wifinfo.menu.FlashSize.1M0.build.flash_size=1M -wifinfo.menu.FlashSize.1M0.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -wifinfo.menu.FlashSize.1M0.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M0.upload.maximum_size=1023984 -wifinfo.menu.FlashSize.1M0.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M64=1M (64K SPIFFS) -wifinfo.menu.FlashSize.1M64.build.flash_size=1M -wifinfo.menu.FlashSize.1M64.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -wifinfo.menu.FlashSize.1M64.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M64.upload.maximum_size=958448 -wifinfo.menu.FlashSize.1M64.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -wifinfo.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M128=1M (128K SPIFFS) -wifinfo.menu.FlashSize.1M128.build.flash_size=1M -wifinfo.menu.FlashSize.1M128.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -wifinfo.menu.FlashSize.1M128.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M128.upload.maximum_size=892912 -wifinfo.menu.FlashSize.1M128.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -wifinfo.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M144=1M (144K SPIFFS) -wifinfo.menu.FlashSize.1M144.build.flash_size=1M -wifinfo.menu.FlashSize.1M144.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -wifinfo.menu.FlashSize.1M144.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M144.upload.maximum_size=876528 -wifinfo.menu.FlashSize.1M144.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -wifinfo.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M160=1M (160K SPIFFS) -wifinfo.menu.FlashSize.1M160.build.flash_size=1M -wifinfo.menu.FlashSize.1M160.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -wifinfo.menu.FlashSize.1M160.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M160.upload.maximum_size=860144 -wifinfo.menu.FlashSize.1M160.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -wifinfo.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M192=1M (192K SPIFFS) -wifinfo.menu.FlashSize.1M192.build.flash_size=1M -wifinfo.menu.FlashSize.1M192.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.FlashSize.1M192.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M192.upload.maximum_size=827376 -wifinfo.menu.FlashSize.1M192.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -wifinfo.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M256=1M (256K SPIFFS) -wifinfo.menu.FlashSize.1M256.build.flash_size=1M -wifinfo.menu.FlashSize.1M256.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -wifinfo.menu.FlashSize.1M256.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M256.upload.maximum_size=761840 -wifinfo.menu.FlashSize.1M256.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -wifinfo.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M512=1M (512K SPIFFS) -wifinfo.menu.FlashSize.1M512.build.flash_size=1M -wifinfo.menu.FlashSize.1M512.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -wifinfo.menu.FlashSize.1M512.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M512.upload.maximum_size=499696 -wifinfo.menu.FlashSize.1M512.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -wifinfo.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -wifinfo.menu.LwIPVariant.v2mss536=v2 Lower Memory -wifinfo.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -wifinfo.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -wifinfo.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -wifinfo.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -wifinfo.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -wifinfo.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -wifinfo.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -wifinfo.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -wifinfo.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -wifinfo.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.LwIPVariant.OpenSource=v1.4 Compile from source -wifinfo.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -wifinfo.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifinfo.menu.Debug.Disabled=Disabled -wifinfo.menu.Debug.Disabled.build.debug_port= -wifinfo.menu.Debug.Serial=Serial -wifinfo.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifinfo.menu.Debug.Serial1=Serial1 -wifinfo.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifinfo.menu.DebugLevel.None____=None -wifinfo.menu.DebugLevel.None____.build.debug_level= -wifinfo.menu.DebugLevel.SSL=SSL -wifinfo.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifinfo.menu.DebugLevel.TLS_MEM=TLS_MEM -wifinfo.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifinfo.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -wifinfo.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -wifinfo.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -wifinfo.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifinfo.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.CORE=CORE -wifinfo.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifinfo.menu.DebugLevel.WIFI=WIFI -wifinfo.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifinfo.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -wifinfo.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifinfo.menu.DebugLevel.UPDATER=UPDATER -wifinfo.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifinfo.menu.DebugLevel.OTA=OTA -wifinfo.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifinfo.menu.DebugLevel.OOM=OOM -wifinfo.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -wifinfo.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifinfo.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -wifinfo.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -wifinfo.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifinfo.menu.FlashErase.none=Only Sketch -wifinfo.menu.FlashErase.none.upload.erase_cmd= -wifinfo.menu.FlashErase.sdk=Sketch + WiFi Settings -wifinfo.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifinfo.menu.FlashErase.all=All Flash Contents -wifinfo.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifinfo.menu.UploadSpeed.115200=115200 -wifinfo.menu.UploadSpeed.115200.upload.speed=115200 -wifinfo.menu.UploadSpeed.9600=9600 -wifinfo.menu.UploadSpeed.9600.upload.speed=9600 -wifinfo.menu.UploadSpeed.57600=57600 -wifinfo.menu.UploadSpeed.57600.upload.speed=57600 -wifinfo.menu.UploadSpeed.230400.linux=230400 -wifinfo.menu.UploadSpeed.230400.macosx=230400 -wifinfo.menu.UploadSpeed.230400.upload.speed=230400 -wifinfo.menu.UploadSpeed.256000.windows=256000 -wifinfo.menu.UploadSpeed.256000.upload.speed=256000 -wifinfo.menu.UploadSpeed.460800.linux=460800 -wifinfo.menu.UploadSpeed.460800.macosx=460800 -wifinfo.menu.UploadSpeed.460800.upload.speed=460800 -wifinfo.menu.UploadSpeed.512000.windows=512000 -wifinfo.menu.UploadSpeed.512000.upload.speed=512000 -wifinfo.menu.UploadSpeed.921600=921600 -wifinfo.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -arduino-esp8266.name=Arduino -arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO -arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI -arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.primo=Primo -arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi -arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO -arduino-esp8266.build.board=ESP8266_ARDUINO -arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO -arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi -arduino-esp8266.upload.tool=esptool -arduino-esp8266.upload.maximum_data_size=81920 -arduino-esp8266.upload.wait_for_upload_port=true -arduino-esp8266.upload.erase_cmd= -arduino-esp8266.serial.disableDTR=true -arduino-esp8266.serial.disableRTS=true -arduino-esp8266.build.mcu=esp8266 -arduino-esp8266.build.core=esp8266 -arduino-esp8266.build.variant=generic -arduino-esp8266.build.spiffs_pagesize=256 -arduino-esp8266.build.debug_port= -arduino-esp8266.build.debug_level= -arduino-esp8266.menu.CpuFrequency.80=80 MHz -arduino-esp8266.menu.CpuFrequency.80.build.f_cpu=80000000L -arduino-esp8266.menu.CpuFrequency.160=160 MHz -arduino-esp8266.menu.CpuFrequency.160.build.f_cpu=160000000L -arduino-esp8266.upload.resetmethod=ck -arduino-esp8266.build.flash_mode=qio -arduino-esp8266.build.flash_freq=40 -arduino-esp8266.menu.FlashSize.4M1M=4M (1M SPIFFS) -arduino-esp8266.menu.FlashSize.4M1M.build.flash_size=4M -arduino-esp8266.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -arduino-esp8266.menu.FlashSize.4M1M.upload.maximum_size=1044464 -arduino-esp8266.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.FlashSize.4M3M=4M (3M SPIFFS) -arduino-esp8266.menu.FlashSize.4M3M.build.flash_size=4M -arduino-esp8266.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -arduino-esp8266.menu.FlashSize.4M3M.upload.maximum_size=1044464 -arduino-esp8266.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.LwIPVariant.v2mss536=v2 Lower Memory -arduino-esp8266.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -arduino-esp8266.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -arduino-esp8266.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -arduino-esp8266.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -arduino-esp8266.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -arduino-esp8266.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -arduino-esp8266.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -arduino-esp8266.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -arduino-esp8266.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -arduino-esp8266.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.LwIPVariant.OpenSource=v1.4 Compile from source -arduino-esp8266.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -arduino-esp8266.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -arduino-esp8266.menu.Debug.Disabled=Disabled -arduino-esp8266.menu.Debug.Disabled.build.debug_port= -arduino-esp8266.menu.Debug.Serial=Serial -arduino-esp8266.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -arduino-esp8266.menu.Debug.Serial1=Serial1 -arduino-esp8266.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -arduino-esp8266.menu.DebugLevel.None____=None -arduino-esp8266.menu.DebugLevel.None____.build.debug_level= -arduino-esp8266.menu.DebugLevel.SSL=SSL -arduino-esp8266.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -arduino-esp8266.menu.DebugLevel.TLS_MEM=TLS_MEM -arduino-esp8266.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -arduino-esp8266.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -arduino-esp8266.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.CORE=CORE -arduino-esp8266.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -arduino-esp8266.menu.DebugLevel.WIFI=WIFI -arduino-esp8266.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -arduino-esp8266.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -arduino-esp8266.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -arduino-esp8266.menu.DebugLevel.UPDATER=UPDATER -arduino-esp8266.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -arduino-esp8266.menu.DebugLevel.OTA=OTA -arduino-esp8266.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -arduino-esp8266.menu.DebugLevel.OOM=OOM -arduino-esp8266.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -arduino-esp8266.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -arduino-esp8266.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -arduino-esp8266.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -arduino-esp8266.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -arduino-esp8266.menu.FlashErase.none=Only Sketch -arduino-esp8266.menu.FlashErase.none.upload.erase_cmd= -arduino-esp8266.menu.FlashErase.sdk=Sketch + WiFi Settings -arduino-esp8266.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -arduino-esp8266.menu.FlashErase.all=All Flash Contents -arduino-esp8266.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -arduino-esp8266.menu.UploadSpeed.115200=115200 -arduino-esp8266.menu.UploadSpeed.115200.upload.speed=115200 -arduino-esp8266.menu.UploadSpeed.9600=9600 -arduino-esp8266.menu.UploadSpeed.9600.upload.speed=9600 -arduino-esp8266.menu.UploadSpeed.57600=57600 -arduino-esp8266.menu.UploadSpeed.57600.upload.speed=57600 -arduino-esp8266.menu.UploadSpeed.230400.linux=230400 -arduino-esp8266.menu.UploadSpeed.230400.macosx=230400 -arduino-esp8266.menu.UploadSpeed.230400.upload.speed=230400 -arduino-esp8266.menu.UploadSpeed.256000.windows=256000 -arduino-esp8266.menu.UploadSpeed.256000.upload.speed=256000 -arduino-esp8266.menu.UploadSpeed.460800.linux=460800 -arduino-esp8266.menu.UploadSpeed.460800.macosx=460800 -arduino-esp8266.menu.UploadSpeed.460800.upload.speed=460800 -arduino-esp8266.menu.UploadSpeed.512000.windows=512000 -arduino-esp8266.menu.UploadSpeed.512000.upload.speed=512000 -arduino-esp8266.menu.UploadSpeed.921600=921600 -arduino-esp8266.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -gen4iod.name=4D Systems gen4 IoD Range -gen4iod.build.board=GEN4_IOD -gen4iod.build.f_cpu=160000000L -gen4iod.build.variant=generic -gen4iod.upload.tool=esptool -gen4iod.upload.maximum_data_size=81920 -gen4iod.upload.wait_for_upload_port=true -gen4iod.upload.erase_cmd= -gen4iod.serial.disableDTR=true -gen4iod.serial.disableRTS=true -gen4iod.build.mcu=esp8266 -gen4iod.build.core=esp8266 -gen4iod.build.spiffs_pagesize=256 -gen4iod.build.debug_port= -gen4iod.build.debug_level= -gen4iod.menu.CpuFrequency.80=80 MHz -gen4iod.menu.CpuFrequency.80.build.f_cpu=80000000L -gen4iod.menu.CpuFrequency.160=160 MHz -gen4iod.menu.CpuFrequency.160.build.f_cpu=160000000L -gen4iod.upload.resetmethod=nodemcu -gen4iod.build.flash_mode=qio -gen4iod.build.flash_freq=80 -gen4iod.menu.FlashSize.512K0=512K (no SPIFFS) -gen4iod.menu.FlashSize.512K0.build.flash_size=512K -gen4iod.menu.FlashSize.512K0.build.flash_size_bytes=0x80000 -gen4iod.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -gen4iod.menu.FlashSize.512K0.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K0.upload.maximum_size=499696 -gen4iod.menu.FlashSize.512K0.build.rfcal_addr=0x7C000 -gen4iod.menu.FlashSize.512K64=512K (64K SPIFFS) -gen4iod.menu.FlashSize.512K64.build.flash_size=512K -gen4iod.menu.FlashSize.512K64.build.flash_size_bytes=0x80000 -gen4iod.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -gen4iod.menu.FlashSize.512K64.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K64.upload.maximum_size=434160 -gen4iod.menu.FlashSize.512K64.build.rfcal_addr=0x7C000 -gen4iod.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -gen4iod.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -gen4iod.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -gen4iod.menu.FlashSize.512K128=512K (128K SPIFFS) -gen4iod.menu.FlashSize.512K128.build.flash_size=512K -gen4iod.menu.FlashSize.512K128.build.flash_size_bytes=0x80000 -gen4iod.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -gen4iod.menu.FlashSize.512K128.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K128.upload.maximum_size=368624 -gen4iod.menu.FlashSize.512K128.build.rfcal_addr=0x7C000 -gen4iod.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -gen4iod.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -gen4iod.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -gen4iod.menu.LwIPVariant.v2mss536=v2 Lower Memory -gen4iod.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -gen4iod.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -gen4iod.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -gen4iod.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -gen4iod.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -gen4iod.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -gen4iod.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -gen4iod.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -gen4iod.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -gen4iod.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.LwIPVariant.OpenSource=v1.4 Compile from source -gen4iod.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -gen4iod.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -gen4iod.menu.Debug.Disabled=Disabled -gen4iod.menu.Debug.Disabled.build.debug_port= -gen4iod.menu.Debug.Serial=Serial -gen4iod.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -gen4iod.menu.Debug.Serial1=Serial1 -gen4iod.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -gen4iod.menu.DebugLevel.None____=None -gen4iod.menu.DebugLevel.None____.build.debug_level= -gen4iod.menu.DebugLevel.SSL=SSL -gen4iod.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -gen4iod.menu.DebugLevel.TLS_MEM=TLS_MEM -gen4iod.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -gen4iod.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -gen4iod.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -gen4iod.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -gen4iod.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -gen4iod.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.CORE=CORE -gen4iod.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -gen4iod.menu.DebugLevel.WIFI=WIFI -gen4iod.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -gen4iod.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -gen4iod.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -gen4iod.menu.DebugLevel.UPDATER=UPDATER -gen4iod.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -gen4iod.menu.DebugLevel.OTA=OTA -gen4iod.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -gen4iod.menu.DebugLevel.OOM=OOM -gen4iod.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -gen4iod.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -gen4iod.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -gen4iod.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -gen4iod.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -gen4iod.menu.FlashErase.none=Only Sketch -gen4iod.menu.FlashErase.none.upload.erase_cmd= -gen4iod.menu.FlashErase.sdk=Sketch + WiFi Settings -gen4iod.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -gen4iod.menu.FlashErase.all=All Flash Contents -gen4iod.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -gen4iod.menu.UploadSpeed.115200=115200 -gen4iod.menu.UploadSpeed.115200.upload.speed=115200 -gen4iod.menu.UploadSpeed.9600=9600 -gen4iod.menu.UploadSpeed.9600.upload.speed=9600 -gen4iod.menu.UploadSpeed.57600=57600 -gen4iod.menu.UploadSpeed.57600.upload.speed=57600 -gen4iod.menu.UploadSpeed.230400.linux=230400 -gen4iod.menu.UploadSpeed.230400.macosx=230400 -gen4iod.menu.UploadSpeed.230400.upload.speed=230400 -gen4iod.menu.UploadSpeed.256000.windows=256000 -gen4iod.menu.UploadSpeed.256000.upload.speed=256000 -gen4iod.menu.UploadSpeed.460800.linux=460800 -gen4iod.menu.UploadSpeed.460800.macosx=460800 -gen4iod.menu.UploadSpeed.460800.upload.speed=460800 -gen4iod.menu.UploadSpeed.512000.windows=512000 -gen4iod.menu.UploadSpeed.512000.upload.speed=512000 -gen4iod.menu.UploadSpeed.921600=921600 -gen4iod.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -oak.name=Digistump Oak -oak.build.board=ESP8266_OAK -oak.build.variant=oak -oak.upload.maximum_size=1040368 -oak.upload.tool=esptool -oak.upload.maximum_data_size=81920 -oak.upload.wait_for_upload_port=true -oak.upload.erase_cmd= -oak.serial.disableDTR=true -oak.serial.disableRTS=true -oak.build.mcu=esp8266 -oak.build.core=esp8266 -oak.build.spiffs_pagesize=256 -oak.build.debug_port= -oak.build.debug_level= -oak.menu.CpuFrequency.80=80 MHz -oak.menu.CpuFrequency.80.build.f_cpu=80000000L -oak.menu.CpuFrequency.160=160 MHz -oak.menu.CpuFrequency.160.build.f_cpu=160000000L -oak.upload.resetmethod=none -oak.build.flash_mode=dio -oak.build.flash_freq=40 -oak.menu.FlashSize.4M1M=4M (1M SPIFFS) -oak.menu.FlashSize.4M1M.build.flash_size=4M -oak.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -oak.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -oak.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -oak.menu.FlashSize.4M1M.upload.maximum_size=1044464 -oak.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -oak.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -oak.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -oak.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -oak.menu.FlashSize.4M3M=4M (3M SPIFFS) -oak.menu.FlashSize.4M3M.build.flash_size=4M -oak.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -oak.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -oak.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -oak.menu.FlashSize.4M3M.upload.maximum_size=1044464 -oak.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -oak.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -oak.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -oak.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -oak.menu.LwIPVariant.v2mss536=v2 Lower Memory -oak.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -oak.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -oak.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -oak.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -oak.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -oak.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -oak.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -oak.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -oak.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -oak.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.LwIPVariant.OpenSource=v1.4 Compile from source -oak.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -oak.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -oak.menu.Debug.Disabled=Disabled -oak.menu.Debug.Disabled.build.debug_port= -oak.menu.Debug.Serial=Serial -oak.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -oak.menu.Debug.Serial1=Serial1 -oak.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -oak.menu.DebugLevel.None____=None -oak.menu.DebugLevel.None____.build.debug_level= -oak.menu.DebugLevel.SSL=SSL -oak.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -oak.menu.DebugLevel.TLS_MEM=TLS_MEM -oak.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -oak.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -oak.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -oak.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -oak.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -oak.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -oak.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -oak.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.CORE=CORE -oak.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -oak.menu.DebugLevel.WIFI=WIFI -oak.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -oak.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -oak.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -oak.menu.DebugLevel.UPDATER=UPDATER -oak.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -oak.menu.DebugLevel.OTA=OTA -oak.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -oak.menu.DebugLevel.OOM=OOM -oak.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -oak.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -oak.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h" -oak.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -oak.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -oak.menu.FlashErase.none=Only Sketch -oak.menu.FlashErase.none.upload.erase_cmd= -oak.menu.FlashErase.sdk=Sketch + WiFi Settings -oak.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -oak.menu.FlashErase.all=All Flash Contents -oak.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -oak.menu.UploadSpeed.921600=921600 -oak.menu.UploadSpeed.921600.upload.speed=921600 -oak.menu.UploadSpeed.9600=9600 -oak.menu.UploadSpeed.9600.upload.speed=9600 -oak.menu.UploadSpeed.57600=57600 -oak.menu.UploadSpeed.57600.upload.speed=57600 -oak.menu.UploadSpeed.115200=115200 -oak.menu.UploadSpeed.115200.upload.speed=115200 -oak.menu.UploadSpeed.230400.linux=230400 -oak.menu.UploadSpeed.230400.macosx=230400 -oak.menu.UploadSpeed.230400.upload.speed=230400 -oak.menu.UploadSpeed.256000.windows=256000 -oak.menu.UploadSpeed.256000.upload.speed=256000 -oak.menu.UploadSpeed.460800.linux=460800 -oak.menu.UploadSpeed.460800.macosx=460800 -oak.menu.UploadSpeed.460800.upload.speed=460800 -oak.menu.UploadSpeed.512000.windows=512000 -oak.menu.UploadSpeed.512000.upload.speed=512000 - diff --git a/arduino/version 2.4.1/platform.txt b/arduino/version 2.4.1/platform.txt deleted file mode 100644 index 2ddeb0065..000000000 --- a/arduino/version 2.4.1/platform.txt +++ /dev/null @@ -1,137 +0,0 @@ - -# ESP8266 platform -# ------------------------------ - -# For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification - -name=ESP8266 Modules -version=2.4.1 - - - - -compiler.warning_flags=-w -compiler.warning_flags.none=-w -compiler.warning_flags.default= -compiler.warning_flags.more=-Wall -compiler.warning_flags.all=-Wall -Wextra - -build.lwip_lib=-llwip_gcc -build.lwip_include=lwip/include -build.lwip_flags=-DLWIP_OPEN_SRC - -#build.float=-u _printf_float -u _scanf_float -build.float= -build.led= - -compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ -compiler.sdk.path={runtime.platform.path}/tools/sdk -compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf -compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" - -compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections - -compiler.S.cmd=xtensa-lx106-elf-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls - -compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read - -compiler.c.elf.cmd=xtensa-lx106-elf-gcc -compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 -lstdc++ -lm -lc -lgcc - -compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections - -compiler.as.cmd=xtensa-lx106-elf-as - -compiler.ar.cmd=xtensa-lx106-elf-ar -compiler.ar.flags=cru - -compiler.elf2hex.cmd=esptool -compiler.elf2hex.flags= - -compiler.size.cmd=xtensa-lx106-elf-size - -compiler.esptool.cmd=esptool -compiler.esptool.cmd.windows=esptool.exe - -# This can be overriden in boards.txt -build.extra_flags=-DESP8266 - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags= -compiler.S.extra_flags= -compiler.cpp.extra_flags= -compiler.ar.extra_flags= -compiler.objcopy.eep.extra_flags= -compiler.elf2hex.extra_flags= - -## generate file with git version number -## needs bash, git, and echo - - -## windows-compatible version without git - - - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Create archives -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/arduino.ar" "{object_file}" - -## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/arduino.ar" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" - -## Create eeprom -recipe.objcopy.eep.pattern= - -## Create hex -#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" - -recipe.objcopy.hex.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec - -## Save hex -recipe.output.tmp_file={build.project_name}.bin -recipe.output.save_file={build.project_name}.{build.variant}.bin - -## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* -#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* - -# ------------------------------ - -tools.esptool.cmd=esptool -tools.esptool.cmd.windows=esptool.exe -tools.esptool.path={runtime.tools.esptool.path} -tools.esptool.network_cmd=python -tools.esptool.network_cmd.windows=python.exe - -tools.esptool.upload.protocol=esp -tools.esptool.upload.params.verbose=-vv -tools.esptool.upload.params.quiet= -tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin" -tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" - -tools.mkspiffs.cmd=mkspiffs -tools.mkspiffs.cmd.windows=mkspiffs.exe -tools.mkspiffs.path={runtime.tools.mkspiffs.path} - -tools.espupload.cmd=python -tools.espupload.cmd.windows=python.exe -tools.espupload.path={runtime.platform.path}/tools -tools.espupload.upload.protocol=espupload -tools.espupload.upload.params.verbose= -tools.espupload.upload.params.quiet= -tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" diff --git a/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h b/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h index 1f7b88589..90704f0c7 100644 --- a/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h @@ -46,7 +46,11 @@ THE SOFTWARE. // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 #ifndef __arm__ - #include + #if (defined(__AVR__)) + #include + #else + #include + #endif #else // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen #ifndef __PGMSPACE_H_ @@ -109,11 +113,19 @@ THE SOFTWARE. #define DEBUG_PRINTLN(x) Serial.println(x) #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) #else +#ifndef DEBUG_PRINT #define DEBUG_PRINT(x) +#endif +#ifndef DEBUG_PRINTF #define DEBUG_PRINTF(x, y) +#endif +#ifndef DEBUG_PRINTLN #define DEBUG_PRINTLN(x) +#endif +#ifndef DEBUG_PRINTLNF #define DEBUG_PRINTLNF(x, y) #endif +#endif #define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] #define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[] @@ -402,7 +414,7 @@ uint8_t MPU6050::dmpInitialize() { setIntEnabled(0x12); DEBUG_PRINTLN(F("Setting sample rate to 200Hz...")); - setRate(4); // 1khz / (1 + 4) = 200 Hz + setRate(1); // 1khz / (1 + 4) = 200 Hz DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]...")); setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L); diff --git a/lib/IRremoteESP8266-2.2.1.02/README.md b/lib/IRremoteESP8266-2.2.1.02/README.md deleted file mode 100644 index 6b2975793..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# IRremote ESP8266 Library - -[![Build Status](https://travis-ci.org/markszabo/IRremoteESP8266.svg?branch=master)](https://travis-ci.org/markszabo/IRremoteESP8266) -[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Average time to resolve an issue") -[![Percentage of issues still open](http://isitmaintained.com/badge/open/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Percentage of issues still open") -[![GitLicense](https://gitlicense.com/badge/markszabo/IRremoteESP8266)](https://gitlicense.com/license/markszabo/IRremoteESP8266) - -This library enables you to **send and receive** infra-red signals on an ESP8266 using Arduino framework (https://github.com/esp8266/Arduino) - -## v2.2 Now Available -Version 2.2 of the library is now available. This is a significant internal change to existing versions. - -## Upgrading from versions prior to v2.0 -You will need to change your pre-v2.0 code slightly to work with post-v2.0 versions of the library. You can read more about the changes on our [wiki](https://github.com/markszabo/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. -Please [report an issue](https://github.com/markszabo/IRremoteESP8266/issues/new) if you find any problems with the documentation or the library itself. - -## Troubleshooting -Before reporting an issue or asking for help, please try to follow our [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide) first. - -## Frequently Asked Questions -Some common answers to common questions and problems can be found on our [F.A.Q. wiki page](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions). - -## History -This library was originally based on Ken Shirriff's work (https://github.com/shirriff/Arduino-IRremote/) - -[Mark Szabo](https://github.com/markszabo/IRremoteESP8266) has updated the IRsend class to work on ESP8266 and [Sebastien Warin](https://github.com/sebastienwarin/IRremoteESP8266) the receiving & decoding part (IRrecv class). - -## Installation -1. Click "Download ZIP" -2. Extract the downloaded zip file -3. Rename the extracted folder to "IRremoteESP8266" -4. Move this folder to your libraries directory (under windows: C:\Users\YOURNAME\Documents\Arduino\libraries\) -5. Restart your Arduino ide -6. Check out the examples - -###### Using Git to install library ( Linux ) -``` -cd ~/Arduino/libraries -git clone https://github.com/markszabo/IRremoteESP8266.git -``` -###### To Update to the latest version of the library -` -cd ~/Arduino/libraries/IRremoteESP8266 && git pull -` - -## Unit Tests -The [Unit Tests](https://en.wikipedia.org/wiki/Unit_testing) under the test/ directory are for a Unix machine, **not** the micro-controller (ESP8266). -This allows execution under Travis and on the developer's machine. -We can do this from v2.0 of the library onwards, as everything now uses c98-style type definitions. -e.g. uint16_t etc. -Any Arduino/ESP8266 specific code needs to be disabled using something similar to the following lines: -``` -#ifndef UNIT_TEST - -#endif -``` - -This is not a perfect situation as we can not obviously emulate hardware specific features and differences. e.g. Interrupts, GPIOs, CPU instruction timing etc, etc. - -If you want to run all the tests yourself, try the following: -``` -$ cd test -$ make run -``` - -## Contributing -If you want to [contribute](.github/CONTRIBUTING.md#how-can-i-contribute) to this project, consider: -- [Report](.github/CONTRIBUTING.md#reporting-bugs) bugs and errors -- Ask for enhancements -- [Create issues](.github/CONTRIBUTING.md#reporting-bugs) and [pull requests](.github/CONTRIBUTING.md#pull-requests) -- Tell other people about this library - -## Contributors -Available [here](.github/Contributors.md) diff --git a/lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md b/lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md deleted file mode 100644 index 3b9bce86a..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md +++ /dev/null @@ -1,112 +0,0 @@ -# Release Notes - -## _v2.2.1 (20171025)_ - -**[Features]** -- Support for sending and decoding Nikai TV messages. (#311, #313) -- gc_decode: External utility to decode Global Cache codes. (#308, #312) -- IRMQTTServer: Example code to send IR messages via HTTP & MQTT. (#316, #323) -- Improve converting 64bit values to hexidecimal. (#318) - -**[Misc]** -- IRrecvDump.ino code is now deprecated. Use IRrecvDumpV2.ino instead. (#314) - - -## _v2.2.0 (20170922)_ - -**[Bug Fixes]** -- Add printing output of RC-MM and RC-5X protocols in example code. (#284) -- LG timing improvements based on observations (#291) - -**[Features]** -- Automatic capture timing calibration for some protocols. (#268) -- Support for creating & sending Trotec AC codes. (#279) -- Support for creating & sending Argo Ulisse 13 DCI codes. (#280 #300) -- Move to 2 microsecond timing resolution for capture of codes. (#287) -- Capture buffer changes: -- Size at runtime. (#276) -- Message timeout at runtime. (#294) -- Simplify creating & using a second buffer (#303) -- New example code: - - Trotec A/C (#279) - - LG A/C units (#289) - - Argo Ulisse 13 DCI codes. (#300) - - -## _v2.1.1 (20170711)_ - -**[Bug Fixes]** -- GlobalCache incorrectly using hardware offset for period calc. (#267) - -**[Features]** -- Support reporting of 'NEC'-like 32-bit protocols. e.g. Apple TV remote (#265) -- Add an example of sendRaw() to IRsendDemo.ino (#270) - - -## _v2.1.0 (20170704)_ - -**[Features]** -- Support for sending Pronto IR codes. (#248) -- Support for sending Fujitsu A/C codes. (#88) -- Minor improvements to examples. - - -## _v2.0.3 (20170618)_ - -**[Bug fixes]** -- Capture buffer could become corrupt after large message, breaking subsequent decodes. (#253) - - -## _v2.0.2 (20170615)_ - -**[Bug fixes]** -- Correct decode issue introduced in v2.0.1 affecting multiple protocol decoders (#243) -- Correct post-message gap for the Panasonic protocol(s) (#245) -- Incorrect display of the decoded uint64_t value in the example code. (#245) - - -## _v2.0.1 (20170614)_ - -**[Bug fixes]** -- Decoding protocols when it doesn't detect a post-command gap, and there is no more data. (#243) -- Incorrect minimum size calculation when there is no post-command gap. (#243) - - -## _v2.0.0 - 64 bit support and major improvements (20170612)_ - -**[Misc]** -- This is almost a complete re-write of the library. - -**[Features]** -- All suitable protocols now handle 64-bit data messages and are repeatable via an optional argument. -- Unit tests for all protocols. -- Far better and stricter decoding for most protocols. -- Address & command decoding for protocols where that information is available. -- Much more precise timing for generation of signals sent. -- Lower duty-cycles for some protocols. -- Several new protocols added, and some new sending and decoding routines for existing ones. -- Ability to optionally chose which protocols are included, enabling faster decoding and smaller code footprints if desired. -- Support for far larger capture buffers. (e.g. RAWLEN > 256) - -**[Bug fixes]** -- Numerous bug fixes. - - -## _v1.2.0 (20170429)_ - -**[Features]** -- Add ability to copy IR capture buffer, and continue capturing. Means faster and better IR command decoding. -- Reduce IRAM usage by 28 bytes. -- Improve capture of RC-MM & Panasonic protocols. -- Upgrade IRrecvDumpV2 to new IR capture buffer. Much fewer corrupted/truncated IR messages. - - -## _v1.1.1 (20170413)_ - -**[Bug fixes]** -- Fix a reported problem when sending the LG protocol. Preemptive fix for possible similar cases. -- Fix minor issues in examples. - -**[Features]** -- Add documentation to some examples to aid new people. -- Add ALPHA support for RC-MM protocol. (Known to be currently not 100% working.) diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino deleted file mode 100644 index bb86a5f9d..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino +++ /dev/null @@ -1,199 +0,0 @@ -/* - * IRremoteESP8266: IRrecvDumpV2 - dump details of IR codes with IRrecv - * An IR detector/demodulator must be connected to the input RECV_PIN. - * Example circuit diagram: - * https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving - * Changes: - * Version 0.2 April, 2017 - * - Decode from a copy of the data so we can start capturing faster thus - * reduce the likelihood of miscaptures. - * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, Copyright 2009 Ken Shirriff, http://arcfn.com - */ - -#ifndef UNIT_TEST -#include -#endif -#include -#include -#include - -// An IR detector/demodulator is connected to GPIO pin 14(D5 on a NodeMCU -// board). -uint16_t RECV_PIN = 14; -// As this program is a special purpose capture/decoder, let us use a larger -// than normal buffer so we can handle Air Conditioner remote codes. -uint16_t CAPTURE_BUFFER_SIZE = 1024; - -// Nr. of milli-Seconds of no-more-data before we consider a message ended. -// NOTE: Don't exceed MAX_TIMEOUT_MS. Typically 130ms. -#define TIMEOUT 15U // Suits most messages, while not swallowing repeats. -// #define TIMEOUT 90U // Suits messages with big gaps like XMP-1 & some aircon - // units, but can accidently swallow repeated messages - // in the rawData[] output. - -// Use turn on the save buffer feature for more complete capture coverage. -IRrecv irrecv(RECV_PIN, CAPTURE_BUFFER_SIZE, TIMEOUT, true); - -decode_results results; // Somewhere to store the results - -void setup() { - // Status message will be sent to the PC at 115200 baud - Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY); - delay(500); // Wait a bit for the serial connection to be establised. - - irrecv.enableIRIn(); // Start the receiver -} - -// Display encoding type -// -void encoding(decode_results *results) { - switch (results->decode_type) { - default: - case UNKNOWN: Serial.print("UNKNOWN"); break; - case NEC: Serial.print("NEC"); break; - case NEC_LIKE: Serial.print("NEC (non-strict)"); break; - case SONY: Serial.print("SONY"); break; - case RC5: Serial.print("RC5"); break; - case RC5X: Serial.print("RC5X"); break; - case RC6: Serial.print("RC6"); break; - case RCMM: Serial.print("RCMM"); break; - case DISH: Serial.print("DISH"); break; - case SHARP: Serial.print("SHARP"); break; - case JVC: Serial.print("JVC"); break; - case SANYO: Serial.print("SANYO"); break; - case SANYO_LC7461: Serial.print("SANYO_LC7461"); break; - case MITSUBISHI: Serial.print("MITSUBISHI"); break; - case SAMSUNG: Serial.print("SAMSUNG"); break; - case LG: Serial.print("LG"); break; - case WHYNTER: Serial.print("WHYNTER"); break; - case AIWA_RC_T501: Serial.print("AIWA_RC_T501"); break; - case PANASONIC: Serial.print("PANASONIC"); break; - case DENON: Serial.print("DENON"); break; - case COOLIX: Serial.print("COOLIX"); break; - case NIKAI: Serial.print("NIKAI"); break; - } - if (results->repeat) Serial.print(" (Repeat)"); -} - -// Dump out the decode_results structure. -// -void dumpInfo(decode_results *results) { - if (results->overflow) - Serial.printf("WARNING: IR code too big for buffer (>= %d). " - "These results shouldn't be trusted until this is resolved. " - "Edit & increase CAPTURE_BUFFER_SIZE.\n", - CAPTURE_BUFFER_SIZE); - - // Show Encoding standard - Serial.print("Encoding : "); - encoding(results); - Serial.println(""); - - // Show Code & length - Serial.print("Code : "); - serialPrintUint64(results->value, 16); - Serial.print(" ("); - Serial.print(results->bits, DEC); - Serial.println(" bits)"); -} - -uint16_t getCookedLength(decode_results *results) { - uint16_t length = results->rawlen - 1; - for (uint16_t i = 0; i < results->rawlen - 1; i++) { - uint32_t usecs = results->rawbuf[i] * RAWTICK; - // Add two extra entries for multiple larger than UINT16_MAX it is. - length += (usecs / UINT16_MAX) * 2; - } - return length; -} - -// Dump out the decode_results structure. -// -void dumpRaw(decode_results *results) { - // Print Raw data - Serial.print("Timing["); - Serial.print(results->rawlen - 1, DEC); - Serial.println("]: "); - - for (uint16_t i = 1; i < results->rawlen; i++) { - if (i % 100 == 0) - yield(); // Preemptive yield every 100th entry to feed the WDT. - if (i % 2 == 0) { // even - Serial.print("-"); - } else { // odd - Serial.print(" +"); - } - Serial.printf("%6d", results->rawbuf[i] * RAWTICK); - if (i < results->rawlen - 1) - Serial.print(", "); // ',' not needed for last one - if (!(i % 8)) Serial.println(""); - } - Serial.println(""); // Newline -} - -// Dump out the decode_results structure. -// -void dumpCode(decode_results *results) { - // Start declaration - Serial.print("uint16_t "); // variable type - Serial.print("rawData["); // array name - Serial.print(getCookedLength(results), DEC); // array size - Serial.print("] = {"); // Start declaration - - // Dump data - for (uint16_t i = 1; i < results->rawlen; i++) { - uint32_t usecs; - for (usecs = results->rawbuf[i] * RAWTICK; - usecs > UINT16_MAX; - usecs -= UINT16_MAX) - Serial.printf("%d, 0", UINT16_MAX); - Serial.print(usecs, DEC); - if (i < results->rawlen - 1) - Serial.print(", "); // ',' not needed on last one - if (i % 2 == 0) Serial.print(" "); // Extra if it was even. - } - - // End declaration - Serial.print("};"); // - - // Comment - Serial.print(" // "); - encoding(results); - Serial.print(" "); - serialPrintUint64(results->value, HEX); - - // Newline - Serial.println(""); - - // Now dump "known" codes - if (results->decode_type != UNKNOWN) { - // Some protocols have an address &/or command. - // NOTE: It will ignore the atypical case when a message has been decoded - // but the address & the command are both 0. - if (results->address > 0 || results->command > 0) { - Serial.print("uint32_t address = 0x"); - Serial.print(results->address, HEX); - Serial.println(";"); - Serial.print("uint32_t command = 0x"); - Serial.print(results->command, HEX); - Serial.println(";"); - } - - // All protocols have data - Serial.print("uint64_t data = 0x"); - serialPrintUint64(results->value, 16); - Serial.println(";"); - } -} - -// The repeating section of the code -// -void loop() { - // Check if the IR code has been received. - if (irrecv.decode(&results)) { - dumpInfo(&results); // Output the results - dumpRaw(&results); // Output the results in RAW format - dumpCode(&results); // Output the results as source code - Serial.println(""); // Blank line between entries - } -} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino deleted file mode 100644 index 52e31b5d8..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2017 Jonny Graham -#include -#include - -IRFujitsuAC fujitsu(5); // IR led controlled by Pin D1. - -void printState() { - // Display the settings. - Serial.println("Fujitsu A/C remote is in the following state:"); - Serial.printf(" Command:%d, Mode: %d, Temp: %dC, Fan Speed: %d," \ - " Swing Mode: %d\n", - fujitsu.getCmd(), fujitsu.getMode(), fujitsu.getTemp(), - fujitsu.getFanSpeed(), fujitsu.getSwing()); - // Display the encoded IR sequence. - unsigned char* ir_code = fujitsu.getRaw(); - Serial.print("IR Code: 0x"); - for (uint8_t i = 0; i < FUJITSU_AC_STATE_LENGTH; i++) - Serial.printf("%02X", ir_code[i]); - Serial.println(); -} - -void setup() { - fujitsu.begin(); - Serial.begin(115200); - delay(200); - - // Set up what we want to send. See ir_Mitsubishi.cpp for all the options. - Serial.println("Default state of the remote."); - printState(); - Serial.println("Setting desired state for A/C."); - fujitsu.setCmd(FUJITSU_AC_CMD_TURN_ON); - fujitsu.setSwing(FUJITSU_AC_SWING_BOTH); - fujitsu.setMode(FUJITSU_AC_MODE_COOL); - fujitsu.setFanSpeed(FUJITSU_AC_FAN_HIGH); - fujitsu.setTemp(24); -} - -void loop() { - // Now send the IR signal. - Serial.println("Sending IR command to A/C ..."); - fujitsu.send(); - printState(); - delay(5000); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/keywords.txt b/lib/IRremoteESP8266-2.2.1.02/keywords.txt deleted file mode 100644 index ab1b3f70c..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/keywords.txt +++ /dev/null @@ -1,128 +0,0 @@ -######################################### -# Syntax Coloring Map For IRremoteESP8266 -######################################### - -####################################################### -# The Arduino IDE requires the use of a tab separator -# between the name and identifier. Without this tab the -# keyword is not highlighted. -# -# Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords -####################################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -decode_results KEYWORD1 -IRrecv KEYWORD1 -IRsend KEYWORD1 -IRtimer KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -decode KEYWORD2 -enableIRIn KEYWORD2 -disableIRIn KEYWORD2 -resume KEYWORD2 -begin KEYWORD2 -send KEYWORD2 -enableIROut KEYWORD2 -sendNEC KEYWORD2 -encodeNEC KEYWORD2 -sendLG KEYWORD2 -encodeLG KEYWORD2 -sendSony KEYWORD2 -encodeSony KEYWORD2 -sendSanyo KEYWORD2 -sendSanyoLC7461 KEYWORD2 -encodeSanyoLC7461 KEYWORD2 -sendMitsubishi KEYWORD2 -sendRaw KEYWORD2 -sendGC KEYWORD2 -sendRC5 KEYWORD2 -sendRC6 KEYWORD2 -sendRCMM KEYWORD2 -sendDISH KEYWORD2 -sendSharp KEYWORD2 -sendSharpRaw KEYWORD2 -encodeSharp KEYWORD2 -sendPanasonic KEYWORD2 -sendPanasonic64 KEYWORD2 -encodePanasonic KEYWORD2 -sendJVC KEYWORD2 -encodeJVC KEYWORD2 -sendWhynter KEYWORD2 -sendSAMSUNG KEYWORD2 -encodeSAMSUNG KEYWORD2 -sendDaikin KEYWORD2 -sendCOOLIX KEYWORD2 -sendDenon KEYWORD2 -sendKelvinator KEYWORD2 -sendSherwood KEYWORD2 -sendMitsubishiAC KEYWORD2 -mark KEYWORD2 -space KEYWORD2 -reset KEYWORD2 -elapsed KEYWORD2 -calcLGChecksum KEYWORD2 -reverseBits KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### - -NEC LITERAL1 -SONY LITERAL1 -SANYO LITERAL1 -MITSUBISHI LITERAL1 -RC5 LITERAL1 -RC5X LITERAL1 -RC6 LITERAL1 -DISH LITERAL1 -SHARP LITERAL1 -PANASONIC LITERAL1 -JVC LITERAL1 -LG LITERAL1 -SAMSUNG LITERAL1 -WHYNTER LITERAL1 -AIWA_RC_T501 LITERAL1 -COOLIX LITERAL1 -UNKNOWN LITERAL1 -REPEAT LITERAL1 -DENON LITERAL1 -DAIKIN LITERAL1 -KELVINATOR LITERAL1 -SHERWOOD LITERAL1 -MITSUBISHIAC LITERAL1 -RCMM LITERAL1 -SANYO_LC7461 LITERAL1 -NEC_BITS LITERAL1 -SHERWOOD_BITS LITERAL1 -SONY_MIN_BITS LITERAL1 -SONY_12_BITS LITERAL1 -SONY_15_BITS LITERAL1 -SONY_20_BITS LITERAL1 -SANYO_SA8650B_BITS LITERAL1 -MITSUBISHI_BITS LITERAL1 -PANASONIC_BITS LITERAL1 -JVC_BITS LITERAL1 -LG_BITS LITERAL1 -SAMSUNG_BITS LITERAL1 -COOLIX_BITS LITERAL1 -DAIKIN_BITS LITERAL1 -RC5X_BITS LITERAL1 -RC6_36_BITS LITERAL1 -RC6_MODE0_BITS LITERAL1 -RCMM_BITS LITERAL1 -WHYNTER_BITS LITERAL1 -SANYO_LC7461_BITS LITERAL1 -SHARP_BITS LITERAL1 -DISH_BITS LITERAL1 -DENON_BITS LITERAL1 -SONY_MIN_REPEAT LITERAL1 -MITSUBISHI_MIN_REPEAT LITERAL1 -DISH_MIN_REPEAT LITERAL1 -SHERWOOD_MIN_REPEAT LITERAL1 diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h b/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h deleted file mode 100644 index febe5e2d5..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2015 Mark Szabo -// Copyright 2015 Sebastien Warin -// Copyright 2017 David Conran - -#ifndef IRRECV_H_ -#define IRRECV_H_ - -#ifndef UNIT_TEST -#include -#endif -#include -#define __STDC_LIMIT_MACROS -#include -#include "IRremoteESP8266.h" - -// Constants -#define HEADER 2U // Usual nr. of header entries. -#define FOOTER 2U // Usual nr. of footer (stop bits) entries. -#define OFFSET_START 1U // Usual rawbuf entry to start processing from. -#define MS_TO_USEC(x) (x * 1000U) // Convert milli-Seconds to micro-Seconds. -// Marks tend to be 100us too long, and spaces 100us too short -// when received due to sensor lag. -#define MARK_EXCESS 50U -#define RAWBUF 100U // Default length of raw capture buffer -#define REPEAT UINT64_MAX -// receiver states -#define STATE_IDLE 2U -#define STATE_MARK 3U -#define STATE_SPACE 4U -#define STATE_STOP 5U -#define TOLERANCE 25U // default percent tolerance in measurements -#define RAWTICK 2U // Capture tick to uSec factor. -// How long (ms) before we give up wait for more data? -// Don't exceed MAX_TIMEOUT_MS without a good reason. -// That is the capture buffers maximum value size. (UINT16_MAX / RAWTICK) -// Typically messages/protocols tend to repeat around the 100ms timeframe, -// thus we should timeout before that to give us some time to try to decode -// before we need to start capturing a possible new message. -// Typically 15ms suits most applications. However, some protocols demand a -// higher value. e.g. 90ms for XMP-1 and some aircon units. -#define TIMEOUT_MS 15U // In MilliSeconds. -#define MAX_TIMEOUT_MS (RAWTICK * UINT16_MAX / MS_TO_USEC(1)) - -// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param -#define FNV_PRIME_32 16777619UL -#define FNV_BASIS_32 2166136261UL - -// Types -// information for the interrupt handler -typedef struct { - uint8_t recvpin; // pin for IR data from detector - uint8_t rcvstate; // state machine - uint16_t timer; // state timer, counts 50uS ticks. - uint16_t bufsize; // max. nr. of entries in the capture buffer. - uint16_t *rawbuf; // raw data - // uint16_t is used for rawlen as it saves 3 bytes of iram in the interrupt - // handler. Don't ask why, I don't know. It just does. - uint16_t rawlen; // counter of entries in rawbuf. - uint8_t overflow; // Buffer overflow indicator. - uint8_t timeout; // Nr. of milliSeconds before we give up. -} irparams_t; - -// results from a data match -typedef struct { - bool success; // Was the match successful? - uint64_t data; // The data found. - uint16_t used; // How many buffer positions were used. -} match_result_t; - -// Classes - -// Results returned from the decoder -class decode_results { - public: - decode_type_t decode_type; // NEC, SONY, RC5, UNKNOWN - uint64_t value; // Decoded value - uint16_t bits; // Number of bits in decoded value - volatile uint16_t *rawbuf; // Raw intervals in .5 us ticks - uint16_t rawlen; // Number of records in rawbuf. - bool overflow; - bool repeat; // Is the result a repeat code? - uint32_t address; // Decoded device address. - uint32_t command; // Decoded command. -}; - -// main class for receiving IR -class IRrecv { - public: - explicit IRrecv(uint16_t recvpin, uint16_t bufsize = RAWBUF, - uint8_t timeout = TIMEOUT_MS, - bool save_buffer = false); // Constructor - ~IRrecv(); // Destructor - bool decode(decode_results *results, irparams_t *save = NULL); - void enableIRIn(); - void disableIRIn(); - void resume(); - uint16_t getBufSize(); - -#ifndef UNIT_TEST - - private: -#endif - irparams_t *irparams_save; - // These are called by decode - void copyIrParams(volatile irparams_t *src, irparams_t *dst); - int16_t compare(uint16_t oldval, uint16_t newval); - uint32_t ticksLow(uint32_t usecs, uint8_t tolerance = TOLERANCE); - uint32_t ticksHigh(uint32_t usecs, uint8_t tolerance = TOLERANCE); - bool match(uint32_t measured, uint32_t desired, - uint8_t tolerance = TOLERANCE); - bool matchAtLeast(uint32_t measured, uint32_t desired, - uint8_t tolerance = TOLERANCE); - bool matchMark(uint32_t measured, uint32_t desired, - uint8_t tolerance = TOLERANCE, int16_t excess = MARK_EXCESS); - bool matchSpace(uint32_t measured, uint32_t desired, - uint8_t tolerance = TOLERANCE, int16_t excess = MARK_EXCESS); - match_result_t matchData(volatile uint16_t *data_ptr, uint16_t nbits, - uint16_t onemark, uint32_t onespace, - uint16_t zeromark, uint32_t zerospace); - bool decodeHash(decode_results *results); -#if (DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || SEND_SANYO) - bool decodeNEC(decode_results *results, uint16_t nbits = NEC_BITS, - bool strict = true); -#endif -#if DECODE_SONY - bool decodeSony(decode_results *results, uint16_t nbits = SONY_MIN_BITS, - bool strict = false); -#endif -#if DECODE_SANYO - // DISABLED due to poor quality. - // bool decodeSanyo(decode_results *results, - // uint16_t nbits = SANYO_SA8650B_BITS, - // bool strict = false); - bool decodeSanyoLC7461(decode_results *results, - uint16_t nbits = SANYO_LC7461_BITS, - bool strict = true); -#endif -#if DECODE_MITSUBISHI - bool decodeMitsubishi(decode_results *results, - uint16_t nbits = MITSUBISHI_BITS, - bool strict = true); -#endif -#if (DECODE_RC5 || DECODE_R6) - int16_t getRClevel(decode_results *results, uint16_t *offset, uint16_t *used, - uint16_t bitTime); -#endif -#if DECODE_RC5 - bool decodeRC5(decode_results *results, uint16_t nbits = RC5X_BITS, - bool strict = true); -#endif -#if DECODE_RC6 - bool decodeRC6(decode_results *results, uint16_t nbits = RC6_MODE0_BITS, - bool strict = false); -#endif -#if DECODE_RCMM - bool decodeRCMM(decode_results *results, uint16_t nbits = RCMM_BITS, - bool strict = false); -#endif -#if (DECODE_PANASONIC || DECODE_DENON) - bool decodePanasonic(decode_results *results, uint16_t nbits = PANASONIC_BITS, - bool strict = false, - uint32_t manufacturer = PANASONIC_MANUFACTURER); -#endif -#if DECODE_LG - bool decodeLG(decode_results *results, uint16_t nbits = LG_BITS, - bool strict = false); -#endif -#if DECODE_JVC - bool decodeJVC(decode_results *results, uint16_t nbits = JVC_BITS, - bool strict = true); -#endif -#if DECODE_SAMSUNG - bool decodeSAMSUNG(decode_results *results, uint16_t nbits = SAMSUNG_BITS, - bool strict = true); -#endif -#if DECODE_WHYNTER - bool decodeWhynter(decode_results *results, uint16_t nbits = WHYNTER_BITS, - bool strict = true); -#endif -#if DECODE_COOLIX - bool decodeCOOLIX(decode_results *results, uint16_t nbits = COOLIX_BITS, - bool strict = true); -#endif -#if DECODE_DENON - bool decodeDenon(decode_results *results, uint16_t nbits = DENON_BITS, - bool strict = true); -#endif -#if DECODE_DISH - bool decodeDISH(decode_results *results, uint16_t nbits = DISH_BITS, - bool strict = true); -#endif -#if (DECODE_SHARP || DECODE_DENON) - bool decodeSharp(decode_results *results, uint16_t nbits = SHARP_BITS, - bool strict = true, bool expansion = true); -#endif -#if DECODE_AIWA_RC_T501 - bool decodeAiwaRCT501(decode_results *results, - uint16_t nbits = AIWA_RC_T501_BITS, bool strict = true); -#endif -#if DECODE_NIKAI - bool decodeNikai(decode_results *results, uint16_t nbits = NIKAI_BITS, - bool strict = true); -#endif -}; - -#endif // IRRECV_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h deleted file mode 100644 index e2dc26904..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h +++ /dev/null @@ -1,337 +0,0 @@ - /*************************************************** - * IRremote for ESP8266 - * - * Based on the IRremote library for Arduino by Ken Shirriff - * Version 0.11 August, 2009 - * Copyright 2009 Ken Shirriff - * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html - * - * Edited by Mitra to add new controller SANYO - * - * Interrupt code based on NECIRrcv by Joe Knapp - * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 - * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ - * - * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) - * LG added by Darryl Smith (based on the JVC protocol) - * Whynter A/C ARC-110WD added by Francesco Meschia - * Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit - * Denon: sendDenon, decodeDenon added by Massimiliano Pinto - (from https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp) - * Kelvinator A/C and Sherwood added by crankyoldgit - * Mitsubishi (TV) sending added by crankyoldgit - * Pronto code sending added by crankyoldgit - * Mitsubishi A/C added by crankyoldgit - * (derived from https://github.com/r45635/HVAC-IR-Control) - * DISH decode by marcosamarinho - * Gree Heatpump sending added by Ville Skyttä (scop) - * (derived from https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp) - * Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for sending IR code on ESP8266 - * Updated by Sebastien Warin (http://sebastien.warin.fr) for receiving IR code on ESP8266 - * - * Updated by sillyfrog for Daikin, adopted from - * (https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/) - * Fujitsu A/C code added by jonnygraham - * Trotec AC code by stufisher - * GPL license, all text above must be included in any redistribution - ****************************************************/ - -#ifndef IRREMOTEESP8266_H_ -#define IRREMOTEESP8266_H_ - -#define __STDC_LIMIT_MACROS -#include -#ifdef UNIT_TEST -#include -#endif - -// Library Version -#define _IRREMOTEESP8266_VERSION_ "2.2.1" -// Supported IR protocols -// Each protocol you include costs memory and, during decode, costs time -// Disable (set to false) all the protocols you do not need/want! -// -/* -#define DECODE_NEC true -#define SEND_NEC true - -#define DECODE_SHERWOOD true // Doesn't exist. Actually is DECODE_NEC -#define SEND_SHERWOOD true - -#define DECODE_RC5 true -#define SEND_RC5 true - -#define DECODE_RC6 true -#define SEND_RC6 true - -#define DECODE_RCMM true -#define SEND_RCMM true - -#define DECODE_SONY true -#define SEND_SONY true - -#define DECODE_PANASONIC true -#define SEND_PANASONIC true - -#define DECODE_JVC true -#define SEND_JVC true - -#define DECODE_SAMSUNG true -#define SEND_SAMSUNG true - -#define DECODE_WHYNTER true -#define SEND_WHYNTER true - -#define DECODE_AIWA_RC_T501 true -#define SEND_AIWA_RC_T501 true - -#define DECODE_LG true -#define SEND_LG true - -#define DECODE_SANYO true -#define SEND_SANYO true - -#define DECODE_MITSUBISHI true -#define SEND_MITSUBISHI true - -#define DECODE_DISH true -#define SEND_DISH true - -#define DECODE_SHARP true -#define SEND_SHARP true - -#define DECODE_DENON true -#define SEND_DENON true - -#define DECODE_KELVINATOR false // Not written. -#define SEND_KELVINATOR true - -#define DECODE_MITSUBISHI_AC false // Not written. -#define SEND_MITSUBISHI_AC true - -#define DECODE_FUJITSU_AC false // Not written. -#define SEND_FUJITSU_AC true - -#define DECODE_DAIKIN false // Not finished. -#define SEND_DAIKIN true - -#define DECODE_COOLIX true -#define SEND_COOLIX true - -#define DECODE_GLOBALCACHE false // Not written. -#define SEND_GLOBALCACHE true - -#define DECODE_GREE false // Not written. -#define SEND_GREE true - -#define DECODE_PRONTO false // Not written. -#define SEND_PRONTO true - -#define DECODE_ARGO false // Not written. -#define SEND_ARGO true - -#define DECODE_TROTEC false // Not implemented. -#define SEND_TROTEC true - -#define DECODE_NIKAI true -#define SEND_NIKAI true -*/ - -// Tasmota supported protocols (less protocols is less code size) -#define DECODE_NEC true -#define SEND_NEC true - -#define DECODE_SHERWOOD false // Doesn't exist. Actually is DECODE_NEC -#define SEND_SHERWOOD false - -#define DECODE_RC5 true -#define SEND_RC5 true - -#define DECODE_RC6 true -#define SEND_RC6 true - -#define DECODE_RCMM false -#define SEND_RCMM false - -#define DECODE_SONY true -#define SEND_SONY true - -#define DECODE_PANASONIC true -#define SEND_PANASONIC true - -#define DECODE_JVC true -#define SEND_JVC true - -#define DECODE_SAMSUNG true -#define SEND_SAMSUNG true - -#define DECODE_WHYNTER false -#define SEND_WHYNTER false - -#define DECODE_AIWA_RC_T501 false -#define SEND_AIWA_RC_T501 false - -#define DECODE_LG false -#define SEND_LG false - -#define DECODE_SANYO false -#define SEND_SANYO false - -#define DECODE_MITSUBISHI false -#define SEND_MITSUBISHI false - -#define DECODE_DISH false -#define SEND_DISH true - -#define DECODE_SHARP false -#define SEND_SHARP false - -#define DECODE_DENON false -#define SEND_DENON false - -#define DECODE_KELVINATOR false // Not written. -#define SEND_KELVINATOR false - -#define DECODE_MITSUBISHI_AC false // Not written. -#define SEND_MITSUBISHI_AC true - -#define DECODE_FUJITSU_AC false // Not written. -#define SEND_FUJITSU_AC false - -#define DECODE_DAIKIN false // Not finished. -#define SEND_DAIKIN false - -#define DECODE_COOLIX false -#define SEND_COOLIX false - -#define DECODE_GLOBALCACHE false // Not written. -#define SEND_GLOBALCACHE false - -#define DECODE_GREE false // Not written. -#define SEND_GREE false - -#define DECODE_PRONTO false // Not written. -#define SEND_PRONTO false - -#define DECODE_ARGO false // Not written. -#define SEND_ARGO false - -#define DECODE_TROTEC false // Not implemented. -#define SEND_TROTEC false - -#define DECODE_NIKAI false -#define SEND_NIKAI false - -/* - * Always add to the end of the list and should never remove entries - * or change order. Projects may save the type number for later usage - * so numbering should always stay the same. - */ -enum decode_type_t { - UNKNOWN = -1, - UNUSED = 0, - RC5, - RC6, - NEC, - SONY, - PANASONIC, - JVC, - SAMSUNG, - WHYNTER, - AIWA_RC_T501, - LG, - SANYO, - MITSUBISHI, - DISH, - SHARP, - COOLIX, - DAIKIN, - DENON, - KELVINATOR, - SHERWOOD, - MITSUBISHI_AC, - RCMM, - SANYO_LC7461, - RC5X, - GREE, - PRONTO, // Technically not a protocol, but an encoding. - NEC_LIKE, - ARGO, - TROTEC, - NIKAI, - RAW, // Technically not a protocol, but an encoding. - GLOBALCACHE // Technically not a protocol, but an encoding. -}; - -// Message lengths & required repeat values -#define AIWA_RC_T501_BITS 15U -#define AIWA_RC_T501_MIN_REPEAT 1U -#define COOLIX_BITS 24U -#define DAIKIN_BITS 99U -#define DAIKIN_COMMAND_LENGTH 27U -#define DENON_BITS SHARP_BITS -#define DENON_48_BITS PANASONIC_BITS -#define DENON_LEGACY_BITS 14U -#define DISH_BITS 16U -#define DISH_MIN_REPEAT 3U -#define GREE_STATE_LENGTH 8U -#define GREE_BITS (GREE_STATE_LENGTH * 8) -#define JVC_BITS 16U -#define KELVINATOR_STATE_LENGTH 16U -#define LG_BITS 28U -#define LG32_BITS 32U -#define MITSUBISHI_BITS 16U -// TODO(anyone): Verify that the Mitsubishi repeat is really needed. -#define MITSUBISHI_MIN_REPEAT 1U // Based on marcosamarinho's code. -#define MITSUBISHI_AC_STATE_LENGTH 18U -#define MITSUBISHI_AC_MIN_REPEAT 1U -#define FUJITSU_AC_MIN_REPEAT 0U -#define NEC_BITS 32U -#define PANASONIC_BITS 48U -#define PANASONIC_MANUFACTURER 0x4004ULL -#define PRONTO_MIN_LENGTH 6U -#define RC5_RAW_BITS 14U -#define RC5_BITS RC5_RAW_BITS - 2U -#define RC5X_BITS RC5_RAW_BITS - 1U -#define RC6_MODE0_BITS 20U // Excludes the 'start' bit. -#define RC6_36_BITS 36U // Excludes the 'start' bit. -#define RCMM_BITS 24U -#define SAMSUNG_BITS 32U -#define SANYO_SA8650B_BITS 12U -#define SANYO_LC7461_ADDRESS_BITS 13U -#define SANYO_LC7461_COMMAND_BITS 8U -#define SANYO_LC7461_BITS ((SANYO_LC7461_ADDRESS_BITS + \ - SANYO_LC7461_COMMAND_BITS) * 2) -#define SHARP_ADDRESS_BITS 5U -#define SHARP_COMMAND_BITS 8U -#define SHARP_BITS (SHARP_ADDRESS_BITS + SHARP_COMMAND_BITS + 2) // 15U -#define SHERWOOD_BITS NEC_BITS -#define SHERWOOD_MIN_REPEAT 1U -#define SONY_12_BITS 12U -#define SONY_15_BITS 15U -#define SONY_20_BITS 20U -#define SONY_MIN_BITS SONY_12_BITS -#define SONY_MIN_REPEAT 2U -#define TROTEC_COMMAND_LENGTH 9U -#define WHYNTER_BITS 32U -#define ARGO_COMMAND_LENGTH 12U -#define NIKAI_BITS 24U - -// Turn on Debugging information by uncommenting the following line. -// #define DEBUG 1 - -#ifdef DEBUG -#ifdef UNIT_TEST -#define DPRINT(x) do { std::cout << x; } while (0) -#define DPRINTLN(x) do { std::cout << x << std::endl; } while (0) -#endif // UNIT_TEST -#ifdef ARDUINO -#define DPRINT(x) do { Serial.print(x); } while (0) -#define DPRINTLN(x) do { Serial.println(x); } while (0) -#endif // ARDUINO -#else // DEBUG -#define DPRINT(x) -#define DPRINTLN(x) -#endif // DEBUG - -#endif // IRREMOTEESP8266_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp b/lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp deleted file mode 100644 index 300b1fa99..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2015 Mark Szabo -// Copyright 2017 David Conran - -#include "IRsend.h" -#ifndef UNIT_TEST -#include -#else -#define __STDC_LIMIT_MACROS -#include -#endif -#include -#ifdef UNIT_TEST -#include -#endif -#include "IRtimer.h" - -// Originally from https://github.com/shirriff/Arduino-IRremote/ -// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for -// sending IR code on ESP8266 - -// IRsend ---------------------------------------------------------------------- -// Create an IRsend object. -// -// Args: -// IRsendPin: Which GPIO pin to use when sending an IR command. -// inverted: *DANGER* Optional flag to invert the output. (default = false) -// e.g. LED is illuminated when GPIO is LOW rather than HIGH. -// Setting this to something other than the default could -// easily destroy your IR LED if you are overdriving it. -// Unless you *REALLY* know what you are doing, don't change this. -// Returns: -// An IRsend object. -IRsend::IRsend(uint16_t IRsendPin, bool inverted) : IRpin(IRsendPin), - periodOffset(PERIOD_OFFSET) { - if (inverted) { - outputOn = LOW; - outputOff = HIGH; - } else { - outputOn = HIGH; - outputOff = LOW; - } -} - -// Enable the pin for output. -void IRsend::begin() { -#ifndef UNIT_TEST - pinMode(IRpin, OUTPUT); -#endif -} - -// Turn off the IR LED. -void IRsend::ledOff() { -#ifndef UNIT_TEST - digitalWrite(IRpin, outputOff); -#endif -} - -// Calculate the period for a given frequency. (T = 1/f) -// -// Args: -// freq: Frequency in Hz. -// use_offset: Should we use the calculated offset or not? -// Returns: -// nr. of uSeconds. -uint32_t IRsend::calcUSecPeriod(uint32_t hz, bool use_offset) { - if (hz == 0) hz = 1; // Avoid Zero hz. Divide by Zero is nasty. - uint32_t period = (1000000UL + hz/2) / hz; // The equiv of round(1000000/hz). - // Apply the offset and ensure we don't result in a <= 0 value. - if (use_offset) - return std::max((uint32_t) 1, period + periodOffset); - else - return std::max((uint32_t) 1, period); -} - -// Set the output frequency modulation and duty cycle. -// -// Args: -// freq: The freq we want to modulate at. Assumes < 1000 means kHz else Hz. -// duty: Percentage duty cycle of the LED. e.g. 25 = 25% = 1/4 on, 3/4 off. -// -// Note: -// Integer timing functions & math mean we can't do fractions of -// microseconds timing. Thus minor changes to the freq & duty values may have -// limited effect. You've been warned. -void IRsend::enableIROut(uint32_t freq, uint8_t duty) { - // Can't have more than 100% duty cycle. - duty = std::min(duty, (uint8_t) 100); - if (freq < 1000) // Were we given kHz? Supports the old call usage. - freq *= 1000; - uint32_t period = calcUSecPeriod(freq); - // Nr. of uSeconds the LED will be on per pulse. - onTimePeriod = (period * duty) / 100; - // Nr. of uSeconds the LED will be off per pulse. - offTimePeriod = period - onTimePeriod; -} - -// Modulate the IR LED for the given period (usec) and at the duty cycle set. -// -// Args: -// usec: The period of time to modulate the IR LED for, in microseconds. -// Returns: -// Nr. of pulses actually sent. -// -// Note: -// The ESP8266 has no good way to do hardware PWM, so we have to do it all -// in software. There is a horrible kludge/brilliant hack to use the second -// serial TX line to do fairly accurate hardware PWM, but it is only -// available on a single specific GPIO and only available on some modules. -// e.g. It's not available on the ESP-01 module. -// Hence, for greater compatibility & choice, we don't use that method. -// Ref: -// https://www.analysir.com/blog/2017/01/29/updated-esp8266-nodemcu-backdoor-upwm-hack-for-ir-signals/ -uint16_t IRsend::mark(uint16_t usec) { - uint16_t counter = 0; - IRtimer usecTimer = IRtimer(); - // Cache the time taken so far. This saves us calling time, and we can be - // assured that we can't have odd math problems. i.e. unsigned under/overflow. - uint32_t elapsed = usecTimer.elapsed(); - - while (elapsed < usec) { // Loop until we've met/exceeded our required time. -#ifndef UNIT_TEST - digitalWrite(IRpin, outputOn); // Turn the LED on. - // Calculate how long we should pulse on for. - // e.g. Are we to close to the end of our requested mark time (usec)? - delayMicroseconds(std::min((uint32_t) onTimePeriod, usec - elapsed)); - digitalWrite(IRpin, outputOff); // Turn the LED off. -#endif - counter++; - if (elapsed + onTimePeriod >= usec) - return counter; // LED is now off & we've passed our allotted time. - // Wait for the lesser of the rest of the duty cycle, or the time remaining. -#ifndef UNIT_TEST - delayMicroseconds(std::min(usec - elapsed - onTimePeriod, - (uint32_t) offTimePeriod)); -#endif - elapsed = usecTimer.elapsed(); // Update & recache the actual elapsed time. - } - return counter; -} - -// Turn the pin (LED) off for a given time. -// Sends an IR space for the specified number of microseconds. -// A space is no output, so the PWM output is disabled. -// -// Args: -// time: Time in microseconds (us). -void IRsend::space(uint32_t time) { - ledOff(); - if (time == 0) return; -#ifndef UNIT_TEST - // delayMicroseconds is only accurate to 16383us. - // Ref: https://www.arduino.cc/en/Reference/delayMicroseconds - if (time <= 16383) { - delayMicroseconds(time); - } else { - // Invoke a delay(), where possible, to avoid triggering the WDT. - delay(time / 1000UL); // Delay for as many whole milliseconds as we can. - // Delay the remaining sub-millisecond. - delayMicroseconds(static_cast(time % 1000UL)); - } -#endif -} - -// Calculate & set any offsets to account for execution times. -// -// Args: -// hz: The frequency to calibrate at >= 1000Hz. Default is 38000Hz. -// -// Status: ALPHA / Untested. -// -// NOTE: -// This will generate an 65535us mark() IR LED signal. -// This only needs to be called once, if at all. -void IRsend::calibrate(uint16_t hz) { - if (hz < 1000) // Were we given kHz? Supports the old call usage. - hz *= 1000; - periodOffset = 0; // Turn off any existing offset while we calibrate. - enableIROut(hz); - IRtimer usecTimer = IRtimer(); // Start a timer *just* before we do the call. - uint16_t pulses = mark(UINT16_MAX); // Generate a PWM of 65,535 us. (Max.) - uint32_t timeTaken = usecTimer.elapsed(); // Record the time it took. - // While it shouldn't be necessary, assume at least 1 pulse, to avoid a - // divide by 0 situation. - pulses = std::max(pulses, (uint16_t) 1U); - uint32_t calcPeriod = calcUSecPeriod(hz); // e.g. @38kHz it should be 26us. - // Assuming 38kHz for the example calculations: - // In a 65535us pulse, we should have 2520.5769 pulses @ 26us periods. - // e.g. 65535.0us / 26us = 2520.5769 - // This should have caused approx 2520 loops through the main loop in mark(). - // The average over that many interations should give us a reasonable - // approximation at what offset we need to use to account for instruction - // execution times. - // - // Calculate the actual period from the actual time & the actual pulses - // generated. - double_t actualPeriod = (double_t) timeTaken / (double_t) pulses; - // Store the difference between the actual time per period vs. calculated. - periodOffset = (int8_t) ((double_t) calcPeriod - actualPeriod); -} - -// Generic method for sending data that is common to most protocols. -// Will send leading or trailing 0's if the nbits is larger than the number -// of bits in data. -// -// Args: -// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. -// onespace: Nr. of usecs for the led to be fully off for a '1' bit. -// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. -// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. -// data: The data to be transmitted. -// nbits: Nr. of bits of data to be sent. -// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. -void IRsend::sendData(uint16_t onemark, uint32_t onespace, - uint16_t zeromark, uint32_t zerospace, - uint64_t data, uint16_t nbits, bool MSBfirst) { - if (nbits == 0) // If we are asked to send nothing, just return. - return; - if (MSBfirst) { // Send the MSB first. - // Send 0's until we get down to a bit size we can actually manage. - while (nbits > sizeof(data) * 8) { - mark(zeromark); - space(zerospace); - nbits--; - } - // Send the supplied data. - for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) - if (data & mask) { // Send a 1 - mark(onemark); - space(onespace); - } else { // Send a 0 - mark(zeromark); - space(zerospace); - } - } else { // Send the Least Significant Bit (LSB) first / MSB last. - for (uint16_t bit = 0; bit < nbits; bit++, data >>= 1) - if (data & 1) { // Send a 1 - mark(onemark); - space(onespace); - } else { // Send a 0 - mark(zeromark); - space(zerospace); - } - } -} - -// Send a raw IRremote message. -// -// Args: -// buf: An array of uint16_t's that has microseconds elements. -// len: Nr. of elements in the buf[] array. -// hz: Frequency to send the message at. (kHz < 1000; Hz >= 1000) -// -// Status: STABLE / Known working. -// -// Notes: -// Even elements are Mark times (On), Odd elements are Space times (Off). -// -// Ref: -// examples/IRrecvDumpV2/IRrecvDumpV2.ino -void IRsend::sendRaw(uint16_t buf[], uint16_t len, uint16_t hz) { - // Set IR carrier frequency - enableIROut(hz); - for (uint16_t i = 0; i < len; i++) { - if (i & 1) { // Odd bit. - space(buf[i]); - } else { // Even bit. - mark(buf[i]); - } - } - ledOff(); // We potentially have ended with a mark(), so turn of the LED. -} - -#ifndef UNIT_TEST -void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) { - switch (type) { -#if SEND_NEC - case NEC: sendNEC(data, nbits); break; -#endif -#if SEND_SONY - case SONY: sendSony(data, nbits); break; -#endif -#if SEND_RC5 - case RC5: sendRC5(data, nbits); break; -#endif -#if SEND_RC6 - case RC6: sendRC6(data, nbits); break; -#endif -#if SEND_DISH - case DISH: sendDISH(data, nbits); break; -#endif -#if SEND_JVC - case JVC: sendJVC(data, nbits); break; -#endif -#if SEND_SAMSUNG - case SAMSUNG: sendSAMSUNG(data, nbits); break; -#endif -#if SEND_LG - case LG: sendLG(data, nbits); break; -#endif -#if SEND_WHYNTER - case WHYNTER: sendWhynter(data, nbits); break; -#endif -#if SEND_COOLIX - case COOLIX: sendCOOLIX(data, nbits); break; -#endif -#if SEND_DENON - case DENON: sendDenon(data, nbits); break; -#endif -#if SEND_SHERWOOD - case SHERWOOD: sendSherwood(data, nbits); break; -#endif -#if SEND_RCMM - case RCMM: sendRCMM(data, nbits); break; -#endif -#if SEND_MITSUBISHI - case MITSUBISHI: sendMitsubishi(data, nbits); break; -#endif -#if SEND_SHARP - case SHARP: sendSharpRaw(data, nbits); break; -#endif -#if SEND_AIWA_RC_T501 - case AIWA_RC_T501: sendAiwaRCT501(data, nbits); break; -#endif - } -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRsend.h b/lib/IRremoteESP8266-2.2.1.02/src/IRsend.h deleted file mode 100644 index 87c1fdd9a..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRsend.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2015 Mark Szabo -// Copyright 2017 David Conran -#ifndef IRSEND_H_ -#define IRSEND_H_ - -#define __STDC_LIMIT_MACROS -#include -#include "IRremoteESP8266.h" - -// Originally from https://github.com/shirriff/Arduino-IRremote/ -// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for -// sending IR code on ESP8266 - -#if TEST || UNIT_TEST -#define VIRTUAL virtual -#else -#define VIRTUAL -#endif - -// Constants -// Offset (in microseconds) to use in Period time calculations to account for -// code excution time in producing the software PWM signal. -// Value determined in https://github.com/markszabo/IRremoteESP8266/issues/62 -#define PERIOD_OFFSET -3 -#define DUTY_DEFAULT 50 - -// Classes -class IRsend { - public: - explicit IRsend(uint16_t IRsendPin, bool inverted = false); - void begin(); - void enableIROut(uint32_t freq, uint8_t duty = DUTY_DEFAULT); - VIRTUAL uint16_t mark(uint16_t usec); - VIRTUAL void space(uint32_t usec); - void calibrate(uint16_t hz = 38000U); - void sendRaw(uint16_t buf[], uint16_t len, uint16_t hz); - void sendData(uint16_t onemark, uint32_t onespace, uint16_t zeromark, - uint32_t zerospace, uint64_t data, uint16_t nbits, - bool MSBfirst = true); - void send(uint16_t type, uint64_t data, uint16_t nbits); -#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO) - void sendNEC(uint64_t data, uint16_t nbits = NEC_BITS, uint16_t repeat = 0); - uint32_t encodeNEC(uint16_t address, uint16_t command); -#endif -#if SEND_SONY - // sendSony() should typically be called with repeat=2 as Sony devices - // expect the code to be sent at least 3 times. (code + 2 repeats = 3 codes) - // Legacy use of this procedure was to only send a single code so call it with - // repeat=0 for backward compatibility. As of v2.0 it defaults to sending - // a Sony command that will be accepted be a device. - void sendSony(uint64_t data, uint16_t nbits = SONY_20_BITS, - uint16_t repeat = SONY_MIN_REPEAT); - uint32_t encodeSony(uint16_t nbits, uint16_t command, uint16_t address, - uint16_t extended = 0); -#endif -#if SEND_SHERWOOD - void sendSherwood(uint64_t data, uint16_t nbits = SHERWOOD_BITS, - uint16_t repeat = SHERWOOD_MIN_REPEAT); -#endif -#if SEND_SAMSUNG - void sendSAMSUNG(uint64_t data, uint16_t nbits = SAMSUNG_BITS, - uint16_t repeat = 0); - uint32_t encodeSAMSUNG(uint8_t customer, uint8_t command); -#endif -#if SEND_LG - void sendLG(uint64_t data, uint16_t nbits = LG_BITS, uint16_t repeat = 0); - uint32_t encodeLG(uint16_t address, uint16_t command); -#endif -#if (SEND_SHARP || SEND_DENON) - uint32_t encodeSharp(uint16_t address, uint16_t command, - uint16_t expansion = 1, uint16_t check = 0, - bool MSBfirst = false); - void sendSharp(uint16_t address, uint16_t command, - uint16_t nbits = SHARP_BITS, uint16_t repeat = 0); - void sendSharpRaw(uint64_t data, uint16_t nbits = SHARP_BITS, - uint16_t repeat = 0); -#endif -#if SEND_JVC - void sendJVC(uint64_t data, uint16_t nbits = JVC_BITS, uint16_t repeat = 0); - uint16_t encodeJVC(uint8_t address, uint8_t command); -#endif -#if SEND_DENON - void sendDenon(uint64_t data, uint16_t nbits = DENON_BITS, - uint16_t repeat = 0); -#endif -#if SEND_SANYO - uint64_t encodeSanyoLC7461(uint16_t address, uint8_t command); - void sendSanyoLC7461(uint64_t data, uint16_t nbits = SANYO_LC7461_BITS, - uint16_t repeat = 0); -#endif -#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) - // Legacy use of this procedure was only to send a single code - // so use repeat=0 for backward compatibility. - void sendDISH(uint64_t data, uint16_t nbits = DISH_BITS, - uint16_t repeat = DISH_MIN_REPEAT); -#endif -#if (SEND_PANASONIC || SEND_DENON) - void sendPanasonic64(uint64_t data, uint16_t nbits = PANASONIC_BITS, - uint16_t repeat = 0); - void sendPanasonic(uint16_t address, uint32_t data, - uint16_t nbits = PANASONIC_BITS, uint16_t repeat = 0); - uint64_t encodePanasonic(uint16_t manufacturer, uint8_t device, - uint8_t subdevice, uint8_t function); -#endif -#if SEND_RC5 - void sendRC5(uint64_t data, uint16_t nbits = RC5X_BITS, uint16_t repeat = 0); - uint16_t encodeRC5(uint8_t address, uint8_t command, - bool key_released = false); - uint16_t encodeRC5X(uint8_t address, uint8_t command, - bool key_released = false); - uint64_t toggleRC5(uint64_t data); -#endif -#if SEND_RC6 - void sendRC6(uint64_t data, uint16_t nbits = RC6_MODE0_BITS, - uint16_t repeat = 0); - uint64_t encodeRC6(uint32_t address, uint8_t command, - uint16_t mode = RC6_MODE0_BITS); - uint64_t toggleRC6(uint64_t data, uint16_t nbits = RC6_MODE0_BITS); -#endif -#if SEND_RCMM - void sendRCMM(uint64_t data, uint16_t nbits = RCMM_BITS, uint16_t repeat = 0); -#endif -#if SEND_COOLIX - void sendCOOLIX(uint64_t data, uint16_t nbits = COOLIX_BITS, - uint16_t repeat = 0); -#endif -#if SEND_WHYNTER - void sendWhynter(uint64_t data, uint16_t nbits = WHYNTER_BITS, - uint16_t repeat = 0); -#endif -#if SEND_MITSUBISHI - void sendMitsubishi(uint64_t data, uint16_t nbits = MITSUBISHI_BITS, - uint16_t repeat = MITSUBISHI_MIN_REPEAT); -#endif -#if SEND_MITSUBISHI_AC - void sendMitsubishiAC(unsigned char data[], - uint16_t nbytes = MITSUBISHI_AC_STATE_LENGTH, - uint16_t repeat = MITSUBISHI_AC_MIN_REPEAT); -#endif -#if SEND_FUJITSU_AC - void sendFujitsuAC(unsigned char data[], - uint16_t nbytes, - uint16_t repeat = FUJITSU_AC_MIN_REPEAT); -#endif -#if SEND_GLOBALCACHE - void sendGC(uint16_t buf[], uint16_t len); -#endif -#if SEND_KELVINATOR - void sendKelvinator(unsigned char data[], - uint16_t nbytes = KELVINATOR_STATE_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_DAIKIN - void sendDaikin(unsigned char data[], - uint16_t nbytes = DAIKIN_COMMAND_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_AIWA_RC_T501 - void sendAiwaRCT501(uint64_t data, uint16_t nbits = AIWA_RC_T501_BITS, - uint16_t repeat = AIWA_RC_T501_MIN_REPEAT); -#endif -#if SEND_GREE - void sendGree(uint64_t data, uint16_t nbits = GREE_BITS, uint16_t repeat = 0); - void sendGree(uint8_t data[], uint16_t nbytes = GREE_STATE_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_PRONTO - void sendPronto(uint16_t data[], uint16_t len, uint16_t repeat = 0); -#endif -#if SEND_ARGO - void sendArgo(unsigned char data[], - uint16_t nbytes = ARGO_COMMAND_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_TROTEC - void sendTrotec(unsigned char data[], - uint16_t nbytes = TROTEC_COMMAND_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_NIKAI - void sendNikai(uint64_t data, uint16_t nbits = NIKAI_BITS, - uint16_t repeat = 0); -#endif - - protected: -#ifdef UNIT_TEST -#ifndef HIGH -#define HIGH 0x1 -#endif -#ifndef LOW -#define LOW 0x0 -#endif -#endif // UNIT_TEST - uint8_t outputOn; - uint8_t outputOff; - - private: - uint16_t onTimePeriod; - uint16_t offTimePeriod; - uint16_t IRpin; - int8_t periodOffset; - void ledOff(); - uint32_t calcUSecPeriod(uint32_t hz, bool use_offset = true); -}; - -#endif // IRSEND_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp b/lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp deleted file mode 100644 index 22b4bb3b7..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRutils.h" -#ifndef UNIT_TEST -#include -#endif - -#define __STDC_LIMIT_MACROS -#include -#include -#ifndef ARDUINO -#include -#endif -#include "IRrecv.h" - -// Reverse the order of the requested least significant nr. of bits. -// Args: -// input: Bit pattern/integer to reverse. -// nbits: Nr. of bits to reverse. -// Returns: -// The reversed bit pattern. -uint64_t reverseBits(uint64_t input, uint16_t nbits) { - if (nbits <= 1) - return input; // Reversing <= 1 bits makes no change at all. - // Cap the nr. of bits to rotate to the max nr. of bits in the input. - nbits = std::min(nbits, (uint16_t) (sizeof(input) * 8)); - uint64_t output = 0; - for (uint16_t i = 0; i < nbits; i++) { - output <<= 1; - output |= (input & 1); - input >>= 1; - } - // Merge any remaining unreversed bits back to the top of the reversed bits. - return (input << nbits) | output; -} - -// Convert a uint64_t (unsigned long long) to a string. -// Arduino String/toInt/Serial.print() can't handle printing 64 bit values. -// -// Args: -// input: The value to print -// base: The output base. -// Returns: -// A string representation of the integer. -// Note: Based on Arduino's Print::printNumber() -#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. -String uint64ToString(uint64_t input, uint8_t base) { - String result = ""; -#else -std::string uint64ToString(uint64_t input, uint8_t base) { - std::string result = ""; -#endif - // prevent issues if called with base <= 1 - if (base < 2) base = 10; - // Check we have a base that we can actually print. - // i.e. [0-9A-Z] == 36 - if (base > 36) base = 10; - - do { - char c = input % base; - input /= base; - - if (c < 10) - c +='0'; - else - c += 'A' - 10; - result = c + result; - } while (input); - return result; -} - -#ifdef ARDUINO -// Print a uint64_t/unsigned long long to the Serial port -// Serial.print() can't handle printing long longs. (uint64_t) -// -// Args: -// input: The value to print -// base: The output base. -void serialPrintUint64(uint64_t input, uint8_t base) { - Serial.print(uint64ToString(input, base)); -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRutils.h b/lib/IRremoteESP8266-2.2.1.02/src/IRutils.h deleted file mode 100644 index eb3f1d8ee..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRutils.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef IRUTILS_H_ -#define IRUTILS_H_ - -// Copyright 2017 David Conran - -#ifndef UNIT_TEST -#include -#endif -#define __STDC_LIMIT_MACROS -#include -#ifndef ARDUINO -#include -#endif - -uint64_t reverseBits(uint64_t input, uint16_t nbits); -#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. -String uint64ToString(uint64_t input, uint8_t base = 10); -#else -std::string uint64ToString(uint64_t input, uint8_t base = 10); -#endif -void serialPrintUint64(uint64_t input, uint8_t base = 10); - -#endif // IRUTILS_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp deleted file mode 100644 index f664d6ad7..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright bakrus -// Copyright 2017 David Conran - -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// CCCCC OOOOO OOOOO LL IIIII XX XX -// CC C OO OO OO OO LL III XX XX -// CC OO OO OO OO LL III XXXX -// CC C OO OO OO OO LL III XX XX -// CCCCC OOOO0 OOOO0 LLLLLLL IIIII XX XX - -// Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit - -// Constants -// Pulse parms are *50-100 for the Mark and *50+100 for the space -// First MARK is the one after the long gap -// pulse parameters in usec -#define COOLIX_TICK 560U // Approximately 21 cycles at 38kHz -#define COOLIX_BIT_MARK_TICKS 1U -#define COOLIX_BIT_MARK (COOLIX_BIT_MARK_TICKS * COOLIX_TICK) -#define COOLIX_ONE_SPACE_TICKS 3U -#define COOLIX_ONE_SPACE (COOLIX_ONE_SPACE_TICKS * COOLIX_TICK) -#define COOLIX_ZERO_SPACE_TICKS 1U -#define COOLIX_ZERO_SPACE (COOLIX_ZERO_SPACE_TICKS * COOLIX_TICK) -#define COOLIX_HDR_MARK_TICKS 8U -#define COOLIX_HDR_MARK (COOLIX_HDR_MARK_TICKS * COOLIX_TICK) -#define COOLIX_HDR_SPACE_TICKS 8U -#define COOLIX_HDR_SPACE (COOLIX_HDR_SPACE_TICKS * COOLIX_TICK) -#define COOLIX_MIN_GAP_TICKS (COOLIX_HDR_MARK_TICKS + \ - COOLIX_ZERO_SPACE_TICKS) -#define COOLIX_MIN_GAP (COOLIX_MIN_GAP_TICKS * COOLIX_TICK) - -#if SEND_COOLIX -// Send a Coolix message -// -// Args: -// data: Contents of the message to be sent. -// nbits: Nr. of bits of data to be sent. Typically COOLIX_BITS. -// repeat: Nr. of additional times the message is to be sent. -// -// Status: BETA / Probably works. -// -// Ref: -// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_COOLIX.cpp -// TODO(anyone): Verify repeat functionality against a real unit. -void IRsend::sendCOOLIX(uint64_t data, uint16_t nbits, uint16_t repeat) { - if (nbits % 8 != 0) - return; // nbits is required to be a multiple of 8. - - // Set IR carrier frequency - enableIROut(38); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header - mark(COOLIX_HDR_MARK); - space(COOLIX_HDR_SPACE); - - // Data - // Break data into byte segments, starting at the Most Significant - // Byte. Each byte then being sent normal, then followed inverted. - for (uint16_t i = 8; i <= nbits; i += 8) { - // Grab a bytes worth of data. - uint8_t segment = (data >> (nbits - i)) & 0xFF; - // Normal - sendData(COOLIX_BIT_MARK, COOLIX_ONE_SPACE, - COOLIX_BIT_MARK, COOLIX_ZERO_SPACE, - segment, 8, true); - // Inverted. - sendData(COOLIX_BIT_MARK, COOLIX_ONE_SPACE, - COOLIX_BIT_MARK, COOLIX_ZERO_SPACE, - segment ^ 0xFF, 8, true); - } - - // Footer - mark(COOLIX_BIT_MARK); - space(COOLIX_MIN_GAP); // Pause before repeating - } -} -#endif - -#if DECODE_COOLIX -// Decode the supplied Coolix message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: The number of data bits to expect. Typically COOLIX_BITS. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / Probably working. -bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t nbits, - bool strict) { - // The protocol sends the data normal + inverted, alternating on - // each byte. Hence twice the number of expected data bits. - if (results->rawlen < 2 * 2 * nbits + HEADER + FOOTER - 1) - return false; // Can't possibly be a valid COOLIX message. - if (strict && nbits != COOLIX_BITS) - return false; // Not strictly an COOLIX message. - if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. - return false; - - uint64_t data = 0; - uint64_t inverted = 0; - uint16_t offset = OFFSET_START; - - if (nbits > sizeof(data) * 8) - return false; // We can't possibly capture a Coolix packet that big. - - // Header - if (!matchMark(results->rawbuf[offset], COOLIX_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / COOLIX_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], COOLIX_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - COOLIX_HDR_SPACE_TICKS; - - // Data - // Twice as many bits as there are normal plus inverted bits. - for (uint16_t i = 0; i < nbits * 2; i++, offset++) { - bool flip = (i / 8) % 2; - if (!matchMark(results->rawbuf[offset++], COOLIX_BIT_MARK_TICKS * m_tick)) - return false; - if (matchSpace(results->rawbuf[offset], COOLIX_ONE_SPACE_TICKS * s_tick)) { - if (flip) - inverted = (inverted << 1) | 1; - else - data = (data << 1) | 1; - } else if (matchSpace(results->rawbuf[offset], - COOLIX_ZERO_SPACE_TICKS * s_tick)) { - if (flip) - inverted <<= 1; - else - data <<= 1; - } else { - return false; - } - } - - // Footer - if (!matchMark(results->rawbuf[offset++], COOLIX_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], COOLIX_MIN_GAP_TICKS * s_tick)) - return false; - - // Compliance - uint64_t orig = data; // Save a copy of the data. - if (strict) { - for (uint16_t i = 0; i < nbits; i += 8, data >>= 8, inverted >>= 8) - if ((data & 0xFF) != ((inverted & 0xFF) ^ 0xFF)) - return false; - } - - // Success - results->decode_type = COOLIX; - results->bits = nbits; - results->value = orig; - results->address = 0; - results->command = 0; - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp deleted file mode 100644 index f57b67608..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* -An Arduino sketch to emulate IR Daikin ARC433** remote control unit -Read more at: -http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/ - -Copyright 2016 sillyfrog -*/ - -#include "ir_Daikin.h" -#include -#include "IRremoteESP8266.h" -#include "IRutils.h" - -// DDDDD AAA IIIII KK KK IIIII NN NN -// DD DD AAAAA III KK KK III NNN NN -// DD DD AA AA III KKKK III NN N NN -// DD DD AAAAAAA III KK KK III NN NNN -// DDDDDD AA AA IIIII KK KK IIIII NN NN - -// Constants -// Ref: -// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -#define DAIKIN_HDR_MARK 3650U // DAIKIN_ZERO_MARK * 8 -#define DAIKIN_HDR_SPACE 1623U // DAIKIN_ZERO_MARK * 4 -#define DAIKIN_ONE_SPACE 1280U -#define DAIKIN_ONE_MARK 428U -#define DAIKIN_ZERO_MARK 428U -#define DAIKIN_ZERO_SPACE 428U -#define DAIKIN_GAP 29000U - -#if SEND_DAIKIN -// Send a Daikin A/C message. -// -// Args: -// data: An array of DAIKIN_COMMAND_LENGTH bytes containing the IR command. -// -// Status: STABLE -// -// Ref: -// IRDaikinESP.cpp -// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -void IRsend::sendDaikin(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < DAIKIN_COMMAND_LENGTH) - return; // Not enough bytes to send a proper message. - // Set IR carrier frequency - enableIROut(38); - for (uint16_t r = 0; r <= repeat; r++) { - // Header #1 - mark(DAIKIN_HDR_MARK); - space(DAIKIN_HDR_SPACE); - // Data #1 - for (uint16_t i = 0; i < 8 && i < nbytes; i++) - sendData(DAIKIN_ONE_MARK, DAIKIN_ONE_SPACE, DAIKIN_ZERO_MARK, - DAIKIN_ZERO_SPACE, data[i], 8, false); - // Footer #1 - mark(DAIKIN_ONE_MARK); - space(DAIKIN_ZERO_SPACE + DAIKIN_GAP); - - // Header #2 - mark(DAIKIN_HDR_MARK); - space(DAIKIN_HDR_SPACE); - // Data #2 - for (uint16_t i = 8; i < nbytes; i++) - sendData(DAIKIN_ONE_MARK, DAIKIN_ONE_SPACE, DAIKIN_ZERO_MARK, - DAIKIN_ZERO_SPACE, data[i], 8, false); - // Footer #2 - mark(DAIKIN_ONE_MARK); - space(DAIKIN_ZERO_SPACE + DAIKIN_GAP); - } -} - -IRDaikinESP::IRDaikinESP(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -void IRDaikinESP::begin() { - _irsend.begin(); -} - -void IRDaikinESP::send() { - _irsend.sendDaikin(daikin); -} - -void IRDaikinESP::checksum() { - uint8_t sum = 0; - uint8_t i; - - for (i = 0; i <= 6; i++) - sum += daikin[i]; - - daikin[7] = sum & 0xFF; - sum = 0; - for (i = 8; i <= 25; i++) - sum += daikin[i]; - daikin[26] = sum & 0xFF; -} - - -void IRDaikinESP::stateReset() { - for (uint8_t i = 4; i < DAIKIN_COMMAND_LENGTH; i++) - daikin[i] = 0x0; - - daikin[0] = 0x11; - daikin[1] = 0xDA; - daikin[2] = 0x27; - daikin[3] = 0xF0; - daikin[7] = 0x20; - daikin[8] = 0x11; - daikin[9] = 0xDA; - daikin[10] = 0x27; - daikin[13] = 0x41; - daikin[14] = 0x1E; - daikin[16] = 0xB0; - daikin[23] = 0xC0; - daikin[26] = 0xE3; - checksum(); -} - -uint8_t* IRDaikinESP::getRaw() { - checksum(); // Ensure correct settings before sending. - return daikin; -} - -void IRDaikinESP::on() { - // state = ON; - daikin[13] |= 0x01; - checksum(); -} - -void IRDaikinESP::off() { - // state = OFF; - daikin[13] &= 0xFE; - checksum(); -} - -void IRDaikinESP::setPower(bool state) { - if (state) - on(); - else - off(); -} - -uint8_t IRDaikinESP::getPower() { - return daikin[13] & 0x01; -} - -// DAIKIN_SILENT or DAIKIN_POWERFUL -void IRDaikinESP::setAux(uint8_t aux) { - daikin[21] = aux; - checksum(); -} - -uint8_t IRDaikinESP::getAux() { - return daikin[21]; -} - -void IRDaikinESP::setQuiet(bool state) { - if (state) - setAux(DAIKIN_SILENT); - else - setAux(0x0); -} - -bool IRDaikinESP::getQuiet() { - return (getAux() == DAIKIN_SILENT); -} - -void IRDaikinESP::setPowerful(bool state) { - if (state) - setAux(DAIKIN_POWERFUL); - else - setAux(0x0); -} - -bool IRDaikinESP::getPowerful() { - return (getAux() == DAIKIN_POWERFUL); -} - -// Set the temp in deg C -void IRDaikinESP::setTemp(uint8_t temp) { - if (temp < DAIKIN_MIN_TEMP) - temp = DAIKIN_MIN_TEMP; - else if (temp > DAIKIN_MAX_TEMP) - temp = DAIKIN_MAX_TEMP; - daikin[14] = temp * 2; - checksum(); -} - -uint8_t IRDaikinESP::getTemp() { - return daikin[14] / 2; -} - -// Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed -void IRDaikinESP::setFan(uint8_t fan) { - // Set the fan speed bits, leave low 4 bits alone - uint8_t fanset; - daikin[16] &= 0x0F; - fan = std::min(fan, DAIKIN_FAN_MAX); - if (fan == DAIKIN_FAN_AUTO) - fanset = 0xA0; - else - fanset = 0x20 + (0x10 * fan); - daikin[16] |= fanset; - checksum(); -} - -uint8_t IRDaikinESP::getFan() { - uint8_t fan = daikin[16] >> 4; - fan -= 2; - if (fan > DAIKIN_FAN_MAX) - fan = DAIKIN_FAN_AUTO; - return fan; -} - -uint8_t IRDaikinESP::getMode() { - /* - DAIKIN_COOL - DAIKIN_HEAT - DAIKIN_FAN - DAIKIN_AUTO - DAIKIN_DRY - */ - return daikin[13] >> 4; -} - -void IRDaikinESP::setMode(uint8_t mode) { - switch (mode) { - case DAIKIN_COOL: - case DAIKIN_HEAT: - case DAIKIN_FAN: - case DAIKIN_DRY: - break; - default: - mode = DAIKIN_AUTO; - } - daikin[13] = (mode << 4) | getPower(); - checksum(); -} - -void IRDaikinESP::setSwingVertical(bool state) { - if (state) - daikin[16] |= 0x0F; - else - daikin[16] &= 0xF0; - checksum(); -} - -bool IRDaikinESP::getSwingVertical() { - return daikin[16] & 0x01; -} - -void IRDaikinESP::setSwingHorizontal(bool state) { - if (state) - daikin[17] |= 0x0F; - else - daikin[17] &= 0xF0; - checksum(); -} - -bool IRDaikinESP::getSwingHorizontal() { - return daikin[17] & 0x01; -} -#endif // SEND_DAIKIN - -#if DECODE_DAIKIN -// TODO(crankyoldgit): NOT WORKING. This needs to be finished. -// Decode the supplied Daikin A/C message. (NOT WORKING - DO NOT USE) -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. Typically SAMSUNG_BITS. -// strict: Flag to indicate if we strictly adhere to the specification. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: UNFINISHED / Completely not working, not even vaguely. -// -// Ref: -// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -bool IRrecv::decodeDaikin(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER) - return false; - - // Compliance - if (strict && nbits != DAIKIN_BITS) - return false; - - uint32_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset++], DAIKIN_HDR_MARK)) - return false; - if (!matchSpace(results->rawbuf[offset++], DAIKIN_HDR_SPACE)) - return false; - - // Data (#1) - for (uint8_t i = 0; i < sizeof(data) * 8; i++, offset++) { - if (!matchMark(results->rawbuf[offset++], DAIKIN_ONE_MARK)) - return false; - if (matchSpace(results->rawbuf[offset], DAIKIN_ONE_SPACE)) - data = (data << 1) | 1; // 1 - else if (matchSpace(results->rawbuf[offset], DAIKIN_ZERO_SPACE)) - data <<= 1; // 0 - else - return false; - } - - uint32_t number = data; // some number... - uint32_t reversed = reverseBits(number, sizeof(number) * 8) - - DPRINT("Code "); - DPRINTLN(reversed, HEX); - - // Data (#2) - for (uint8_t i = 0; i < sizeof(data) * 8; i++, offset++) { - if (!matchMark(results->rawbuf[offset++], DAIKIN_ONE_MARK)) - return false; - if (matchSpace(results->rawbuf[offset], DAIKIN_ONE_SPACE)) - data = (data << 1) | 1; // 1 - else if (matchSpace(results->rawbuf[offset], DAIKIN_ZERO_SPACE)) - data <<= 1; // 0 - else - return false; - } - - number = data; // some number... - reversed = reverseBits(number, sizeof(number) * 8) - - DPRINT("Code2 "); - DPRINTLN(reversed, HEX); - - if (!matchSpace(results->rawbuf[offset++], DAIKIN_GAP)) { - DPRINTLN("no gap"); - return false; - } - - // Success - results->bits = DAIKIN_BITS; - results->value = reversed; - results->decode_type = DAIKIN; - results->address = 0; - results->command = 0; - return true; -} -#endif // DECODE_DAIKIN diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h deleted file mode 100644 index 7172a5e27..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright 2016 sillyfrog */ -#ifndef IR_DAIKIN_H_ -#define IR_DAIKIN_H_ - -#include "IRremoteESP8266.h" -#include "IRsend.h" - -// DDDDD AAA IIIII KK KK IIIII NN NN -// DD DD AAAAA III KK KK III NNN NN -// DD DD AA AA III KKKK III NN N NN -// DD DD AAAAAAA III KK KK III NN NNN -// DDDDDD AA AA IIIII KK KK IIIII NN NN - -/* - Daikin AC map - byte 7= checksum of the first part (and last byte before a 29ms pause) - byte 13=mode - b7 = 0 - b6+b5+b4 = Mode - Modes: b6+b5+b4 - 011 = Cool - 100 = Heat (temp 23) - 110 = FAN (temp not shown, but 25) - 000 = Fully Automatic (temp 25) - 010 = DRY (temp 0xc0 = 96 degrees c) - b3 = 0 - b2 = OFF timer set - b1 = ON timer set - b0 = Air Conditioner ON - byte 14=temp*2 (Temp should be between 18 - 32) - byte 16=Fan - FAN control - b7+b6+b5+b4 = Fan speed - Fan: b7+b6+b5+b4 - 0×30 = 1 bar - 0×40 = 2 bar - 0×50 = 3 bar - 0×60 = 4 bar - 0×70 = 5 bar - 0xa0 = Auto - 0xb0 = Not auto, moon + tree - b3+b2+b1+b0 = Swing control up/down - Swing control up/down: - 0000 = Swing up/down off - 1111 = Swing up/down on - byte 17 - Swing control left/right: - 0000 = Swing left/right off - 1111 = Swing left/right on - byte 21=Aux -> Powerful (bit 1), Silent (bit 5) - byte 24=Aux2 -> Intelligent eye on (bit 7) - byte 26= checksum of the second part -*/ - -// Constants -#define DAIKIN_COOL 0b011 -#define DAIKIN_HEAT 0b100 -#define DAIKIN_FAN 0b110 -#define DAIKIN_AUTO 0b000 -#define DAIKIN_DRY 0b010 -#define DAIKIN_POWERFUL 0b00000010 -#define DAIKIN_SILENT 0b00100000 -#define DAIKIN_MIN_TEMP 18U // Celsius -#define DAIKIN_MAX_TEMP 32U // Celsius -#define DAIKIN_FAN_AUTO (uint8_t) 0U -#define DAIKIN_FAN_MIN (uint8_t) 1U -#define DAIKIN_FAN_MAX (uint8_t) 5U - -#if SEND_DAIKIN -class IRDaikinESP { - public: - explicit IRDaikinESP(uint16_t pin); - - void send(); - void begin(); - void on(); - void off(); - void setPower(bool state); - uint8_t getPower(); - void setAux(uint8_t aux); - uint8_t getAux(); - void setTemp(uint8_t temp); - uint8_t getTemp(); - void setFan(uint8_t fan); - uint8_t getFan(); - uint8_t getMode(); - void setMode(uint8_t mode); - void setSwingVertical(bool state); - bool getSwingVertical(); - void setSwingHorizontal(bool state); - bool getSwingHorizontal(); - bool getQuiet(); - void setQuiet(bool state); - bool getPowerful(); - void setPowerful(bool state); - uint8_t* getRaw(); - - private: - // # of bytes per command - uint8_t daikin[DAIKIN_COMMAND_LENGTH]; - void stateReset(); - void checksum(); - IRsend _irsend; -}; -#endif - -#endif // IR_DAIKIN_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp deleted file mode 100644 index adf753c0c..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright 2017 Jonny Graham -#include "ir_Fujitsu.h" -#include -#include "IRsend.h" - - -// Fujitsu A/C support added by Jonny Graham - - -// Fujitsu A/C -// Ref: -// These values are based on averages of measurements -#define FUJITSU_AC_HDR_MARK 3224U -#define FUJITSU_AC_HDR_SPACE 1574U -#define FUJITSU_AC_BIT_MARK 448U -#define FUJITSU_AC_ONE_SPACE 1182U -#define FUJITSU_AC_ZERO_SPACE 367U -#define FUJITSU_AC_TRL_MARK 448U -#define FUJITSU_AC_TRL_SPACE 8100U - -#if SEND_FUJITSU_AC -// Send a Fujitsu A/C message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (typically either -// FUJITSU_AC_STATE_LENGTH or FUJITSU_AC_STATE_LENGTH_SHORT) -// repeat: Nr. of times the message is to be repeated. -// (Default = FUJITSU_AC_MIN_REPEAT). -// -// Status: BETA / Appears to be working. -// -void IRsend::sendFujitsuAC(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - // Set IR carrier frequency - enableIROut(38); - for (uint16_t r = 0; r <= repeat; ++r) { - // Header - mark(FUJITSU_AC_HDR_MARK); - space(FUJITSU_AC_HDR_SPACE); - // Data - for (uint16_t i = 0; i < nbytes; i++) - sendData(FUJITSU_AC_BIT_MARK, FUJITSU_AC_ONE_SPACE, - FUJITSU_AC_BIT_MARK, FUJITSU_AC_ZERO_SPACE, - data[i], 8, false); - // Footer - mark(FUJITSU_AC_TRL_MARK); - space(FUJITSU_AC_TRL_SPACE); - } -} - -// Code to emulate Fujitsu A/C IR remote control unit. - -// Warning: Consider this very alpha code. Seems to work, but not validated. -// -// Equipment it seems compatible with: -// * Fujitsu ASYG30LFCA with remote AR-RAH2E -// * -// Initialise the object. -IRFujitsuAC::IRFujitsuAC(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -// Reset the state of the remote to a known good state/sequence. -void IRFujitsuAC::stateReset() { - _temp = 24; - _fanSpeed = FUJITSU_AC_FAN_HIGH; - _mode = FUJITSU_AC_MODE_COOL; - _swingMode = FUJITSU_AC_SWING_BOTH; - _cmd = FUJITSU_AC_CMD_TURN_ON; -} - -// Configure the pin for output. -void IRFujitsuAC::begin() { - _irsend.begin(); -} - -// Send the current desired state to the IR LED. -void IRFujitsuAC::send() { - getRaw(); - uint8_t len = getCommandLength(); - _irsend.sendFujitsuAC(remote_state, len); -} - -uint8_t IRFujitsuAC::getCommandLength() { - if (remote_state[5] != 0xFE) - return FUJITSU_AC_STATE_LENGTH_SHORT; - else - return FUJITSU_AC_STATE_LENGTH; -} - -// Return a pointer to the internal state date of the remote. -uint8_t* IRFujitsuAC::getRaw() { - remote_state[0] = 0x14; - remote_state[1] = 0x63; - remote_state[2] = 0x00; - remote_state[3] = 0x10; - remote_state[4] = 0x10; - bool fullCmd = false; - switch (_cmd) { - case FUJITSU_AC_CMD_TURN_OFF: - remote_state[5] = 0x02; - break; - case FUJITSU_AC_CMD_STEP_HORIZ: - remote_state[5] = 0x79; - break; - case FUJITSU_AC_CMD_STEP_VERT: - remote_state[5] = 0x6C; - break; - default: - remote_state[5] = 0xFE; - fullCmd = true; - break; - } - if (fullCmd) { - remote_state[6] = 0x09; - remote_state[7] = 0x30; - uint8_t tempByte = _temp - FUJITSU_AC_MIN_TEMP; - remote_state[8] = (_cmd == FUJITSU_AC_CMD_TURN_ON) | (tempByte << 4); - remote_state[9] = _mode | 0 << 4; // timer off - remote_state[10] = _fanSpeed | _swingMode << 4; - remote_state[11] = 0; // timerOff values - remote_state[12] = 0; // timerOff/on values - remote_state[13] = 0; // timerOn values - remote_state[14] = 0x20; - // Checksum is the sum of the 8th to 16th bytes (ie remote_state[7] - // thru remote_state[15]). - // The checksum itself is stored in the 16th byte (ie remote_state[15]). - // So we sum bytes 8th-15th... - uint8_t checksum = 0; - for (uint8_t i = 7 ; i < 15; ++i) { - checksum += remote_state[i]; - } - // and then do 0 - sum and store it in 16th. - remote_state[15] = 0 - checksum; - } else { - // For the short codes, byte 7 is the inverse of byte 6 - remote_state[6] = ~remote_state[5]; - for (uint8_t i = 7; i < FUJITSU_AC_STATE_LENGTH; ++i) { - remote_state[i] = 0; - } - } - return remote_state; -} - -// Set the requested power state of the A/C to off. -void IRFujitsuAC::off() { - _cmd = FUJITSU_AC_CMD_TURN_OFF; -} - -void IRFujitsuAC::stepHoriz() { - _cmd = FUJITSU_AC_CMD_STEP_HORIZ; -} - -void IRFujitsuAC::stepVert() { - _cmd = FUJITSU_AC_CMD_STEP_VERT; -} - -// Set the requested command of the A/C. -void IRFujitsuAC::setCmd(uint8_t cmd) { - switch (cmd) { - case FUJITSU_AC_CMD_TURN_OFF: - case FUJITSU_AC_CMD_TURN_ON: - case FUJITSU_AC_CMD_STAY_ON: - case FUJITSU_AC_CMD_STEP_HORIZ: - case FUJITSU_AC_CMD_STEP_VERT: - break; - default: - cmd = FUJITSU_AC_CMD_STAY_ON; - break; - } - _cmd = cmd; -} - -uint8_t IRFujitsuAC::getCmd() { - return _cmd; -} - -// Set the temp. in deg C -void IRFujitsuAC::setTemp(uint8_t temp) { - temp = std::max((uint8_t) FUJITSU_AC_MIN_TEMP, temp); - temp = std::min((uint8_t) FUJITSU_AC_MAX_TEMP, temp); - _temp = temp; -} - -uint8_t IRFujitsuAC::getTemp() { - return _temp; -} - -// Set the speed of the fan -void IRFujitsuAC::setFanSpeed(uint8_t fanSpeed) { - if (fanSpeed > FUJITSU_AC_FAN_QUIET) - fanSpeed = FUJITSU_AC_FAN_HIGH; // Set the fan to maximum if out of range. - _fanSpeed = fanSpeed; -} -uint8_t IRFujitsuAC::getFanSpeed() { - return _fanSpeed; -} - -// Set the requested climate operation mode of the a/c unit. -void IRFujitsuAC::setMode(uint8_t mode) { - if (mode > FUJITSU_AC_MODE_HEAT) - mode = FUJITSU_AC_MODE_HEAT; // Set the mode to maximum if out of range. - _mode = mode; -} - -uint8_t IRFujitsuAC::getMode() { - return _mode; -} -// Set the requested swing operation mode of the a/c unit. -void IRFujitsuAC::setSwing(uint8_t swingMode) { - if (swingMode > FUJITSU_AC_SWING_BOTH) - swingMode = FUJITSU_AC_SWING_BOTH; // Set the mode to max if out of range - _swingMode = swingMode; -} - -uint8_t IRFujitsuAC::getSwing() { - return _swingMode; -} - -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h deleted file mode 100644 index 451a5b203..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2017 Jonny Graham -#ifndef IR_FUJITSU_H_ -#define IR_FUJITSU_H_ - -#define __STDC_LIMIT_MACROS -#include -#include "IRremoteESP8266.h" -#include "IRsend.h" - - -// FUJITSU A/C support added by Jonny Graham - -// Constants - -#define FUJITSU_AC_MODE_AUTO 0x00U -#define FUJITSU_AC_MODE_COOL 0x01U -#define FUJITSU_AC_MODE_DRY 0x02U -#define FUJITSU_AC_MODE_FAN 0x03U -#define FUJITSU_AC_MODE_HEAT 0x04U - -#define FUJITSU_AC_CMD_STAY_ON 0x00U -#define FUJITSU_AC_CMD_TURN_ON 0x01U -#define FUJITSU_AC_CMD_TURN_OFF 0x02U -#define FUJITSU_AC_CMD_STEP_HORIZ 0x79U -#define FUJITSU_AC_CMD_STEP_VERT 0x6CU - -#define FUJITSU_AC_FAN_AUTO 0x00U -#define FUJITSU_AC_FAN_HIGH 0x01U -#define FUJITSU_AC_FAN_MED 0x02U -#define FUJITSU_AC_FAN_LOW 0x03U -#define FUJITSU_AC_FAN_QUIET 0x04U - -#define FUJITSU_AC_MIN_TEMP 16U // 16C -#define FUJITSU_AC_MAX_TEMP 30U // 30C - -#define FUJITSU_AC_SWING_OFF 0x00U -#define FUJITSU_AC_SWING_VERT 0x01U -#define FUJITSU_AC_SWING_HORIZ 0x02U -#define FUJITSU_AC_SWING_BOTH 0x03U - -#define FUJITSU_AC_STATE_LENGTH 16 -#define FUJITSU_AC_STATE_LENGTH_SHORT 7 - -#if SEND_FUJITSU_AC -class IRFujitsuAC { - public: - explicit IRFujitsuAC(uint16_t pin); - - void stateReset(); - void send(); - void begin(); - void off(); - void stepHoriz(); - void stepVert(); - void setCmd(uint8_t cmd); - uint8_t getCmd(); - void setTemp(uint8_t temp); - uint8_t getTemp(); - void setFanSpeed(uint8_t fan); - uint8_t getFanSpeed(); - void setMode(uint8_t mode); - uint8_t getMode(); - void setSwing(uint8_t mode); - uint8_t getSwing(); - uint8_t* getRaw(); - - private: - uint8_t remote_state[FUJITSU_AC_STATE_LENGTH]; - uint8_t getCommandLength(); - IRsend _irsend; - uint8_t _temp; - uint8_t _fanSpeed; - uint8_t _mode; - uint8_t _swingMode; - uint8_t _cmd; -}; - -#endif - -#endif // IR_FUJITSU_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp deleted file mode 100644 index d1bc760bf..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2017 Ville Skyttä (scop) -// Copyright 2017 David Conran -// -// Gree protocol compatible heat pump carrying the "Ultimate" brand name. -// - -#include "IRremoteESP8266.h" -#include "IRsend.h" - -// GGGG RRRRRR EEEEEEE EEEEEEE -// GG GG RR RR EE EE -// GG RRRRRR EEEEE EEEEE -// GG GG RR RR EE EE -// GGGGGG RR RR EEEEEEE EEEEEEE - -// Constants -// Ref: https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.h -#define GREE_HDR_MARK 9000U -#define GREE_HDR_SPACE 4000U -#define GREE_BIT_MARK 620U -#define GREE_ONE_SPACE 1600U -#define GREE_ZERO_SPACE 540U -#define GREE_MSG_SPACE 19000U - -#if SEND_GREE -// Send a Gree Heat Pump message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=GREE_STATE_LENGTH) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: ALPHA / Untested. -// -// Ref: -// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp -void IRsend::sendGree(unsigned char data[], uint16_t nbytes, uint16_t repeat) { - if (nbytes < GREE_STATE_LENGTH) - return; // Not enough bytes to send a proper message. - - // Set IR carrier frequency - enableIROut(38); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header #1 - mark(GREE_HDR_MARK); - space(GREE_HDR_SPACE); - - // Data #1 - uint16_t i; - for (i = 0; i < 4 && i < nbytes; i++) - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - data[i], 8, false); - - // Footer #1 (010) - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - 0b010, 3); - - // Header #2 - mark(GREE_BIT_MARK); - space(GREE_MSG_SPACE); - - // Data #2 - for (; i < nbytes; i++) - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - data[i], 8, false); - - // Footer #2 - mark(GREE_BIT_MARK); - space(GREE_MSG_SPACE); - } -} - -// Send a Gree Heat Pump message. -// -// Args: -// data: The raw message to be sent. -// nbits: Nr. of bits of data in the message. (Default is GREE_BITS) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: ALPHA / Untested. -// -// Ref: -// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp -void IRsend::sendGree(uint64_t data, uint16_t nbits, uint16_t repeat) { - if (nbits != GREE_BITS) - return; // Wrong nr. of bits to send a proper message. - // Set IR carrier frequency - enableIROut(38); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header - mark(GREE_HDR_MARK); - space(GREE_HDR_SPACE); - - // Data - for (int16_t i = 8; i <= nbits; i += 8) { - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - (data >> (nbits - i)) & 0xFF, 8, false); - if (i == nbits / 2) { - // Send the mid-message Footer. - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - 0b010, 3); - mark(GREE_BIT_MARK); - space(GREE_MSG_SPACE); - } - } - // Footer - mark(GREE_BIT_MARK); - space(GREE_MSG_SPACE); - } -} -#endif // SEND_GREE diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp deleted file mode 100644 index 257a32e1a..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2016 David Conran -// -// Code to emulate IR Kelvinator YALIF remote control unit, which should control -// at least the following Kelvinator A/C units: -// KSV26CRC, KSV26HRC, KSV35CRC, KSV35HRC, KSV53HRC, KSV62HRC, KSV70CRC, -// KSV70HRC, KSV80HRC. -// -// Note: -// * Unsupported: -// - All Sleep modes. -// - All Timer modes. -// - "I Feel" button & mode. -// - Energy Saving mode. -// - Low Heat mode. -// - Fahrenheit. - -#include "ir_Kelvinator.h" -#include - -// KK KK EEEEEEE LL VV VV IIIII NN NN AAA TTTTTTT OOOOO RRRRRR -// KK KK EE LL VV VV III NNN NN AAAAA TTT OO OO RR RR -// KKKK EEEEE LL VV VV III NN N NN AA AA TTT OO OO RRRRRR -// KK KK EE LL VV VV III NN NNN AAAAAAA TTT OO OO RR RR -// KK KK EEEEEEE LLLLLLL VVV IIIII NN NN AA AA TTT OOOO0 RR RR - -// Constants -#define KELVINATOR_HDR_MARK 8990U -#define KELVINATOR_HDR_SPACE 4490U -#define KELVINATOR_BIT_MARK 675U -#define KELVINATOR_ONE_SPACE 1560U -#define KELVINATOR_ZERO_SPACE 520U -#define KELVINATOR_GAP_SPACE 19950U -#define KELVINATOR_CMD_FOOTER 2U - -#define KELVINATOR_POWER 8U -#define KELVINATOR_MODE_MASK 0xF8U -#define KELVINATOR_FAN_OFFSET 4U -#define KELVINATOR_BASIC_FAN_MASK uint8_t(0xFFU ^ (3U << KELVINATOR_FAN_OFFSET)) -#define KELVINATOR_FAN_MASK uint8_t(0xFFU ^ (7U << KELVINATOR_FAN_OFFSET)) -#define KELVINATOR_CHECKSUM_START 10U -#define KELVINATOR_VENT_SWING_OFFSET 6U -#define KELVINATOR_VENT_SWING uint8_t(1U << KELVINATOR_VENT_SWING_OFFSET) -#define KELVINATOR_VENT_SWING_V uint8_t(1U) -#define KELVINATOR_VENT_SWING_H uint8_t(1U << 4) -#define KELVINATOR_SLEEP_1_AND_3 uint8_t(1U << 7) -#define KELVINATOR_QUIET_OFFSET 7U -#define KELVINATOR_QUIET uint8_t(1U << KELVINATOR_QUIET_OFFSET) -#define KELVINATOR_ION_FILTER_OFFSET 6U -#define KELVINATOR_ION_FILTER uint8_t(1U << KELVINATOR_ION_FILTER_OFFSET) -#define KELVINATOR_LIGHT_OFFSET 5U -#define KELVINATOR_LIGHT uint8_t(1U << KELVINATOR_LIGHT_OFFSET) -#define KELVINATOR_XFAN_OFFSET 7U -#define KELVINATOR_XFAN uint8_t(1U << KELVINATOR_XFAN_OFFSET) -#define KELVINATOR_TURBO_OFFSET 4U -#define KELVINATOR_TURBO uint8_t(1U << KELVINATOR_TURBO_OFFSET) - -#if SEND_KELVINATOR -// Send a Kelvinator A/C message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=KELVINATOR_STATE_LENGTH) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: STABLE / Known working. -// -void IRsend::sendKelvinator(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < KELVINATOR_STATE_LENGTH) - return; // Not enough bytes to send a proper message. - - // Set IR carrier frequency - enableIROut(38); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header #1 - mark(KELVINATOR_HDR_MARK); - space(KELVINATOR_HDR_SPACE); - // Data (command) - // Send the first command data (4 bytes) - uint8_t i; - for (i = 0; i < 4; i++) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, data[i], 8, false); - // Send Footer for the command data (3 bits (0b010)) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, KELVINATOR_CMD_FOOTER, 3, false); - // Send an interdata gap. - mark(KELVINATOR_BIT_MARK); - space(KELVINATOR_GAP_SPACE); - // Data (options) - // Send the 1st option chunk of data (4 bytes). - for (; i < 8; i++) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, data[i], 8, false); - // Send a double data gap to signify we are starting a new command sequence. - mark(KELVINATOR_BIT_MARK); - space(KELVINATOR_GAP_SPACE * 2); - // Header #2 - mark(KELVINATOR_HDR_MARK); - space(KELVINATOR_HDR_SPACE); - // Data (command) - // Send the 2nd command data (4 bytes). - // Basically an almost identical repeat of the earlier command data. - for (; i < 12; i++) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, data[i], 8, false); - // Send Footer for the command data (3 bits (B010)) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, KELVINATOR_CMD_FOOTER, 3, false); - // Send an interdata gap. - mark(KELVINATOR_BIT_MARK); - space(KELVINATOR_GAP_SPACE); - // Data (options) - // Send the 2nd option chunk of data (4 bytes). - // Unlike the commands, definitely not a repeat of the earlier option data. - for (; i < KELVINATOR_STATE_LENGTH; i++) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, data[i], 8, false); - // Footer - mark(KELVINATOR_BIT_MARK); - space(KELVINATOR_GAP_SPACE * 2); - } -} - -IRKelvinatorAC::IRKelvinatorAC(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -void IRKelvinatorAC::stateReset() { - for (uint8_t i = 0; i < KELVINATOR_STATE_LENGTH; i++) - remote_state[i] = 0x0; - remote_state[3] = 0x50; - remote_state[11] = 0x70; -} - -void IRKelvinatorAC::begin() { - _irsend.begin(); -} - -void IRKelvinatorAC::fixup() { - // X-Fan mode is only valid in COOL or DRY modes. - if (getMode() != KELVINATOR_COOL && getMode() != KELVINATOR_DRY) - setXFan(false); - checksum(); // Calculate the checksums -} - -void IRKelvinatorAC::send() { - fixup(); // Ensure correct settings before sending. - _irsend.sendKelvinator(remote_state); -} - -uint8_t* IRKelvinatorAC::getRaw() { - fixup(); // Ensure correct settings before sending. - return remote_state; -} - -// Many Bothans died to bring us this information. -void IRKelvinatorAC::checksum() { - // For each command + options block. - for (uint8_t offset = 0; offset < KELVINATOR_STATE_LENGTH; offset += 8) { - uint8_t sum = KELVINATOR_CHECKSUM_START; - // Sum the lower half of the first 4 bytes of this block. - for (uint8_t i = 0; i < 4; i++) - sum += (remote_state[i + offset] & 0xFU); - // then sum the upper half of the next 3 bytes. - for (uint8_t i = 4; i < 7; i++) - sum += (remote_state[i + offset] >> 4); - // Trim it down to fit into the 4 bits allowed. i.e. Mod 16. - sum &= 0xFU; - // Place it into the IR code in the top half of the 8th & 16th byte. - remote_state[7 + offset] = (sum << 4) | (remote_state[7 + offset] & 0xFU); - } -} - -void IRKelvinatorAC::on() { - remote_state[0] |= KELVINATOR_POWER; - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} - -void IRKelvinatorAC::off() { - remote_state[0] &= ~KELVINATOR_POWER; - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} - -void IRKelvinatorAC::setPower(bool state) { - if (state) - on(); - else - off(); -} - -bool IRKelvinatorAC::getPower() { - return ((remote_state[0] & KELVINATOR_POWER) != 0); -} - -// Set the temp. in deg C -void IRKelvinatorAC::setTemp(uint8_t temp) { - temp = std::max((uint8_t) KELVINATOR_MIN_TEMP, temp); - temp = std::min((uint8_t) KELVINATOR_MAX_TEMP, temp); - remote_state[1] = (remote_state[1] & 0xF0U) | (temp - KELVINATOR_MIN_TEMP); - remote_state[9] = remote_state[1]; // Duplicate to the 2nd command chunk. -} - -// Return the set temp. in deg C -uint8_t IRKelvinatorAC::getTemp() { - return ((remote_state[1] & 0xFU) + KELVINATOR_MIN_TEMP); -} - -// Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed -void IRKelvinatorAC::setFan(uint8_t fan) { - fan = std::min((uint8_t) KELVINATOR_FAN_MAX, fan); // Bounds check - - // Only change things if we need to. - if (fan != getFan()) { - // Set the basic fan values. - uint8_t fan_basic = std::min((uint8_t) KELVINATOR_BASIC_FAN_MAX, fan); - remote_state[0] = (remote_state[0] & KELVINATOR_BASIC_FAN_MASK) | - (fan_basic << KELVINATOR_FAN_OFFSET); - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. - // Set the advanced(?) fan value. - remote_state[14] = (remote_state[14] & KELVINATOR_FAN_MASK) | - (fan << KELVINATOR_FAN_OFFSET); - setTurbo(false); // Turbo mode is turned off if we change the fan settings. - } -} - -uint8_t IRKelvinatorAC::getFan() { - return ((remote_state[14] & ~KELVINATOR_FAN_MASK) >> KELVINATOR_FAN_OFFSET); -} - -uint8_t IRKelvinatorAC::getMode() { - return (remote_state[0] & ~KELVINATOR_MODE_MASK); -} - -void IRKelvinatorAC::setMode(uint8_t mode) { - // If we get an unexpected mode, default to AUTO. - if (mode > KELVINATOR_HEAT) mode = KELVINATOR_AUTO; - remote_state[0] = (remote_state[0] & KELVINATOR_MODE_MASK) | mode; - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. - if (mode == KELVINATOR_AUTO || KELVINATOR_DRY) - // When the remote is set to Auto or Dry, it defaults to 25C and doesn't - // show it. - setTemp(KELVINATOR_AUTO_TEMP); -} - -void IRKelvinatorAC::setSwingVertical(bool state) { - if (state) { - remote_state[0] |= KELVINATOR_VENT_SWING; - remote_state[4] |= KELVINATOR_VENT_SWING_V; - } else { - remote_state[4] &= ~KELVINATOR_VENT_SWING_V; - if (!getSwingHorizontal()) - remote_state[0] &= ~KELVINATOR_VENT_SWING; - } - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getSwingVertical() { - return ((remote_state[4] & KELVINATOR_VENT_SWING_V) != 0); -} - -void IRKelvinatorAC::setSwingHorizontal(bool state) { - if (state) { - remote_state[0] |= KELVINATOR_VENT_SWING; - remote_state[4] |= KELVINATOR_VENT_SWING_H; - } else { - remote_state[4] &= ~KELVINATOR_VENT_SWING_H; - if (!getSwingVertical()) - remote_state[0] &= ~KELVINATOR_VENT_SWING; - } - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getSwingHorizontal() { - return ((remote_state[4] & KELVINATOR_VENT_SWING_H) != 0); -} - -void IRKelvinatorAC::setQuiet(bool state) { - remote_state[12] &= ~KELVINATOR_QUIET; - remote_state[12] |= (state << KELVINATOR_QUIET_OFFSET); -} - -bool IRKelvinatorAC::getQuiet() { - return ((remote_state[12] & KELVINATOR_QUIET) != 0); -} - -void IRKelvinatorAC::setIonFilter(bool state) { - remote_state[2] &= ~KELVINATOR_ION_FILTER; - remote_state[2] |= (state << KELVINATOR_ION_FILTER_OFFSET); - remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getIonFilter() { - return ((remote_state[2] & KELVINATOR_ION_FILTER) != 0); -} - -void IRKelvinatorAC::setLight(bool state) { - remote_state[2] &= ~KELVINATOR_LIGHT; - remote_state[2] |= (state << KELVINATOR_LIGHT_OFFSET); - remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getLight() { - return ((remote_state[2] & KELVINATOR_LIGHT) != 0); -} - -// Note: XFan mode is only valid in Cool or Dry mode. -void IRKelvinatorAC::setXFan(bool state) { - remote_state[2] &= ~KELVINATOR_XFAN; - remote_state[2] |= (state << KELVINATOR_XFAN_OFFSET); - remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getXFan() { - return ((remote_state[2] & KELVINATOR_XFAN) != 0); -} - -// Note: Turbo mode is turned off if the fan speed is changed. -void IRKelvinatorAC::setTurbo(bool state) { - remote_state[2] &= ~KELVINATOR_TURBO; - remote_state[2] |= (state << KELVINATOR_TURBO_OFFSET); - remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getTurbo() { - return ((remote_state[2] & KELVINATOR_TURBO) != 0); -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp deleted file mode 100644 index 716ddd205..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2015 Darryl Smith -// Copyright 2015 cheaplin -// Copyright 2017 David Conran - -#include "ir_LG.h" -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// L GGGG -// L G -// L G GG -// L G G -// LLLLL GGG - -// LG decode originally added by Darryl Smith (based on the JVC protocol) -// LG send originally added by https://github.com/chaeplin - -// Constants -#define LG_TICK 50U -#define LG_HDR_MARK_TICKS 160U -#define LG_HDR_MARK (LG_HDR_MARK_TICKS * LG_TICK) -#define LG_HDR_SPACE_TICKS 80U -#define LG_HDR_SPACE (LG_HDR_SPACE_TICKS * LG_TICK) -#define LG_BIT_MARK_TICKS 11U -#define LG_BIT_MARK (LG_BIT_MARK_TICKS * LG_TICK) -#define LG_ONE_SPACE_TICKS 32U -#define LG_ONE_SPACE (LG_ONE_SPACE_TICKS * LG_TICK) -#define LG_ZERO_SPACE_TICKS 11U -#define LG_ZERO_SPACE (LG_ZERO_SPACE_TICKS * LG_TICK) -#define LG_RPT_SPACE_TICKS 45U -#define LG_RPT_SPACE (LG_RPT_SPACE_TICKS * LG_TICK) -#define LG_MIN_GAP_TICKS 795U -#define LG_MIN_GAP (LG_MIN_GAP_TICKS * LG_TICK) -#define LG_MIN_MESSAGE_LENGTH_TICKS 2161U -#define LG_MIN_MESSAGE_LENGTH (LG_MIN_MESSAGE_LENGTH_TICKS * LG_TICK) -#define LG32_HDR_MARK_TICKS 90U -#define LG32_HDR_MARK (LG32_HDR_MARK_TICKS * LG_TICK) -#define LG32_HDR_SPACE_TICKS 89U -#define LG32_HDR_SPACE (LG32_HDR_SPACE_TICKS * LG_TICK) -#define LG32_RPT_HDR_MARK_TICKS 179U -#define LG32_RPT_HDR_MARK (LG32_RPT_HDR_MARK_TICKS * LG_TICK) - -#if (SEND_LG || DECODE_LG) -// Calculate the rolling 4-bit wide checksum over all of the data. -// Args: -// data: The value to be checksum'ed. -// Returns: -// A 4-bit checksum. -uint8_t calcLGChecksum(uint16_t data) { - return(((data >> 12) + ((data >> 8) & 0xF) + ((data >> 4) & 0xF) + - (data & 0xF)) & 0xF); -} -#endif - -#if SEND_LG -// Send an LG formatted message. -// -// Args: -// data: The contents of the message you want to send. -// nbits: The bit size of the message being sent. -// Typically LG_BITS or LG32_BITS. -// repeat: The number of times you want the message to be repeated. -// -// Status: Beta / Should be working. -// -// Notes: -// LG has a separate message to indicate a repeat, like NEC does. -void IRsend::sendLG(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set IR carrier frequency - enableIROut(38); - - uint16_t repeatHeaderMark = 0; - IRtimer usecTimer = IRtimer(); - - if (nbits >= LG32_BITS) { - // LG 32bit protocol is near identical to Samsung except for repeats. - sendSAMSUNG(data, nbits, 0); // Send it as a single Samsung message. - repeatHeaderMark = LG32_RPT_HDR_MARK; - repeat++; - } else { - // LG (28-bit) protocol. - repeatHeaderMark = LG_HDR_MARK; - // Header - usecTimer.reset(); - mark(LG_HDR_MARK); - space(LG_HDR_SPACE); - // Data - sendData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, - data, nbits, true); - // Footer - mark(LG_BIT_MARK); - space(std::max((uint32_t) (LG_MIN_MESSAGE_LENGTH - usecTimer.elapsed()), - (uint32_t) LG_MIN_GAP)); - } - - // Repeat - // Protocol has a mandatory repeat-specific code sent after every command. - for (uint16_t i = 0; i < repeat; i++) { - usecTimer.reset(); - mark(repeatHeaderMark); - space(LG_RPT_SPACE); - mark(LG_BIT_MARK); - space(std::max((uint32_t) LG_MIN_MESSAGE_LENGTH - usecTimer.elapsed(), - (uint32_t) LG_MIN_GAP)); - } -} - -// Construct a raw 28-bit LG message from the supplied address & command. -// -// Args: -// address: The address code. -// command: The command code. -// Returns: -// A raw 28-bit LG message suitable for sendLG(). -// -// Status: BETA / Should work. -// -// Notes: -// e.g. Sequence of bits = address + command + checksum. -uint32_t IRsend::encodeLG(uint16_t address, uint16_t command) { - return ((address << 20) | (command << 4) | calcLGChecksum(command)); -} -#endif - -#if DECODE_LG -// Decode the supplied LG message. -// LG protocol has a repeat code which is 4 items long. -// Even though the protocol has 28/32 bits of data, only 24/28 bits are -// distinct. -// In transmission order, the 28/32 bits are constructed as follows: -// 8/12 bits of address + 16 bits of command + 4 bits of checksum. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. -// Typically LG_BITS or LG32_BITS. -// strict: Flag to indicate if we strictly adhere to the specification. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / Should work. -// -// Note: -// LG 32bit protocol appears near identical to the Samsung protocol. -// They possibly differ on how they repeat and initial HDR mark. - -// Ref: -// https://funembedded.wordpress.com/2014/11/08/ir-remote-control-for-lg-conditioner-using-stm32f302-mcu-on-mbed-platform/ -bool IRrecv::decodeLG(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1 && results->rawlen != 4) - return false; // Can't possibly be a valid LG message. - if (strict && nbits != LG_BITS && nbits != LG32_BITS) - return false; // Doesn't comply with expected LG protocol. - - uint64_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset], LG_HDR_MARK) && - !matchMark(results->rawbuf[offset], LG32_HDR_MARK)) return false; - uint32_t m_tick; - if (matchMark(results->rawbuf[offset], LG_HDR_MARK)) - m_tick = results->rawbuf[offset++] * RAWTICK / LG_HDR_MARK_TICKS; - else - m_tick = results->rawbuf[offset++] * RAWTICK / LG32_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], LG_HDR_SPACE) && - !matchSpace(results->rawbuf[offset], LG32_HDR_SPACE)) return false; - uint32_t s_tick; - if (matchSpace(results->rawbuf[offset], LG_HDR_SPACE)) - s_tick = results->rawbuf[offset++] * RAWTICK / LG_HDR_SPACE_TICKS; - else - s_tick = results->rawbuf[offset++] * RAWTICK / LG32_HDR_SPACE_TICKS; - - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - LG_BIT_MARK_TICKS * m_tick, - LG_ONE_SPACE_TICKS * s_tick, - LG_BIT_MARK_TICKS * m_tick, - LG_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - - // Footer - if (!matchMark(results->rawbuf[offset++], LG_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], LG_MIN_GAP_TICKS * s_tick)) - return false; - - // Repeat - if (nbits >= LG32_BITS) { - // If we are expecting the LG 32-bit protocol, there is always - // a repeat message. So, check for it. -#ifndef UNIT_TEST - if (!matchSpace(results->rawbuf[offset], LG_MIN_GAP_TICKS * s_tick)) -#else - if (!(matchSpace(results->rawbuf[offset], - LG_MIN_MESSAGE_LENGTH_TICKS * s_tick) || - matchSpace(results->rawbuf[offset], 65500) || - matchSpace(results->rawbuf[offset], LG_MIN_GAP_TICKS * s_tick))) -#endif // UNIT_TEST - return false; - offset++; - if (!matchMark(results->rawbuf[offset++], LG32_RPT_HDR_MARK_TICKS * m_tick)) - return false; - if (!matchSpace(results->rawbuf[offset++], LG_RPT_SPACE_TICKS * s_tick)) - return false; - if (!matchMark(results->rawbuf[offset++], LG_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], LG_MIN_GAP_TICKS * s_tick)) - return false; - } - - // Compliance - uint16_t command = (data >> 4) & 0xFFFF; // The 16 bits before the checksum. - - if (strict && (data & 0xF) != calcLGChecksum(command)) - return false; // The last 4 bits sent are the expected checksum. - - // Success - results->decode_type = LG; - results->bits = nbits; - results->value = data; - results->command = command; - results->address = data >> 20; // The bits before the command. - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp deleted file mode 100644 index df8b6e1ef..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran - -#include "ir_Mitsubishi.h" -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII -// M M M I T S U U B B I S H H I -// M M M I T SSS U U BBBB I SSS HHHHH I -// M M I T S U U B B I S H H I -// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII - -// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote -// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran - -// Constants -// Mitsubishi TV -// period time is 1/33000Hz = 30.303 uSeconds (T) -// Ref: -// GlobalCache's Control Tower's Mitsubishi TV data. -// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp -#define MITSUBISHI_TICK 30U -#define MITSUBISHI_BIT_MARK_TICKS 10U -#define MITSUBISHI_BIT_MARK (MITSUBISHI_BIT_MARK_TICKS * \ - MITSUBISHI_TICK) -#define MITSUBISHI_ONE_SPACE_TICKS 70U -#define MITSUBISHI_ONE_SPACE (MITSUBISHI_ONE_SPACE_TICKS * \ - MITSUBISHI_TICK) -#define MITSUBISHI_ZERO_SPACE_TICKS 30U -#define MITSUBISHI_ZERO_SPACE (MITSUBISHI_ZERO_SPACE_TICKS * \ - MITSUBISHI_TICK) -#define MITSUBISHI_MIN_COMMAND_LENGTH_TICKS 1786U -#define MITSUBISHI_MIN_COMMAND_LENGTH (MITSUBISHI_MIN_COMMAND_LENGTH_TICKS * \ - MITSUBISHI_TICK) -#define MITSUBISHI_MIN_GAP_TICKS 936U -#define MITSUBISHI_MIN_GAP (MITSUBISHI_MIN_GAP_TICKS * \ - MITSUBISHI_TICK) - -// Mitsubishi A/C -// Ref: -// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L84 -#define MITSUBISHI_AC_HDR_MARK 3400U -#define MITSUBISHI_AC_HDR_SPACE 1750U -#define MITSUBISHI_AC_BIT_MARK 450U -#define MITSUBISHI_AC_ONE_SPACE 1300U -#define MITSUBISHI_AC_ZERO_SPACE 420U -#define MITSUBISHI_AC_RPT_MARK 440U -#define MITSUBISHI_AC_RPT_SPACE 17100UL - -#if SEND_MITSUBISHI -// Send a Mitsubishi message -// -// Args: -// data: Contents of the message to be sent. -// nbits: Nr. of bits of data to be sent. Typically MITSUBISHI_BITS. -// repeat: Nr. of additional times the message is to be sent. -// -// Status: ALPHA / untested. -// -// Notes: -// This protocol appears to have no header. -// Ref: -// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp -// GlobalCache's Control Tower's Mitsubishi TV data. -void IRsend::sendMitsubishi(uint64_t data, uint16_t nbits, uint16_t repeat) { - enableIROut(33); // Set IR carrier frequency - IRtimer usecTimer = IRtimer(); - - for (uint16_t i = 0; i <= repeat; i++) { - usecTimer.reset(); - // No header - - // Data - sendData(MITSUBISHI_BIT_MARK, MITSUBISHI_ONE_SPACE, - MITSUBISHI_BIT_MARK, MITSUBISHI_ZERO_SPACE, - data, nbits, true); - // Footer - mark(MITSUBISHI_BIT_MARK); - space(std::max(MITSUBISHI_MIN_COMMAND_LENGTH - usecTimer.elapsed(), - MITSUBISHI_MIN_GAP)); - } -} -#endif - -#if DECODE_MITSUBISHI -// Decode the supplied Mitsubishi message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / previously working. -// -// Notes: -// This protocol appears to have no header. -// -// Ref: -// GlobalCache's Control Tower's Mitsubishi TV data. -bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + FOOTER - 1) - return false; // Shorter than shortest possibly expected. - if (strict && nbits != MITSUBISHI_BITS) - return false; // Request is out of spec. - - uint16_t offset = OFFSET_START; - uint64_t data = 0; - - // No Header - // But try to auto-calibrate off the initial mark signal. - if (!matchMark(results->rawbuf[offset], MITSUBISHI_BIT_MARK, 30)) - return false; - // Calculate how long the common tick time is based on the initial mark. - uint32_t tick = results->rawbuf[offset] * RAWTICK / MITSUBISHI_BIT_MARK_TICKS; - - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - MITSUBISHI_BIT_MARK_TICKS * tick, - MITSUBISHI_ONE_SPACE_TICKS * tick, - MITSUBISHI_BIT_MARK_TICKS * tick, - MITSUBISHI_ZERO_SPACE_TICKS * tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - uint16_t actualBits = data_result.used / 2; - - // Footer - if (!matchMark(results->rawbuf[offset++], MITSUBISHI_BIT_MARK_TICKS * tick, - 30)) return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], MITSUBISHI_MIN_GAP_TICKS * tick)) - return false; - - // Compliance - if (actualBits < nbits) - return false; - if (strict && actualBits != nbits) - return false; // Not as we expected. - - // Success - results->decode_type = MITSUBISHI; - results->bits = actualBits; - results->value = data; - results->address = 0; - results->command = 0; - return true; -} -#endif - -#if SEND_MITSUBISHI_AC -// Send a Mitsubishi A/C message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=MITSUBISHI_AC_STATE_LENGTH) -// repeat: Nr. of times the message is to be repeated. -// (Default = MITSUBISHI_AC_MIN_REPEAT). -// -// Status: BETA / Appears to be working. -// -void IRsend::sendMitsubishiAC(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < MITSUBISHI_AC_STATE_LENGTH) - return; // Not enough bytes to send a proper message. - - // Set IR carrier frequency - enableIROut(38); - // Mitsubishi AC remote sends the packet twice. - for (uint16_t r = 0; r <= repeat; r++) { - // Header - mark(MITSUBISHI_AC_HDR_MARK); - space(MITSUBISHI_AC_HDR_SPACE); - // Data - for (uint16_t i = 0; i < nbytes; i++) - sendData(MITSUBISHI_AC_BIT_MARK, MITSUBISHI_AC_ONE_SPACE, - MITSUBISHI_AC_BIT_MARK, MITSUBISHI_AC_ZERO_SPACE, - data[i], 8, false); - // Footer - mark(MITSUBISHI_AC_RPT_MARK); - space(MITSUBISHI_AC_RPT_SPACE); - } -} - -// Code to emulate Mitsubishi A/C IR remote control unit. -// Inspired and derived from the work done at: -// https://github.com/r45635/HVAC-IR-Control -// -// Warning: Consider this very alpha code. Seems to work, but not validated. -// -// Equipment it seems compatible with: -// * -// Initialise the object. -IRMitsubishiAC::IRMitsubishiAC(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -// Reset the state of the remote to a known good state/sequence. -void IRMitsubishiAC::stateReset() { - // The state of the IR remote in IR code form. - // Known good state obtained from: - // https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L108 - // Note: Can't use the following because it requires -std=c++11 - // uint8_t known_good_state[MITSUBISHI_AC_STATE_LENGTH] = { - // 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, - // 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; - remote_state[0] = 0x23; - remote_state[1] = 0xCB; - remote_state[2] = 0x26; - remote_state[3] = 0x01; - remote_state[4] = 0x00; - remote_state[5] = 0x20; - remote_state[6] = 0x08; - remote_state[7] = 0x06; - remote_state[8] = 0x30; - remote_state[9] = 0x45; - remote_state[10] = 0x67; - for (uint8_t i = 11; i < MITSUBISHI_AC_STATE_LENGTH - 1; i++) - remote_state[i] = 0; - remote_state[MITSUBISHI_AC_STATE_LENGTH - 1] = 0x1F; - checksum(); // Calculate the checksum -} - -// Configure the pin for output. -void IRMitsubishiAC::begin() { - _irsend.begin(); -} - -// Send the current desired state to the IR LED. -void IRMitsubishiAC::send() { - checksum(); // Ensure correct checksum before sending. - _irsend.sendMitsubishiAC(remote_state); -} - -// Return a pointer to the internal state date of the remote. -uint8_t* IRMitsubishiAC::getRaw() { - checksum(); - return remote_state; -} - -// Calculate the checksum for the current internal state of the remote. -void IRMitsubishiAC::checksum() { - uint8_t sum = 0; - // Checksum is simple addition of all previous bytes stored - // as a 8 bit value. - for (uint8_t i = 0; i < 17; i++) - sum += remote_state[i]; - remote_state[17] = sum & 0xFFU; -} - -// Set the requested power state of the A/C to off. -void IRMitsubishiAC::on() { - // state = ON; - remote_state[5] |= MITSUBISHI_AC_POWER; -} - -// Set the requested power state of the A/C to off. -void IRMitsubishiAC::off() { - // state = OFF; - remote_state[5] &= ~MITSUBISHI_AC_POWER; -} - -// Set the requested power state of the A/C. -void IRMitsubishiAC::setPower(bool state) { - if (state) - on(); - else - off(); -} - -// Return the requested power state of the A/C. -bool IRMitsubishiAC::getPower() { - return((remote_state[5] & MITSUBISHI_AC_POWER) != 0); -} - -// Set the temp. in deg C -void IRMitsubishiAC::setTemp(uint8_t temp) { - temp = std::max((uint8_t) MITSUBISHI_AC_MIN_TEMP, temp); - temp = std::min((uint8_t) MITSUBISHI_AC_MAX_TEMP, temp); - remote_state[7] = temp - MITSUBISHI_AC_MIN_TEMP; -} - -// Return the set temp. in deg C -uint8_t IRMitsubishiAC::getTemp() { - return(remote_state[7] + MITSUBISHI_AC_MIN_TEMP); -} - -// Set the speed of the fan, 0-6. -// 0 is auto, 1-5 is the speed, 6 is silent. -void IRMitsubishiAC::setFan(uint8_t fan) { - // Bounds check - if (fan > MITSUBISHI_AC_FAN_SILENT) - fan = MITSUBISHI_AC_FAN_MAX; // Set the fan to maximum if out of range. - if (fan == MITSUBISHI_AC_FAN_AUTO) { // Automatic is a special case. - remote_state[9] = 0b10000000 | (remote_state[9] & 0b01111000); - return; - } else if (fan >= MITSUBISHI_AC_FAN_MAX) { - fan--; // There is no spoon^H^H^Heed 5 (max), pretend it doesn't exist. - } - remote_state[9] &= 0b01111000; // Clear the previous state - remote_state[9] |= fan; -} - -// Return the requested state of the unit's fan. -uint8_t IRMitsubishiAC::getFan() { - uint8_t fan = remote_state[9] & 0b111; - if (fan == MITSUBISHI_AC_FAN_MAX) - return MITSUBISHI_AC_FAN_SILENT; - return fan; -} - -// Return the requested climate operation mode of the a/c unit. -uint8_t IRMitsubishiAC::getMode() { - return(remote_state[6]); -} - -// Set the requested climate operation mode of the a/c unit. -void IRMitsubishiAC::setMode(uint8_t mode) { - // If we get an unexpected mode, default to AUTO. - switch (mode) { - case MITSUBISHI_AC_AUTO: break; - case MITSUBISHI_AC_COOL: break; - case MITSUBISHI_AC_DRY: break; - case MITSUBISHI_AC_HEAT: break; - default: mode = MITSUBISHI_AC_AUTO; - } - remote_state[6] = mode; -} - -// Set the requested vane operation mode of the a/c unit. -void IRMitsubishiAC::setVane(uint8_t mode) { - mode = std::min(mode, (uint8_t) 0b111); // bounds check - mode |= 0b1000; - mode <<= 3; - remote_state[9] &= 0b11000111; // Clear the previous setting. - remote_state[9] |= mode; -} - -// Return the requested vane operation mode of the a/c unit. -uint8_t IRMitsubishiAC::getVane() { - return ((remote_state[9] & 0b00111000) >> 3); -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h deleted file mode 100644 index e9f5731aa..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran -#ifndef IR_MITSUBISHI_H_ -#define IR_MITSUBISHI_H_ - -#define __STDC_LIMIT_MACROS -#include -#include "IRremoteESP8266.h" -#include "IRsend.h" - -// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII -// M M M I T S U U B B I S H H I -// M M M I T SSS U U BBBB I SSS HHHHH I -// M M I T S U U B B I S H H I -// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII - -// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote -// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran - -// Constants -#define MITSUBISHI_AC_AUTO 0x20U -#define MITSUBISHI_AC_COOL 0x18U -#define MITSUBISHI_AC_DRY 0x10U -#define MITSUBISHI_AC_HEAT 0x08U -#define MITSUBISHI_AC_POWER 0x20U -#define MITSUBISHI_AC_FAN_AUTO 0U -#define MITSUBISHI_AC_FAN_MAX 5U -#define MITSUBISHI_AC_FAN_REAL_MAX 4U -#define MITSUBISHI_AC_FAN_SILENT 6U -#define MITSUBISHI_AC_MIN_TEMP 16U // 16C -#define MITSUBISHI_AC_MAX_TEMP 31U // 31C -#define MITSUBISHI_AC_VANE_AUTO 0U -#define MITSUBISHI_AC_VANE_AUTO_MOVE 7U - -#if SEND_MITSUBISHI_AC -class IRMitsubishiAC { - public: - explicit IRMitsubishiAC(uint16_t pin); - - void stateReset(); - void send(); - void begin(); - void on(); - void off(); - void setPower(bool state); - bool getPower(); - void setTemp(uint8_t temp); - uint8_t getTemp(); - void setFan(uint8_t fan); - uint8_t getFan(); - void setMode(uint8_t mode); - uint8_t getMode(); - void setVane(uint8_t mode); - uint8_t getVane(); - uint8_t* getRaw(); - - private: - uint8_t remote_state[MITSUBISHI_AC_STATE_LENGTH]; - void checksum(); - IRsend _irsend; -}; - -#endif - -#endif // IR_MITSUBISHI_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp deleted file mode 100644 index e1afda4c5..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran - -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// NN NN IIIII KK KK AAA IIIII -// NNN NN III KK KK AAAAA III -// NN N NN III KKKK AA AA III -// NN NNN III KK KK AAAAAAA III -// NN NN IIIII KK KK AA AA IIIII - -// Constants -// Ref: -// https://github.com/markszabo/IRremoteESP8266/issues/309 -#define NIKAI_TICK 500U -#define NIKAI_HDR_MARK_TICKS 8U -#define NIKAI_HDR_MARK (NIKAI_HDR_MARK_TICKS * NIKAI_TICK) -#define NIKAI_HDR_SPACE_TICKS 8U -#define NIKAI_HDR_SPACE (NIKAI_HDR_SPACE_TICKS * NIKAI_TICK) -#define NIKAI_BIT_MARK_TICKS 1U -#define NIKAI_BIT_MARK (NIKAI_BIT_MARK_TICKS * NIKAI_TICK) -#define NIKAI_ONE_SPACE_TICKS 2U -#define NIKAI_ONE_SPACE (NIKAI_ONE_SPACE_TICKS * NIKAI_TICK) -#define NIKAI_ZERO_SPACE_TICKS 4U -#define NIKAI_ZERO_SPACE (NIKAI_ZERO_SPACE_TICKS * NIKAI_TICK) -#define NIKAI_MIN_GAP_TICKS 17U -#define NIKAI_MIN_GAP (NIKAI_MIN_GAP_TICKS * NIKAI_TICK) - - -#if SEND_NIKAI -// Send a Nikai TV formatted message. -// -// Args: -// data: The message to be sent. -// nbits: The bit size of the message being sent. typically NIKAI_BITS. -// repeat: The number of times the message is to be repeated. -// -// Status: ALPHA / Untested. -// -// Ref: https://github.com/markszabo/IRremoteESP8266/issues/309 -void IRsend::sendNikai(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 38kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(38, 33); - // We always send a message, even for repeat=0, hence '<= repeat'. - for (uint16_t i=0; i <= repeat; i++) { - // Header - mark(NIKAI_HDR_MARK); - space(NIKAI_HDR_SPACE); - // Data - sendData(NIKAI_BIT_MARK, NIKAI_ONE_SPACE, NIKAI_BIT_MARK, - NIKAI_ZERO_SPACE, data, nbits, true); - // Footer - mark(NIKAI_BIT_MARK); - space(NIKAI_MIN_GAP); - } -} -#endif - -#if DECODE_NIKAI -// Decode the supplied Nikai message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. -// Typically NIKAI_BITS. -// strict: Flag to indicate if we strictly adhere to the specification. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: ALPHA / Untested. -// -bool IRrecv::decodeNikai(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) - return false; // Can't possibly be a valid Nikai message. - if (strict && nbits != NIKAI_BITS) - return false; // We expect Nikai to be a certain sized message. - - uint64_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset], NIKAI_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - NIKAI_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], NIKAI_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - NIKAI_HDR_SPACE_TICKS; - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - NIKAI_BIT_MARK_TICKS * m_tick, - NIKAI_ONE_SPACE_TICKS * s_tick, - NIKAI_BIT_MARK_TICKS * m_tick, - NIKAI_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - // Footer - if (!matchMark(results->rawbuf[offset++], NIKAI_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], NIKAI_MIN_GAP_TICKS * s_tick)) - return false; - - // Compliance - - // Success - results->bits = nbits; - results->value = data; - results->decode_type = NIKAI; - results->command = 0; - results->address = 0; - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp deleted file mode 100644 index fb1f12234..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2015 Kristian Lauszus -// Copyright 2017 David Conran - -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC -// P P A A NN N A A S O O NN N I C -// PPPP AAAAA N N N AAAAA SSS O O N N N I C -// P A A N NN A A S O O N NN I C -// P A A N N A A SSSS OOO N N IIIII CCCC - -// Panasonic protocol originally added by Kristian Lauszus from: -// https://github.com/z3t0/Arduino-IRremote -// (Thanks to zenwheel and other people at the original blog post) - -// Constants -// Ref: -// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 -#define PANASONIC_TICK 432U -#define PANASONIC_HDR_MARK_TICKS 8U -#define PANASONIC_HDR_MARK (PANASONIC_HDR_MARK_TICKS * PANASONIC_TICK) -#define PANASONIC_HDR_SPACE_TICKS 4U -#define PANASONIC_HDR_SPACE (PANASONIC_HDR_SPACE_TICKS * PANASONIC_TICK) -#define PANASONIC_BIT_MARK_TICKS 1U -#define PANASONIC_BIT_MARK (PANASONIC_BIT_MARK_TICKS * PANASONIC_TICK) -#define PANASONIC_ONE_SPACE_TICKS 3U -#define PANASONIC_ONE_SPACE (PANASONIC_ONE_SPACE_TICKS * PANASONIC_TICK) -#define PANASONIC_ZERO_SPACE_TICKS 1U -#define PANASONIC_ZERO_SPACE (PANASONIC_ZERO_SPACE_TICKS * PANASONIC_TICK) -#define PANASONIC_MIN_COMMAND_LENGTH_TICKS 300UL -#define PANASONIC_MIN_COMMAND_LENGTH (PANASONIC_MIN_COMMAND_LENGTH_TICKS * \ - PANASONIC_TICK) -#define PANASONIC_END_GAP 5000U // See issue #245 -#define PANASONIC_MIN_GAP_TICKS (PANASONIC_MIN_COMMAND_LENGTH_TICKS - \ - (PANASONIC_HDR_MARK_TICKS + PANASONIC_HDR_SPACE_TICKS + \ - PANASONIC_BITS * (PANASONIC_BIT_MARK_TICKS + PANASONIC_ONE_SPACE_TICKS) + \ - PANASONIC_BIT_MARK_TICKS)) -#define PANASONIC_MIN_GAP ((uint32_t)(PANASONIC_MIN_GAP_TICKS * PANASONIC_TICK)) -#if (SEND_PANASONIC || SEND_DENON) -// Send a Panasonic formatted message. -// -// Args: -// data: The message to be sent. -// nbits: The number of bits of the message to be sent. (PANASONIC_BITS). -// repeat: The number of times the command is to be repeated. -// -// Status: BETA / Should be working. -// -// Note: -// This protocol is a modified version of Kaseikyo. -void IRsend::sendPanasonic64(uint64_t data, uint16_t nbits, uint16_t repeat) { - enableIROut(36700U); // Set IR carrier frequency of 36.7kHz. - IRtimer usecTimer = IRtimer(); - - for (uint16_t i = 0; i <= repeat; i++) { - usecTimer.reset(); - // Header - mark(PANASONIC_HDR_MARK); - space(PANASONIC_HDR_SPACE); - // Data - sendData(PANASONIC_BIT_MARK, PANASONIC_ONE_SPACE, - PANASONIC_BIT_MARK, PANASONIC_ZERO_SPACE, - data, nbits, true); - // Footer - mark(PANASONIC_BIT_MARK); - space(std::max((uint32_t) PANASONIC_MIN_COMMAND_LENGTH - - usecTimer.elapsed(), - PANASONIC_MIN_GAP)); - } -} - -// Send a Panasonic formatted message. -// -// Args: -// address: The manufacturer code. -// data: The data portion to be sent. -// nbits: The number of bits of the message to be sent. (PANASONIC_BITS). -// repeat: The number of times the command is to be repeated. -// -// Status: STABLE. -// -// Note: -// This protocol is a modified version of Kaseikyo. -void IRsend::sendPanasonic(uint16_t address, uint32_t data, uint16_t nbits, - uint16_t repeat) { - sendPanasonic64(((uint64_t) address << 32) | (uint64_t) data, nbits, repeat); -} - -// Calculate the raw Panasonic data based on device, subdevice, & function. -// -// Args: -// manufacturer: A 16-bit manufacturer code. e.g. 0x4004 is Panasonic. -// device: An 8-bit code. -// subdevice: An 8-bit code. -// function: An 8-bit code. -// Returns: -// A raw uint64_t Panasonic message. -// -// Status: BETA / Should be working.. -// -// Note: -// Panasonic 48-bit protocol is a modified version of Kaseikyo. -// Ref: -// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?2615 -uint64_t IRsend::encodePanasonic(uint16_t manufacturer, - uint8_t device, - uint8_t subdevice, - uint8_t function) { - uint8_t checksum = device ^ subdevice ^ function; - return (((uint64_t) manufacturer << 32) | - ((uint64_t) device << 24) | - ((uint64_t) subdevice << 16) | - ((uint64_t) function << 8) | - checksum); -} -#endif // (SEND_PANASONIC || SEND_DENON) - -#if (DECODE_PANASONIC || DECODE_DENON) -// Decode the supplied Panasonic message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / Should be working. -// Note: -// Panasonic 48-bit protocol is a modified version of Kaseikyo. -// Ref: -// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 -// http://www.hifi-remote.com/wiki/index.php?title=Panasonic -bool IRrecv::decodePanasonic(decode_results *results, uint16_t nbits, - bool strict, uint32_t manufacturer) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) - return false; // Not enough entries to be a Panasonic message. - if (strict && nbits != PANASONIC_BITS) - return false; // Request is out of spec. - - uint64_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset], PANASONIC_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - PANASONIC_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], PANASONIC_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - PANASONIC_HDR_SPACE_TICKS; - - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - PANASONIC_BIT_MARK_TICKS * m_tick, - PANASONIC_ONE_SPACE_TICKS * s_tick, - PANASONIC_BIT_MARK_TICKS * m_tick, - PANASONIC_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - - // Footer - if (!match(results->rawbuf[offset++], PANASONIC_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], PANASONIC_END_GAP)) - return false; - - // Compliance - uint32_t address = data >> 32; - uint32_t command = data & 0xFFFFFFFF; - if (strict) { - if (address != manufacturer) // Verify the Manufacturer code. - return false; - // Verify the checksum. - uint8_t checksumOrig = data & 0xFF; - uint8_t checksumCalc = ((data >> 24) ^ (data >> 16) ^ (data >> 8)) & 0xFF; - if (checksumOrig != checksumCalc) - return false; - } - - // Success - results->value = data; - results->address = address; - results->command = command; - results->decode_type = PANASONIC; - results->bits = nbits; - return true; -} -#endif // (DECODE_PANASONIC || DECODE_DENON) diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp deleted file mode 100644 index dbd94bcd4..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran - -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// SSSS AAA MMM SSSS U U N N GGGG -// S A A M M M S U U NN N G -// SSS AAAAA M M M SSS U U N N N G GG -// S A A M M S U U N NN G G -// SSSS A A M M SSSS UUU N N GGG - -// Samsung originally added from https://github.com/shirriff/Arduino-IRremote/ - -// Constants -// Ref: -// http://elektrolab.wz.cz/katalog/samsung_protocol.pdf -#define SAMSUNG_TICK 560U -#define SAMSUNG_HDR_MARK_TICKS 8U -#define SAMSUNG_HDR_MARK (SAMSUNG_HDR_MARK_TICKS * SAMSUNG_TICK) -#define SAMSUNG_HDR_SPACE_TICKS 8U -#define SAMSUNG_HDR_SPACE (SAMSUNG_HDR_SPACE_TICKS * SAMSUNG_TICK) -#define SAMSUNG_BIT_MARK_TICKS 1U -#define SAMSUNG_BIT_MARK (SAMSUNG_BIT_MARK_TICKS * SAMSUNG_TICK) -#define SAMSUNG_ONE_SPACE_TICKS 3U -#define SAMSUNG_ONE_SPACE (SAMSUNG_ONE_SPACE_TICKS * SAMSUNG_TICK) -#define SAMSUNG_ZERO_SPACE_TICKS 1U -#define SAMSUNG_ZERO_SPACE (SAMSUNG_ZERO_SPACE_TICKS * SAMSUNG_TICK) -#define SAMSUNG_RPT_SPACE_TICKS 4U -#define SAMSUNG_RPT_SPACE (SAMSUNG_RPT_SPACE_TICKS * SAMSUNG_TICK) -#define SAMSUNG_MIN_MESSAGE_LENGTH_TICKS 193U -#define SAMSUNG_MIN_MESSAGE_LENGTH (SAMSUNG_MIN_MESSAGE_LENGTH_TICKS * \ - SAMSUNG_TICK) -#define SAMSUNG_MIN_GAP_TICKS (SAMSUNG_MIN_MESSAGE_LENGTH_TICKS - \ - (SAMSUNG_HDR_MARK_TICKS + SAMSUNG_HDR_SPACE_TICKS + \ - SAMSUNG_BITS * (SAMSUNG_BIT_MARK_TICKS + SAMSUNG_ONE_SPACE_TICKS) + \ - SAMSUNG_BIT_MARK_TICKS)) -#define SAMSUNG_MIN_GAP (SAMSUNG_MIN_GAP_TICKS * SAMSUNG_TICK) - - - -#if SEND_SAMSUNG -// Send a Samsung formatted message. -// Samsung has a separate message to indicate a repeat, like NEC does. -// TODO(crankyoldgit): Confirm that is actually how Samsung sends a repeat. -// The refdoc doesn't indicate it is true. -// -// Args: -// data: The message to be sent. -// nbits: The bit size of the message being sent. typically SAMSUNG_BITS. -// repeat: The number of times the message is to be repeated. -// -// Status: BETA / Should be working. -// -// Ref: http://elektrolab.wz.cz/katalog/samsung_protocol.pdf -void IRsend::sendSAMSUNG(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 38kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(38, 33); - IRtimer usecTimer = IRtimer(); - // We always send a message, even for repeat=0, hence '<= repeat'. - for (uint16_t i=0; i <= repeat; i++) { - usecTimer.reset(); - // Header - mark(SAMSUNG_HDR_MARK); - space(SAMSUNG_HDR_SPACE); - // Data - sendData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, - SAMSUNG_ZERO_SPACE, data, nbits, true); - // Footer - mark(SAMSUNG_BIT_MARK); - space(std::max((uint32_t) SAMSUNG_MIN_GAP, - (uint32_t) (SAMSUNG_MIN_MESSAGE_LENGTH - - usecTimer.elapsed()))); - } -} - -// Construct a raw Samsung message from the supplied customer(address) & -// command. -// -// Args: -// customer: The customer code. (aka. Address) -// command: The command code. -// Returns: -// A raw 32-bit Samsung message suitable for sendSAMSUNG(). -// -// Status: BETA / Should be working. -uint32_t IRsend::encodeSAMSUNG(uint8_t customer, uint8_t command) { - customer = reverseBits(customer, sizeof(customer) * 8); - command = reverseBits(command, sizeof(command) * 8); - return((command ^ 0xFF) | (command << 8) | - (customer << 16) | (customer << 24)); -} -#endif - -#if DECODE_SAMSUNG -// Decode the supplied Samsung message. -// Samsung messages whilst 32 bits in size, only contain 16 bits of distinct -// data. e.g. In transmition order: -// customer_byte + customer_byte(same) + address_byte + invert(address_byte) -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. Typically SAMSUNG_BITS. -// strict: Flag to indicate if we strictly adhere to the specification. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: STABLE -// -// Note: -// LG 32bit protocol appears near identical to the Samsung protocol. -// They differ on their compliance criteria and how they repeat. -// Ref: -// http://elektrolab.wz.cz/katalog/samsung_protocol.pdf -bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) - return false; // Can't possibly be a valid Samsung message. - if (strict && nbits != SAMSUNG_BITS) - return false; // We expect Samsung to be 32 bits of message. - - uint64_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset], SAMSUNG_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - SAMSUNG_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], SAMSUNG_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - SAMSUNG_HDR_SPACE_TICKS; - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - SAMSUNG_BIT_MARK_TICKS * m_tick, - SAMSUNG_ONE_SPACE_TICKS * s_tick, - SAMSUNG_BIT_MARK_TICKS * m_tick, - SAMSUNG_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - // Footer - if (!matchMark(results->rawbuf[offset++], SAMSUNG_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], SAMSUNG_MIN_GAP_TICKS * s_tick)) - return false; - - // Compliance - - // According to the spec, the customer (address) code is the first 8 - // transmitted bits. It's then repeated. Check for that. - uint8_t address = data >> 24; - if (strict && address != ((data >> 16) & 0xFF)) - return false; - // Spec says the command code is the 3rd block of transmitted 8-bits, - // followed by the inverted command code. - uint8_t command = (data & 0xFF00) >> 8; - if (strict && command != ((data & 0xFF) ^ 0xFF)) - return false; - - // Success - results->bits = nbits; - results->value = data; - results->decode_type = SAMSUNG; - // command & address need to be reversed as they are transmitted LSB first, - results->command = reverseBits(command, sizeof(command) * 8); - results->address = reverseBits(address, sizeof(address) * 8); - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp deleted file mode 100644 index ef8e9efa6..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2017 stufisher - -#include "ir_Trotec.h" -#include "IRremoteESP8266.h" -#include "IRutils.h" - -// Constants -#define TROTEC_HDR_MARK 5952U -#define TROTEC_HDR_SPACE 7364U -#define TROTEC_ONE_MARK 592U -#define TROTEC_ONE_SPACE 1560U -#define TROTEC_ZERO_MARK 592U -#define TROTEC_ZERO_SPACE 592U -#define TROTEC_GAP 6184U -#define TROTEC_GAP_END 1500U // made up value - -#if SEND_TROTEC - -void IRsend::sendTrotec(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < TROTEC_COMMAND_LENGTH) - return; - - enableIROut(36); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header - mark(TROTEC_HDR_MARK); - space(TROTEC_HDR_SPACE); - - // Data - for (uint16_t i = 0; i < nbytes; i++) - sendData(TROTEC_ONE_MARK, TROTEC_ONE_SPACE, TROTEC_ZERO_MARK, - TROTEC_ZERO_SPACE, data[i], 8, false); - - // Footer - mark(TROTEC_ONE_MARK); - space(TROTEC_GAP); - mark(TROTEC_ONE_MARK); - space(TROTEC_GAP_END); - } -} - -IRTrotecESP::IRTrotecESP(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -void IRTrotecESP::begin() { - _irsend.begin(); -} - -void IRTrotecESP::send() { - checksum(); - _irsend.sendTrotec(trotec); -} - -void IRTrotecESP::checksum() { - uint8_t sum = 0; - uint8_t i; - - for (i = 2; i < 8; i++) sum += trotec[i]; - - trotec[8] = sum & 0xFF; -} - -void IRTrotecESP::stateReset() { - for (uint8_t i = 2; i < TROTEC_COMMAND_LENGTH; i++) - trotec[i] = 0x0; - - trotec[0] = TROTEC_INTRO1; - trotec[1] = TROTEC_INTRO2; - - setPower(false); - setTemp(TROTEC_DEF_TEMP); - setSpeed(TROTEC_FAN_MED); - setMode(TROTEC_AUTO); -} - -uint8_t* IRTrotecESP::getRaw() { - checksum(); - return trotec; -} - -void IRTrotecESP::setPower(bool state) { - if (state) - trotec[2] |= (TROTEC_ON << 3); - else - trotec[2] &= ~(TROTEC_ON << 3); -} - -uint8_t IRTrotecESP::getPower() { - return trotec[2] & (TROTEC_ON << 3); -} - -void IRTrotecESP::setSpeed(uint8_t speed) { - trotec[2] = (trotec[2] & 0xcf) | (speed << 4); -} - -uint8_t IRTrotecESP::getSpeed() { - return trotec[2] & 0x30; -} - -void IRTrotecESP::setMode(uint8_t mode) { - trotec[2] = (trotec[2] & 0xfc) | mode; -} - -uint8_t IRTrotecESP::getMode() { - return trotec[2] & 0x03; -} - -void IRTrotecESP::setTemp(uint8_t temp) { - if (temp < TROTEC_MIN_TEMP) - temp = TROTEC_MIN_TEMP; - else if (temp > TROTEC_MAX_TEMP) - temp = TROTEC_MAX_TEMP; - - trotec[3] = (trotec[3] & 0x80) | (temp - TROTEC_MIN_TEMP); -} - -uint8_t IRTrotecESP::getTemp() { - return trotec[3] & 0x7f; -} - -void IRTrotecESP::setSleep(bool sleep) { - if (sleep) - trotec[3] |= (TROTEC_SLEEP_ON << 7); - else - trotec[3] &= ~(TROTEC_SLEEP_ON << 7); -} - -bool IRTrotecESP::getSleep(void) { - return trotec[3] & (TROTEC_SLEEP_ON << 7); -} - -void IRTrotecESP::setTimer(uint8_t timer) { - if (timer > TROTEC_MAX_TIMER) timer = TROTEC_MAX_TIMER; - - if (timer) { - trotec[5] |= (TROTEC_TIMER_ON << 6); - trotec[6] = timer; - } else { - trotec[5] &= ~(TROTEC_TIMER_ON << 6); - trotec[6] = 0; - } -} - -uint8_t IRTrotecESP::getTimer() { - return trotec[6]; -} - -#endif // SEND_TROTEC diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h deleted file mode 100644 index 01ac13c59..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2017 stufisher - -#ifndef IR_TROTEC_H_ -#define IR_TROTEC_H_ - -#include "IRremoteESP8266.h" -#include "IRsend.h" - -// Constants -// Byte 0 -#define TROTEC_INTRO1 0x12 - -// Byte 1 -#define TROTEC_INTRO2 0x34 - -// Byte 2 -#define TROTEC_AUTO 0 -#define TROTEC_COOL 1 -#define TROTEC_DRY 2 -#define TROTEC_FAN 3 - -#define TROTEC_ON 1 -#define TROTEC_OFF 0 - -#define TROTEC_FAN_LOW 1 -#define TROTEC_FAN_MED 2 -#define TROTEC_FAN_HIGH 3 - -// Byte 3 -#define TROTEC_MIN_TEMP 18 -#define TROTEC_MAX_TEMP 32 -#define TROTEC_DEF_TEMP 25 - -#define TROTEC_SLEEP_ON 1 - -// Byte 5 -#define TROTEC_TIMER_ON 1 - -// Byte 6 -#define TROTEC_MIN_TIMER 0 -#define TROTEC_MAX_TIMER 23 - -#if SEND_TROTEC - -class IRTrotecESP { - public: - explicit IRTrotecESP(uint16_t pin); - - void send(); - void begin(); - - void setPower(bool state); - uint8_t getPower(); - - void setTemp(uint8_t temp); - uint8_t getTemp(); - - void setSpeed(uint8_t fan); - uint8_t getSpeed(); - - uint8_t getMode(); - void setMode(uint8_t mode); - - bool getSleep(); - void setSleep(bool sleep); - - uint8_t getTimer(); - void setTimer(uint8_t timer); - - uint8_t* getRaw(); - - private: - uint8_t trotec[TROTEC_COMMAND_LENGTH]; - void stateReset(); - void checksum(); - IRsend _irsend; -}; -#endif - -#endif // IR_TROTEC_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp deleted file mode 100644 index 4efb2c570..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran - -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// W W H H Y Y N N TTTTT EEEEE RRRRR -// W W H H Y Y NN N T E R R -// W W W HHHHH Y N N N T EEE RRRR -// W W W H H Y N NN T E R R -// WWW H H Y N N T EEEEE R R - -// Whynter A/C ARC-110WD added by Francesco Meschia -// Whynter originally added from https://github.com/shirriff/Arduino-IRremote/ - -// Constants -#define WHYNTER_TICK 50U -#define WHYNTER_HDR_MARK_TICKS 57U -#define WHYNTER_HDR_MARK (WHYNTER_HDR_MARK_TICKS * WHYNTER_TICK) -#define WHYNTER_HDR_SPACE_TICKS 57U -#define WHYNTER_HDR_SPACE (WHYNTER_HDR_SPACE_TICKS * \ - WHYNTER_TICK) -#define WHYNTER_BIT_MARK_TICKS 15U -#define WHYNTER_BIT_MARK (WHYNTER_BIT_MARK_TICKS * WHYNTER_TICK) -#define WHYNTER_ONE_SPACE_TICKS 43U -#define WHYNTER_ONE_SPACE (WHYNTER_ONE_SPACE_TICKS * \ - WHYNTER_TICK) -#define WHYNTER_ZERO_SPACE_TICKS 15U -#define WHYNTER_ZERO_SPACE (WHYNTER_ZERO_SPACE_TICKS * \ - WHYNTER_TICK) -#define WHYNTER_MIN_COMMAND_LENGTH_TICKS 2160U // Completely made up value. -#define WHYNTER_MIN_COMMAND_LENGTH (WHYNTER_MIN_COMMAND_LENGTH_TICKS * \ - WHYNTER_TICK) -#define WHYNTER_MIN_GAP_TICKS (WHYNTER_MIN_COMMAND_LENGTH_TICKS - \ - (2 * (WHYNTER_BIT_MARK_TICKS + WHYNTER_ZERO_SPACE_TICKS) + \ - WHYNTER_BITS * (WHYNTER_BIT_MARK_TICKS + WHYNTER_ONE_SPACE_TICKS))) -#define WHYNTER_MIN_GAP (WHYNTER_MIN_GAP_TICKS * WHYNTER_TICK) - -#if SEND_WHYNTER -// Send a Whynter message. -// -// Args: -// data: message to be sent. -// nbits: Nr. of bits of the message to be sent. -// repeat: Nr. of additional times the message is to be sent. -// -// Status: STABLE -// -// Ref: -// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp -void IRsend::sendWhynter(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set IR carrier frequency - enableIROut(38); - IRtimer usecTimer = IRtimer(); - - for (uint16_t i = 0; i <= repeat; i++) { - usecTimer.reset(); - // Header - mark(WHYNTER_BIT_MARK); - space(WHYNTER_ZERO_SPACE); - mark(WHYNTER_HDR_MARK); - space(WHYNTER_HDR_SPACE); - // Data - sendData(WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, - WHYNTER_ZERO_SPACE, data, nbits, true); - // Footer - mark(WHYNTER_BIT_MARK); - space(std::max(WHYNTER_MIN_COMMAND_LENGTH - usecTimer.elapsed(), - WHYNTER_MIN_GAP)); - } -} -#endif - -#if DECODE_WHYNTER -// Decode the supplied Whynter message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA Strict mode is ALPHA. -// -// Ref: -// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp -bool IRrecv::decodeWhynter(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + 2 * HEADER + FOOTER - 1) - return false; // We don't have enough entries to possibly match. - - // Compliance - if (strict && nbits != WHYNTER_BITS) - return false; // Incorrect nr. of bits per spec. - - uint16_t offset = OFFSET_START; - - // Header - // Sequence begins with a bit mark and a zero space. - // These are typically small, so we'll prefer to do the calibration - // on the much larger header mark & space that are next. - if (!matchMark(results->rawbuf[offset++], WHYNTER_BIT_MARK)) return false; - if (!matchSpace(results->rawbuf[offset++], WHYNTER_ZERO_SPACE)) return false; - // Main header mark and space - if (!matchMark(results->rawbuf[offset], WHYNTER_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - WHYNTER_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], WHYNTER_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - WHYNTER_HDR_SPACE_TICKS; - - // Data - uint64_t data = 0; - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - WHYNTER_BIT_MARK_TICKS * m_tick, - WHYNTER_ONE_SPACE_TICKS * s_tick, - WHYNTER_BIT_MARK_TICKS * m_tick, - WHYNTER_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - - // Footer - if (!matchMark(results->rawbuf[offset++], WHYNTER_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], WHYNTER_MIN_GAP_TICKS * s_tick)) - return false; - - // Success - results->decode_type = WHYNTER; - results->bits = nbits; - results->value = data; - results->address = 0; - results->command = 0; - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp deleted file mode 100644 index 3b18ae582..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend_test.h" -#include "IRsend.h" -#include "gtest/gtest.h" - -// Tests sendData(). - -// Test sending zero bits. -TEST(TestSendData, SendZeroBits) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1, 0, true); - EXPECT_EQ("", irsend.outputStr()); -} - -// Test sending zero and one. -TEST(TestSendData, SendSingleBit) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1, 1, true); - EXPECT_EQ("m1s2", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b0, 1, true); - EXPECT_EQ("m3s4", irsend.outputStr()); -} - -// Test sending bit order. -TEST(TestSendData, TestingBitSendOrder) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b10, 2, true); - EXPECT_EQ("m1s2m3s4", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b10, 2, false); - EXPECT_EQ("m3s4m1s2", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b0001, 4, false); - EXPECT_EQ("m1s2m3s4m3s4m3s4", irsend.outputStr()); -} - -// Test sending typical data. -TEST(TestSendData, SendTypicalData) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1010110011110000, 16, true); - EXPECT_EQ("m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4m3s4", - irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0x1234567890ABCDEF, 64, true); - EXPECT_EQ("m3s4m3s4m3s4m1s2m3s4m3s4m1s2m3s4m3s4m3s4m1s2m1s2m3s4m1s2m3s4m3s4" - "m3s4m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4" - "m1s2m3s4m3s4m1s2m3s4m3s4m3s4m3s4m1s2m3s4m1s2m3s4m1s2m3s4m1s2m1s2" - "m1s2m1s2m3s4m3s4m1s2m1s2m3s4m1s2m1s2m1s2m1s2m3s4m1s2m1s2m1s2m1s2", - irsend.outputStr()); -} - -// Test sending more than expected bits. -TEST(TestSendData, SendOverLargeData) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0xFFFFFFFFFFFFFFFF, 70, true); - EXPECT_EQ("m3s4m3s4m3s4m3s4m3s4m3s4" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2", - irsend.outputStr()); -} - -// Test inverting the output. -TEST(TestIRSend, InvertedOutput) { - IRsendTest irsend(4, true); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1, 1, true); - EXPECT_EQ("s1m2", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b0, 1, true); - EXPECT_EQ("s3m4", irsend.outputStr()); -} - -// Test typical use of sendRaw(). -TEST(TestSendRaw, GeneralUse) { - IRsendTest irsend(4); - IRrecv irrecv(0); - - irsend.begin(); - // NEC C3E0E0E8 as measured in #204 - uint16_t rawData[67] = {8950, 4500, 550, 1650, 600, 1650, 550, 550, 600, 500, - 600, 550, 550, 550, 600, 1650, 550, 1650, 600, 1650, - 600, 1650, 550, 1700, 550, 550, 600, 550, 550, 550, - 600, 500, 600, 550, 550, 1650, 600, 1650, 600, 1650, - 550, 550, 600, 500, 600, 500, 600, 550, 550, 550, - 600, 1650, 550, 1650, 600, 1650, 600, 500, 650, 1600, - 600, 500, 600, 550, 550, 550, 600}; - - irsend.sendRaw(rawData, 67, 38); - EXPECT_EQ( - "m8950s4500" - "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" - "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" - "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" - "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" - "m600", irsend.outputStr()); - - irsend.reset(); - irsend.sendRaw(rawData, 67, 38); - irsend.makeDecodeResult(); - EXPECT_EQ( - "m8950s4500" - "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" - "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" - "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" - "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" - "m600", irsend.outputStr()); - ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, NEC_BITS, false)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(32, irsend.capture.bits); - EXPECT_EQ(0xC3E0E0E8, irsend.capture.value); -} - -// Incorrect handling of decodes from Raw. i.e. There is no gap recorded at -// the end of a command when using the interrupt code. sendRaw() best emulates -// this for unit testing purposes. sendGC() and sendXXX() will add the trailing -// gap. Users won't see this in normal use. -TEST(TestSendRaw, NoTrailingGap) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - uint16_t rawData[67] = {9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, - 600, 1650, 650, 550, 600, 1650, 650, 1650, 650, 1650, - 600, 550, 650, 1650, 650, 1650, 650, 550, 600, 1650, - 650, 1650, 650, 550, 650, 550, 650, 1650, 650, 550, - 650, 550, 650, 550, 600, 550, 650, 550, 650, 550, - 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, - 650, 1650, 650, 1650, 650, 1650, 600}; - irsend.sendRaw(rawData, 67, 38); - irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h b/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h deleted file mode 100644 index 94de487af..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2017 David Conran - -#ifndef TEST_IRSEND_TEST_H_ -#define TEST_IRSEND_TEST_H_ - -#define __STDC_LIMIT_MACROS -#include -#include -#include -#include -#include "IRrecv.h" -#include "IRsend.h" - -#define OUTPUT_BUF 1000U -#define RAW_BUF 1000U -class IRsendTest: public IRsend { - public: - uint32_t output[OUTPUT_BUF]; - uint16_t last; - uint16_t rawbuf[RAW_BUF]; - decode_results capture; - - explicit IRsendTest(uint16_t x, bool i = false) : IRsend(x, i) { - reset(); - } - - void reset() { - last = 0; - output[last] = 0; - } - - std::string outputStr() { - std::stringstream result; - if (last == 0 && output[0] == 0) - return ""; - for (uint16_t i = 0; i <= last; i++) { - if ((i & 1) != outputOff ) // Odd XOR outputOff - result << "s"; - else - result << "m"; - result << output[i]; - } - reset(); - return result.str(); - } - - void makeDecodeResult(uint16_t offset = 0) { - capture.decode_type = UNKNOWN; - capture.bits = 0; - capture.rawlen = last + 1 - offset; - capture.overflow = (last - offset >= (int16_t) RAW_BUF); - capture.repeat = false; - capture.address = 0; - capture.command = 0; - capture.value = 0; - capture.rawbuf = rawbuf; - for (uint16_t i = 0; - (i < RAW_BUF - 1) && (offset < OUTPUT_BUF); - i++, offset++) - if (output[offset] / RAWTICK > UINT16_MAX) - rawbuf[i + 1] = UINT16_MAX; - else - rawbuf[i + 1] = output[offset] / RAWTICK; - } - - void dumpRawResult() { - std::cout << std::dec; - if (capture.rawlen == 0) return; - std::cout << "uint16_t rawbuf["<< capture.rawlen - 1 << "] = {"; - for (uint16_t i = 1; i < capture.rawlen; i++) { - if (i % 8 == 1) - std::cout << std::endl << " "; - std::cout << (capture.rawbuf[i] * RAWTICK); - // std::cout << "(" << capture.rawbuf[i] << ")"; - if (i < capture.rawlen - 1) - std::cout << ", "; - } - std::cout << "};" << std::endl; - } - - void addGap(uint32_t usecs) { - space(usecs); - } - - protected: - uint16_t mark(uint16_t usec) { - if (last >= OUTPUT_BUF) - return 0; - if (last & 1) // Is odd? (i.e. last call was a space()) - output[++last] = usec; - else - output[last] += usec; - return 0; - } - - void space(uint32_t time) { - if (last >= OUTPUT_BUF) - return; - if (last & 1) { // Is odd? (i.e. last call was a space()) - output[last] += time; - } else { - output[++last] = time; - } - } -}; -#endif // TEST_IRSEND_TEST_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp deleted file mode 100644 index 3b4c4145a..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRutils.h" -#include -#include "gtest/gtest.h" - -// Tests reverseBits(). - -// Tests reverseBits for typical use. -TEST(ReverseBitsTest, TypicalUse) { - EXPECT_EQ(0xF, reverseBits(0xF0, 8)); - EXPECT_EQ(0xFFFF, reverseBits(0xFFFF0000, 32)); - EXPECT_EQ(0x555500005555FFFF, reverseBits(0xFFFFAAAA0000AAAA, 64)); - EXPECT_EQ(0, reverseBits(0, 64)); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, reverseBits(0xFFFFFFFFFFFFFFFF, 64)); -} - -// Tests reverseBits for bit size values <= 1 -TEST(ReverseBitsTest, LessThanTwoBitsReversed) { - EXPECT_EQ(0x12345678, reverseBits(0x12345678, 1)); - EXPECT_EQ(1234, reverseBits(1234, 0)); -} - -// Tests reverseBits for bit size larger than a uint64_t. -TEST(ReverseBitsTest, LargerThan64BitsReversed) { - EXPECT_EQ(0, reverseBits(0, 65)); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, reverseBits(0xFFFFFFFFFFFFFFFF, 100)); - EXPECT_EQ(0x555500005555FFFF, reverseBits(0xFFFFAAAA0000AAAA, 3000)); -} - -// Tests reverseBits for bit sizes less than all the data stored. -TEST(ReverseBitsTest, LessBitsReversedThanInputHasSet) { - EXPECT_EQ(0xF8, reverseBits(0xF1, 4)); - EXPECT_EQ(0xF5, reverseBits(0xFA, 4)); - EXPECT_EQ(0x12345678FFFF0000, reverseBits(0x123456780000FFFF, 32)); -} - -// Tests for uint64ToString() - -TEST(TestUint64ToString, TrivialCases) { - EXPECT_EQ("0", uint64ToString(0)); // Default base (10) - EXPECT_EQ("0", uint64ToString(0, 2)); // Base-2 - EXPECT_EQ("0", uint64ToString(0, 8)); // Base-8 - EXPECT_EQ("0", uint64ToString(0, 10)); // Base-10 - EXPECT_EQ("0", uint64ToString(0, 16)); // Base-16 - - EXPECT_EQ("1", uint64ToString(1, 2)); // Base-2 - EXPECT_EQ("2", uint64ToString(2, 8)); // Base-8 - EXPECT_EQ("3", uint64ToString(3, 10)); // Base-10 - EXPECT_EQ("4", uint64ToString(4, 16)); // Base-16 -} - -TEST(TestUint64ToString, NormalUse) { - EXPECT_EQ("12345", uint64ToString(12345)); - EXPECT_EQ("100", uint64ToString(4, 2)); - EXPECT_EQ("3039", uint64ToString(12345, 16)); - EXPECT_EQ("123456", uint64ToString(123456)); - EXPECT_EQ("1E240", uint64ToString(123456, 16)); - EXPECT_EQ("FEEDDEADBEEF", uint64ToString(0xfeeddeadbeef, 16)); -} - -TEST(TestUint64ToString, Max64Bit) { - EXPECT_EQ("18446744073709551615", uint64ToString(UINT64_MAX)); // Default - EXPECT_EQ("1111111111111111111111111111111111111111111111111111111111111111", - uint64ToString(UINT64_MAX, 2)); // Base-2 - EXPECT_EQ("1777777777777777777777", uint64ToString(UINT64_MAX, 8)); // Base-8 - EXPECT_EQ("18446744073709551615", uint64ToString(UINT64_MAX, 10)); // Base-10 - EXPECT_EQ("FFFFFFFFFFFFFFFF", uint64ToString(UINT64_MAX, 16)); // Base-16 -} - -TEST(TestUint64ToString, Max32Bit) { - EXPECT_EQ("4294967295", uint64ToString(UINT32_MAX)); // Default - EXPECT_EQ("37777777777", uint64ToString(UINT32_MAX, 8)); // Base-8 - EXPECT_EQ("4294967295", uint64ToString(UINT32_MAX, 10)); // Base-10 - EXPECT_EQ("FFFFFFFF", uint64ToString(UINT32_MAX, 16)); // Base-16 -} - -TEST(TestUint64ToString, InterestingCases) { - // Previous hacky-code didn't handle leading zeros in the lower 32 bits. - EXPECT_EQ("100000000", uint64ToString(0x100000000, 16)); - EXPECT_EQ("100000001", uint64ToString(0x100000001, 16)); -} - -TEST(TestUint64ToString, SillyBases) { - // If we are given a silly base, we should defer to Base-10. - EXPECT_EQ("12345", uint64ToString(12345, 0)); // Super silly, makes no sense. - EXPECT_EQ("12345", uint64ToString(12345, 1)); // We don't do unary. - EXPECT_EQ("12345", uint64ToString(12345, 100)); // We can't print base-100. - EXPECT_EQ("12345", uint64ToString(12345, 37)); // Base-37 is one to far. - EXPECT_EQ("9IX", uint64ToString(12345, 36)); // But we *can* do base-36. -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp deleted file mode 100644 index b516008c1..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "ir_Daikin.h" -#include "gtest/gtest.h" - -// Tests for sendDaikin(). - -// Test sending typical data only. -TEST(TestSendDaikin, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t daikin_code[DAIKIN_COMMAND_LENGTH] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, - 0x11, 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, - 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; - - irsend.reset(); - irsend.sendDaikin(daikin_code); - EXPECT_EQ( - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428", irsend.outputStr()); -} - -// Test sending with repeats. -TEST(TestSendDaikin, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - uint8_t daikin_code[DAIKIN_COMMAND_LENGTH] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, - 0x11, 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, - 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; - irsend.reset(); - - irsend.sendDaikin(daikin_code, DAIKIN_COMMAND_LENGTH, 1); - EXPECT_EQ( - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428", irsend.outputStr()); -} - -// Test sending atypical sizes. -TEST(TestSendDaikin, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t daikin_short_code[DAIKIN_COMMAND_LENGTH - 1] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, - 0x11, 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, - 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00}; - - irsend.reset(); - irsend.sendDaikin(daikin_short_code, DAIKIN_COMMAND_LENGTH - 1); - ASSERT_EQ("", irsend.outputStr()); - - uint8_t daikin_long_code[DAIKIN_COMMAND_LENGTH + 1] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, - 0x11, 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, - 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3, 0x11}; - irsend.reset(); - irsend.sendDaikin(daikin_long_code, DAIKIN_COMMAND_LENGTH + 1); - ASSERT_EQ( - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s29428", irsend.outputStr()); -} - -// Tests for IRDaikinESP class. - -TEST(TestDaikinClass, Power) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.on(); - EXPECT_TRUE(irdaikin.getPower()); - - irdaikin.off(); - EXPECT_FALSE(irdaikin.getPower()); - - irdaikin.setPower(true); - EXPECT_TRUE(irdaikin.getPower()); - - irdaikin.setPower(false); - EXPECT_FALSE(irdaikin.getPower()); -} - -TEST(TestDaikinClass, Temperature) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setTemp(0); - EXPECT_EQ(DAIKIN_MIN_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(255); - EXPECT_EQ(DAIKIN_MAX_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MIN_TEMP); - EXPECT_EQ(DAIKIN_MIN_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MAX_TEMP); - EXPECT_EQ(DAIKIN_MAX_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MIN_TEMP - 1); - EXPECT_EQ(DAIKIN_MIN_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MAX_TEMP + 1); - EXPECT_EQ(DAIKIN_MAX_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MIN_TEMP + 1); - EXPECT_EQ(DAIKIN_MIN_TEMP + 1, irdaikin.getTemp()); - - irdaikin.setTemp(21); - EXPECT_EQ(21, irdaikin.getTemp()); - - irdaikin.setTemp(25); - EXPECT_EQ(25, irdaikin.getTemp()); - - irdaikin.setTemp(29); - EXPECT_EQ(29, irdaikin.getTemp()); -} - -TEST(TestDaikinClass, OperatingMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setMode(DAIKIN_AUTO); - EXPECT_EQ(DAIKIN_AUTO, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_COOL); - EXPECT_EQ(DAIKIN_COOL, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_HEAT); - EXPECT_EQ(DAIKIN_HEAT, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_DRY); - EXPECT_EQ(DAIKIN_DRY, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_FAN); - EXPECT_EQ(DAIKIN_FAN, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_FAN + 1); - EXPECT_EQ(DAIKIN_AUTO, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_AUTO + 1); - EXPECT_EQ(DAIKIN_AUTO, irdaikin.getMode()); - - irdaikin.setMode(255); - EXPECT_EQ(DAIKIN_AUTO, irdaikin.getMode()); -} - -TEST(TestDaikinClass, VaneSwing) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setSwingHorizontal(true); - irdaikin.setSwingVertical(false); - - irdaikin.setSwingHorizontal(true); - EXPECT_TRUE(irdaikin.getSwingHorizontal()); - EXPECT_FALSE(irdaikin.getSwingVertical()); - - irdaikin.setSwingVertical(true); - EXPECT_TRUE(irdaikin.getSwingHorizontal()); - EXPECT_TRUE(irdaikin.getSwingVertical()); - - irdaikin.setSwingHorizontal(false); - EXPECT_FALSE(irdaikin.getSwingHorizontal()); - EXPECT_TRUE(irdaikin.getSwingVertical()); - - irdaikin.setSwingVertical(false); - EXPECT_FALSE(irdaikin.getSwingHorizontal()); - EXPECT_FALSE(irdaikin.getSwingVertical()); -} - -TEST(TestDaikinClass, QuietMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setQuiet(true); - EXPECT_TRUE(irdaikin.getQuiet()); - - irdaikin.setQuiet(false); - EXPECT_FALSE(irdaikin.getQuiet()); - - irdaikin.setQuiet(true); - EXPECT_TRUE(irdaikin.getQuiet()); - - irdaikin.setPowerful(true); - EXPECT_FALSE(irdaikin.getQuiet()); -} - -TEST(TestDaikinClass, PowerfulMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setPowerful(true); - EXPECT_TRUE(irdaikin.getPowerful()); - - irdaikin.setPowerful(false); - EXPECT_FALSE(irdaikin.getPowerful()); - - irdaikin.setPowerful(true); - EXPECT_TRUE(irdaikin.getPowerful()); - - irdaikin.setQuiet(true); - EXPECT_FALSE(irdaikin.getPowerful()); -} - -TEST(TestDaikinClass, FanSpeed) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setFan(0); - EXPECT_EQ(0, irdaikin.getFan()); - - irdaikin.setFan(255); - EXPECT_EQ(DAIKIN_FAN_MAX, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MAX); - EXPECT_EQ(DAIKIN_FAN_MAX, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MAX + 1); - EXPECT_EQ(DAIKIN_FAN_MAX, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MAX - 1); - EXPECT_EQ(DAIKIN_FAN_MAX - 1, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MIN); - EXPECT_EQ(DAIKIN_FAN_MIN, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MIN + 1); - EXPECT_EQ(DAIKIN_FAN_MIN + 1, irdaikin.getFan()); - - irdaikin.setFan(3); - EXPECT_EQ(3, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_AUTO); - EXPECT_EQ(DAIKIN_FAN_AUTO, irdaikin.getFan()); -} - -TEST(TestDaikinClass, MessageConstuction) { - IRDaikinESP irdaikin(0); - IRsendTest irsend(4); - irdaikin.begin(); - irsend.begin(); - - irdaikin.setFan(DAIKIN_FAN_MIN); - irdaikin.setMode(DAIKIN_COOL); - irdaikin.setTemp(27); - irdaikin.setSwingVertical(false); - irdaikin.setSwingHorizontal(true); - irdaikin.setQuiet(false); - irdaikin.setPower(true); - - // Check everything for kicks. - EXPECT_EQ(DAIKIN_FAN_MIN, irdaikin.getFan()); - EXPECT_EQ(DAIKIN_COOL, irdaikin.getMode()); - EXPECT_EQ(27, irdaikin.getTemp()); - EXPECT_FALSE(irdaikin.getSwingVertical()); - EXPECT_TRUE(irdaikin.getSwingHorizontal()); - EXPECT_FALSE(irdaikin.getQuiet()); - EXPECT_TRUE(irdaikin.getPower()); - - irsend.reset(); - irsend.sendDaikin(irdaikin.getRaw()); - EXPECT_EQ( - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s428m428s428" - "m428s428m428s1280m428s1280m428s428m428s1280m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s428" - "m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280m428s428" - "m428s29428", irsend.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp deleted file mode 100644 index f1b6c04f6..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2017 Jonny Graham - -#include "IRsend.h" -#include "IRsend_test.h" -#include "ir_Fujitsu.h" -#include "gtest/gtest.h" - -template -::testing::AssertionResult ArraysMatch(const T (&expected)[size], - const T* actual) { - for (size_t i(0); i < size; ++i) { - if (expected[i] != actual[i]) { - int e = expected[i]; - int a = actual[i]; - return ::testing::AssertionFailure() << "array[" << i - << "] (" << std::hex << a << std::dec << ") != expected[" << i - << "] (" << std::hex << e << std::dec << ")"; - } - } - - return ::testing::AssertionSuccess(); -} -// Tests for Mitsubishi A/C methods. - -// Test sending typical data only. -TEST(TestSendFujitsuAC, GetRawDefault) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.setCmd(FUJITSU_AC_CMD_TURN_ON); - fujitsuACSender.setSwing(FUJITSU_AC_SWING_BOTH); - fujitsuACSender.setMode(FUJITSU_AC_MODE_COOL); - fujitsuACSender.setFanSpeed(FUJITSU_AC_FAN_HIGH); - fujitsuACSender.setTemp(24); - uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, - 0x81, 0x1, 0x31, 0x0, 0x0, 0x0, 0x20, 0xFD}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} - -TEST(TestSendFujitsuAC, GetRawTurnOff) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.off(); - uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} -TEST(TestSendFujitsuAC, GetRawStepHoriz) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.stepHoriz(); - uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x79, 0x86}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} -TEST(TestSendFujitsuAC, GetRawStepVert) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.stepVert(); - uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C, 0x93}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} - -TEST(TestSendFujitsuAC, GetRawWithSwingHoriz) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.setCmd(FUJITSU_AC_CMD_STAY_ON); - fujitsuACSender.setSwing(FUJITSU_AC_SWING_HORIZ); - fujitsuACSender.setMode(FUJITSU_AC_MODE_COOL); - fujitsuACSender.setFanSpeed(FUJITSU_AC_FAN_QUIET); - fujitsuACSender.setTemp(25); - uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, - 0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} - -TEST(TestSendFujitsuAC, GetRawWithFan) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.setCmd(FUJITSU_AC_CMD_STAY_ON); - fujitsuACSender.setSwing(FUJITSU_AC_SWING_HORIZ); - fujitsuACSender.setMode(FUJITSU_AC_MODE_FAN); - fujitsuACSender.setFanSpeed(FUJITSU_AC_FAN_MED); - fujitsuACSender.setTemp(20); // temp doesn't matter for fan - // but it is sent by the RC anyway - uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, - 0x40, 0x3, 0x22, 0x0, 0x0, 0x0, 0x20, 0x4B}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} - -TEST(TestSendFujitsuAC, GenerateMessage) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - IRsendTest irsend(4); - fujitsuACSender.begin(); - irsend.begin(); - - fujitsuACSender.setCmd(FUJITSU_AC_CMD_STAY_ON); - fujitsuACSender.setSwing(FUJITSU_AC_SWING_BOTH); - fujitsuACSender.setMode(FUJITSU_AC_MODE_COOL); - fujitsuACSender.setFanSpeed(FUJITSU_AC_FAN_HIGH); - fujitsuACSender.setTemp(24); - - EXPECT_EQ(FUJITSU_AC_FAN_HIGH, fujitsuACSender.getFanSpeed()); - EXPECT_EQ(FUJITSU_AC_MODE_COOL, fujitsuACSender.getMode()); - EXPECT_EQ(24, fujitsuACSender.getTemp()); - EXPECT_EQ(FUJITSU_AC_SWING_BOTH, fujitsuACSender.getSwing()); - EXPECT_EQ(FUJITSU_AC_CMD_STAY_ON, fujitsuACSender.getCmd()); - - irsend.reset(); - irsend.sendFujitsuAC(fujitsuACSender.getRaw(), FUJITSU_AC_STATE_LENGTH); - EXPECT_EQ( - "m3224s1574m448s367m448s367m448s1182m448s367m448s1182m448s367m448s367m448" - "s367m448s1182m448s1182m448s367m448s367m448s367m448s1182m448s1182m448s367" - "m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s1182m448s367m448s367m448s367m448s367m448s1182" - "m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s367" - "m448s367m448s1182m448s367m448s367m448s367m448s367m448s367m448s367m448s367" - "m448s367m448s1182m448s1182m448s367m448s367m448s367m448s367m448s367m448s367" - "m448s367m448s367m448s367m448s1182m448s1182m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367m448s1182m448" - "s1182m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367m448" - "s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s8100", - irsend.outputStr()); -} -TEST(TestSendFujitsuAC, GenerateShortMessage) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - IRsendTest irsend(4); - fujitsuACSender.begin(); - irsend.begin(); - - fujitsuACSender.off(); - - EXPECT_EQ(FUJITSU_AC_CMD_TURN_OFF, fujitsuACSender.getCmd()); - - irsend.reset(); - irsend.sendFujitsuAC(fujitsuACSender.getRaw(), FUJITSU_AC_STATE_LENGTH_SHORT); - EXPECT_EQ( - "m3224s1574m448s367m448s367m448s1182m448s367m448s1182m448s367m448s367m448" - "s367m448s1182m448s1182m448s367m448s367m448s367m448s1182m448s1182m448s367" - "m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367" - "m448s367m448s367m448s367m448s1182m448s367m448s367m448s367m448s367m448s367" - "m448s367m448s367m448s1182m448s367m448s367m448s367m448s367m448s1182m448s367" - "m448s367m448s367m448s367m448s367m448s367m448s1182m448s367m448s1182m448" - "s1182m448s1182m448s1182m448s1182m448s1182m448s8100", - irsend.outputStr()); -} - -// Issue #275 -TEST(TestSendFujitsuAC, Issue275) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - IRsendTest irsend(4); - fujitsuACSender.begin(); - irsend.begin(); - irsend.reset(); - - fujitsuACSender.setCmd(FUJITSU_AC_CMD_TURN_OFF); - irsend.sendFujitsuAC(fujitsuACSender.getRaw(), FUJITSU_AC_STATE_LENGTH_SHORT); - EXPECT_EQ( - // Header - "m3224s1574" - // 0 0 1 0 1 0 0 0 (0x28) - "m448s367m448s367m448s1182m448s367m448s1182m448s367m448s367m448s367" - // 1 1 0 0 0 1 1 0 (0xC6) - "m448s1182m448s1182m448s367m448s367m448s367m448s1182m448s1182m448s367" - // 0 0 0 0 0 0 0 0 (0x00) - "m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367" - // 0 0 0 0 1 0 0 0 (0x08) - "m448s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367" - // 0 0 0 0 1 0 0 0 (0x08) - "m448s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367" - // 0 1 0 0 0 0 0 0 (0x40) - "m448s367m448s1182m448s367m448s367m448s367m448s367m448s367m448s367" - // 1 0 1 1 1 1 1 1 (0xBF) - "m448s1182m448s367m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" - // Footer - "m448s8100", irsend.outputStr()); - - irsend.reset(); - // Per report in Issue #275 - uint16_t off[115] = { - 3350, 1650, - 450, 400, 450, 450, 450, 1250, 450, 400, 450, 1250, 450, 400, 450, 400, - 450, 400, 450, 1250, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 1250, - 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, - 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, - 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, - 450, 400, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250, - 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250, - 450, 400, 450, 1250, 450, 1250, 450, 1250, 450, 1250, 450, 1250, - 450, 1250, 450}; - irsend.sendRaw(off, 115, 38); - EXPECT_EQ( - // Header - "m3350s1650" - // 0 0 1 0 1 0 0 0 (0x28) - "m450s400m450s450m450s1250m450s400m450s1250m450s400m450s400m450s400" - // 1 1 0 0 0 1 1 0 (0xC6) - "m450s1250m450s1250m450s400m450s400m450s400m450s1250m450s1250m450s400" - // 0 0 0 0 0 0 0 0 (0x00) - "m450s400m450s400m450s400m450s400m450s400m450s400m450s400m450s400" - // 0 0 0 0 1 0 0 0 (0x08) - "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400" - // 0 0 0 0 1 0 0 0 (0x08) - "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400" - // 0 1 0 0 0 0 0 0 (0x40) - "m450s400m450s1250m450s400m450s400m450s400m450s400m450s400m450s400" - // 1 0 1 1 1 1 1 1 (0xBF) - "m450s1250m450s400m450s1250m450s1250m450s1250m450s1250m450s1250m450s1250" - // Footer - "m450", - irsend.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp deleted file mode 100644 index c2e9762a2..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendGlobalCache(). - -// Test sending a typical command wihtout a repeat. -TEST(TestSendGlobalCache, NonRepeatingCode) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - irsend.reset(); - - // Modified NEC TV "Power On" from Global Cache with no repeats - uint16_t gc_test[71] = {38000, 1, 1, 342, 172, 21, 22, 21, 21, 21, 65, 21, 21, - 21, 22, 21, 22, 21, 21, 21, 22, 21, 65, 21, 65, 21, - 22, 21, 65, 21, 65, 21, 65, 21, 65, 21, 65, 21, 65, - 21, 22, 21, 22, 21, 21, 21, 22, 21, 22, 21, 65, 21, - 22, 21, 21, 21, 65, 21, 65, 21, 65, 21, 64, 22, 65, - 21, 22, 21, 65, 21, 1519}; - irsend.sendGC(gc_test, 71); - irsend.makeDecodeResult(); - EXPECT_EQ("m8892s4472m546s572m546s546m546s1690m546s546m546s572m546s572" - "m546s546m546s572m546s1690m546s1690m546s572m546s1690m546s1690" - "m546s1690m546s1690m546s1690m546s1690m546s572m546s572m546s546" - "m546s572m546s572m546s1690m546s572m546s546m546s1690m546s1690" - "m546s1690m546s1664m572s1690m546s572m546s1690m546s39494", - irsend.outputStr()); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0x20DF827D, irsend.capture.value); - EXPECT_EQ(0x4, irsend.capture.address); - EXPECT_EQ(0x41, irsend.capture.command); -} - -// Test sending typical command with repeats. -TEST(TestSendGlobalCache, RepeatCode) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - irsend.reset(); - - // Sherwood (NEC-like) "Power On" from Global Cache with 2 repeats - uint16_t gc_test[75] = {38000, 2, 69, 341, 171, 21, 64, 21, 64, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 64, 21, 21, - 21, 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, 21, - 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 64, 21, 64, 21, 64, 21, 21, 21, - 64, 21, 64, 21, 64, 21, 1600, 341, 85, 21, 3647}; - irsend.sendGC(gc_test, 75); - irsend.makeDecodeResult(); - EXPECT_EQ("m8866s4446m546s1664m546s1664m546s546m546s546m546s546m546s546" - "m546s546m546s1664m546s1664m546s546m546s1664m546s546m546s546" - "m546s546m546s1664m546s546m546s1664m546s546m546s546m546s546" - "m546s1664m546s546m546s546m546s546m546s546m546s1664m546s1664" - "m546s1664m546s546m546s1664m546s1664m546s1664m546s41600" - "m8866s2210m546s94822" - "m8866s2210m546s94822", irsend.outputStr()); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0xC1A28877, irsend.capture.value); - EXPECT_EQ(0x4583, irsend.capture.address); - EXPECT_EQ(0x11, irsend.capture.command); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp deleted file mode 100644 index 80a3dec1d..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendGree(). - -// Test sending typical data only. -TEST(TestSendGreeChars, SendData) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t gree_code[GREE_STATE_LENGTH] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}; - irsend.reset(); - irsend.sendGree(gree_code); - EXPECT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000", irsend.outputStr()); -} - -TEST(TestSendGreeUint64, SendData) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendGree(0x1234567890ABCDEF); - EXPECT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000", irsend.outputStr()); -} - -// Test sending with repeats. -TEST(TestSendGreeChars, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - uint8_t gree_code[GREE_STATE_LENGTH] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}; - irsend.reset(); - - irsend.sendGree(gree_code, GREE_STATE_LENGTH, 1); - EXPECT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000" - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000", irsend.outputStr()); -} - -TEST(TestSendGreeUint64, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendGree(0x1234567890ABCDEF, GREE_BITS, 1); - EXPECT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000" - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000", irsend.outputStr()); -} - -// Test sending atypical sizes. -TEST(TestSendGreeChars, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t gree_short_code[GREE_STATE_LENGTH - 1] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD}; - uint8_t gree_long_code[GREE_STATE_LENGTH + 1] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12}; - irsend.reset(); - irsend.sendGree(gree_short_code, GREE_STATE_LENGTH - 1); - ASSERT_EQ("", irsend.outputStr()); - - irsend.reset(); - irsend.sendGree(gree_long_code, GREE_STATE_LENGTH + 1); - ASSERT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s19000", irsend.outputStr()); -} - -TEST(TestSendGreeUint64, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendGree(0x1234567890ABCDEF, GREE_BITS - 1); - ASSERT_EQ("", irsend.outputStr()); - - irsend.reset(); - irsend.sendGree(0x1234567890ABCDEF, GREE_BITS + 1); - ASSERT_EQ("", irsend.outputStr()); -} - -TEST(TestSendGree, CompareUint64ToCharResults) { - IRsendTest irsend_chars(4); - IRsendTest irsend_uint64(0); - - uint8_t gree_code[GREE_STATE_LENGTH] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}; - - irsend_chars.begin(); - irsend_uint64.begin(); - - irsend_chars.reset(); - irsend_uint64.reset(); - irsend_chars.sendGree(gree_code); - irsend_uint64.sendGree(0x1234567890ABCDEF); - ASSERT_EQ(irsend_chars.outputStr(), irsend_uint64.outputStr()); - - uint8_t gree_zero_code[GREE_STATE_LENGTH] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - irsend_chars.reset(); - irsend_uint64.reset(); - irsend_chars.sendGree(gree_zero_code); - irsend_uint64.sendGree((uint64_t) 0x0); - ASSERT_EQ(irsend_chars.outputStr(), irsend_uint64.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp deleted file mode 100644 index c409c20ba..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "ir_Kelvinator.h" -#include "gtest/gtest.h" - -// Tests for sendKelvinator(). - -// Test sending typical data only. -TEST(TestSendKelvinator, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t kelv_code[KELVINATOR_STATE_LENGTH] = { - 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, - 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; - irsend.reset(); - irsend.sendKelvinator(kelv_code); - EXPECT_EQ( - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900", irsend.outputStr()); -} - -// Test sending with repeats. -TEST(TestSendKelvinator, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - uint8_t kelv_code[KELVINATOR_STATE_LENGTH] = { - 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, - 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; - irsend.reset(); - - irsend.sendKelvinator(kelv_code, KELVINATOR_STATE_LENGTH, 1); - EXPECT_EQ( - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900", irsend.outputStr()); -} - -// Test sending atypical sizes. -TEST(TestSendKelvinator, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t kelv_short_code[15] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, - 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10}; - uint8_t kelv_long_code[17] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, - 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0, - 0x00}; - irsend.reset(); - irsend.sendKelvinator(kelv_short_code, 15); - ASSERT_EQ("", irsend.outputStr()); - - irsend.reset(); - // Shouldn't be different from the SendDataOnly. We just don't send the - // extra data. - irsend.sendKelvinator(kelv_long_code, 17); - ASSERT_EQ( - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900", irsend.outputStr()); -} - - -// Tests for IRKelvinatorAC class. - -TEST(TestKelvinatorClass, Power) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.on(); - EXPECT_TRUE(irkelv.getPower()); - - irkelv.off(); - EXPECT_FALSE(irkelv.getPower()); - - irkelv.setPower(true); - EXPECT_TRUE(irkelv.getPower()); - - irkelv.setPower(false); - EXPECT_FALSE(irkelv.getPower()); -} - -TEST(TestKelvinatorClass, Temperature) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setTemp(0); - EXPECT_EQ(KELVINATOR_MIN_TEMP, irkelv.getTemp()); - - irkelv.setTemp(255); - EXPECT_EQ(KELVINATOR_MAX_TEMP, irkelv.getTemp()); - - irkelv.setTemp(KELVINATOR_MIN_TEMP); - EXPECT_EQ(KELVINATOR_MIN_TEMP, irkelv.getTemp()); - - irkelv.setTemp(KELVINATOR_MAX_TEMP); - EXPECT_EQ(KELVINATOR_MAX_TEMP, irkelv.getTemp()); - - irkelv.setTemp(KELVINATOR_MIN_TEMP - 1); - EXPECT_EQ(KELVINATOR_MIN_TEMP, irkelv.getTemp()); - - irkelv.setTemp(KELVINATOR_MAX_TEMP + 1); - EXPECT_EQ(KELVINATOR_MAX_TEMP, irkelv.getTemp()); - - irkelv.setTemp(17); - EXPECT_EQ(17, irkelv.getTemp()); - - irkelv.setTemp(21); - EXPECT_EQ(21, irkelv.getTemp()); - - irkelv.setTemp(25); - EXPECT_EQ(25, irkelv.getTemp()); - - irkelv.setTemp(29); - EXPECT_EQ(29, irkelv.getTemp()); -} - -TEST(TestKelvinatorClass, OperatingMode) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setTemp(24); - irkelv.setMode(KELVINATOR_AUTO); - EXPECT_EQ(KELVINATOR_AUTO, irkelv.getMode()); - EXPECT_EQ(KELVINATOR_AUTO_TEMP, irkelv.getTemp()); - - irkelv.setMode(KELVINATOR_COOL); - EXPECT_EQ(KELVINATOR_COOL, irkelv.getMode()); - - irkelv.setMode(KELVINATOR_HEAT); - EXPECT_EQ(KELVINATOR_HEAT, irkelv.getMode()); - - irkelv.setTemp(24); - irkelv.setMode(KELVINATOR_DRY); - EXPECT_EQ(KELVINATOR_DRY, irkelv.getMode()); - EXPECT_EQ(KELVINATOR_AUTO_TEMP, irkelv.getTemp()); - - irkelv.setMode(KELVINATOR_FAN); - EXPECT_EQ(KELVINATOR_FAN, irkelv.getMode()); - - irkelv.setMode(KELVINATOR_HEAT + 1); - EXPECT_EQ(KELVINATOR_AUTO, irkelv.getMode()); - - irkelv.setMode(255); - EXPECT_EQ(KELVINATOR_AUTO, irkelv.getMode()); -} - -TEST(TestKelvinatorClass, VaneSwing) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setSwingHorizontal(true); - irkelv.setSwingVertical(false); - - irkelv.setSwingHorizontal(true); - EXPECT_TRUE(irkelv.getSwingHorizontal()); - EXPECT_FALSE(irkelv.getSwingVertical()); - - irkelv.setSwingVertical(true); - EXPECT_TRUE(irkelv.getSwingHorizontal()); - EXPECT_TRUE(irkelv.getSwingVertical()); - - irkelv.setSwingHorizontal(false); - EXPECT_FALSE(irkelv.getSwingHorizontal()); - EXPECT_TRUE(irkelv.getSwingVertical()); - - irkelv.setSwingVertical(false); - EXPECT_FALSE(irkelv.getSwingHorizontal()); - EXPECT_FALSE(irkelv.getSwingVertical()); -} - -TEST(TestKelvinatorClass, QuietMode) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setQuiet(true); - EXPECT_TRUE(irkelv.getQuiet()); - - irkelv.setQuiet(false); - EXPECT_FALSE(irkelv.getQuiet()); - - irkelv.setQuiet(true); - EXPECT_TRUE(irkelv.getQuiet()); -} - -TEST(TestKelvinatorClass, IonFilter) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setIonFilter(true); - EXPECT_TRUE(irkelv.getIonFilter()); - - irkelv.setIonFilter(false); - EXPECT_FALSE(irkelv.getIonFilter()); - - irkelv.setIonFilter(true); - EXPECT_TRUE(irkelv.getIonFilter()); -} - -TEST(TestKelvinatorClass, Light) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setLight(true); - EXPECT_TRUE(irkelv.getLight()); - - irkelv.setLight(false); - EXPECT_FALSE(irkelv.getLight()); - - irkelv.setLight(true); - EXPECT_TRUE(irkelv.getLight()); -} - -TEST(TestKelvinatorClass, XFan) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setXFan(true); - EXPECT_TRUE(irkelv.getXFan()); - - irkelv.setXFan(false); - EXPECT_FALSE(irkelv.getXFan()); - - irkelv.setXFan(true); - EXPECT_TRUE(irkelv.getXFan()); -} - -TEST(TestKelvinatorClass, TurboFan) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setTurbo(true); - EXPECT_TRUE(irkelv.getTurbo()); - - irkelv.setTurbo(false); - EXPECT_FALSE(irkelv.getTurbo()); - - irkelv.setFan(2); - irkelv.setTurbo(true); - EXPECT_TRUE(irkelv.getTurbo()); - - // Turbo mode is turned off if the temperature is changed. - irkelv.setFan(3); - EXPECT_FALSE(irkelv.getTurbo()); - - // But only when it is changed, not set to the same value again. - irkelv.setTurbo(true); - irkelv.setFan(3); - EXPECT_TRUE(irkelv.getTurbo()); -} - -TEST(TestKelvinatorClass, FanSpeed) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setFan(0); - EXPECT_EQ(0, irkelv.getFan()); - - irkelv.setFan(255); - EXPECT_EQ(KELVINATOR_FAN_MAX, irkelv.getFan()); - - irkelv.setFan(KELVINATOR_FAN_MAX); - EXPECT_EQ(KELVINATOR_FAN_MAX, irkelv.getFan()); - - irkelv.setFan(KELVINATOR_FAN_MAX + 1); - EXPECT_EQ(KELVINATOR_FAN_MAX, irkelv.getFan()); - - irkelv.setFan(KELVINATOR_FAN_MAX - 1); - EXPECT_EQ(KELVINATOR_FAN_MAX - 1, irkelv.getFan()); - - irkelv.setFan(1); - EXPECT_EQ(1, irkelv.getFan()); - - irkelv.setFan(1); - EXPECT_EQ(1, irkelv.getFan()); - - irkelv.setFan(3); - EXPECT_EQ(3, irkelv.getFan()); -} - - -TEST(TestKelvinatorClass, MessageConstuction) { - IRKelvinatorAC irkelv(0); - IRsendTest irsend(4); - irkelv.begin(); - irsend.begin(); - - irkelv.setFan(1); - irkelv.setMode(KELVINATOR_COOL); - irkelv.setTemp(27); - irkelv.setSwingVertical(false); - irkelv.setSwingHorizontal(true); - irkelv.setIonFilter(true); - irkelv.setQuiet(false); - irkelv.setLight(false); - irkelv.setPower(true); - irkelv.setTurbo(false); - irkelv.setXFan(true); - - // Check everything for kicks. - EXPECT_EQ(1, irkelv.getFan()); - EXPECT_EQ(KELVINATOR_COOL, irkelv.getMode()); - EXPECT_EQ(27, irkelv.getTemp()); - EXPECT_FALSE(irkelv.getSwingVertical()); - EXPECT_TRUE(irkelv.getSwingHorizontal()); - EXPECT_TRUE(irkelv.getIonFilter()); - EXPECT_FALSE(irkelv.getQuiet()); - EXPECT_FALSE(irkelv.getLight()); - EXPECT_TRUE(irkelv.getPower()); - EXPECT_FALSE(irkelv.getTurbo()); - EXPECT_TRUE(irkelv.getXFan()); - - irsend.reset(); - irsend.sendKelvinator(irkelv.getRaw()); - EXPECT_EQ( - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s1560m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s1560m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900", irsend.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp deleted file mode 100644 index 2f28657fb..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp +++ /dev/null @@ -1,694 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "ir_Mitsubishi.h" -#include "gtest/gtest.h" - -// Tests for sendMitsubishi(). - -// Test sending typical data only. -TEST(TestSendMitsubishi, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendMitsubishi(0xE242); - EXPECT_EQ( - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580" - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishi(0x0); - EXPECT_EQ( - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s53580" - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s53580", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishi(0x4321); - EXPECT_EQ( - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s2100" - "m300s900m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100" - "m300s53580" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s2100" - "m300s900m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100" - "m300s53580", irsend.outputStr()); -} - -// Test sending with different repeats. -TEST(TestSendMitsubishi, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendMitsubishi(0xE242, MITSUBISHI_BITS, 0); // 0 repeat. - EXPECT_EQ( - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishi(0xE242, MITSUBISHI_BITS, 1); // 1 repeat. - EXPECT_EQ( - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580" - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580", irsend.outputStr()); - irsend.sendMitsubishi(0xE242, MITSUBISHI_BITS, 2); // 2 repeats. - EXPECT_EQ( - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580" - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580" - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580", irsend.outputStr()); -} - -// Test sending an atypical data size. -TEST(TestSendMitsubishi, SendUsualSize) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendMitsubishi(0x0, 8); - EXPECT_EQ( - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s53580" - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s53580", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishi(0x1234567890ABCDEF, 64); - EXPECT_EQ( - "m300s900m300s900m300s900m300s2100m300s900m300s900m300s2100m300s900" - "m300s900m300s900m300s2100m300s2100m300s900m300s2100m300s900m300s900" - "m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100m300s900" - "m300s900m300s2100m300s2100m300s2100m300s2100m300s900m300s900m300s900" - "m300s2100m300s900m300s900m300s2100m300s900m300s900m300s900m300s900" - "m300s2100m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100" - "m300s2100m300s2100m300s900m300s900m300s2100m300s2100m300s900m300s2100" - "m300s2100m300s2100m300s2100m300s900m300s2100m300s2100m300s2100m300s2100" - "m300s53580" - "m300s900m300s900m300s900m300s2100m300s900m300s900m300s2100m300s900" - "m300s900m300s900m300s2100m300s2100m300s900m300s2100m300s900m300s900" - "m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100m300s900" - "m300s900m300s2100m300s2100m300s2100m300s2100m300s900m300s900m300s900" - "m300s2100m300s900m300s900m300s2100m300s900m300s900m300s900m300s900" - "m300s2100m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100" - "m300s2100m300s2100m300s900m300s900m300s2100m300s2100m300s900m300s2100" - "m300s2100m300s2100m300s2100m300s900m300s2100m300s2100m300s2100m300s2100" - "m300s53580", irsend.outputStr()); -} - -// Decode normal Mitsubishi messages. -TEST(TestDecodeMitsubishi, NormalDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Mitsubishi 16-bit message. - irsend.reset(); - irsend.sendMitsubishi(0xC2B8); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xC2B8, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - irsend.reset(); - irsend.sendMitsubishi(0x0); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - irsend.reset(); - irsend.sendMitsubishi(0xFFFF); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xFFFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - // Non-standard Mitsubishi sizes should fail with strict. - irsend.reset(); - // 12 bits. - irsend.sendMitsubishi(0xFFF, 12); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); - - // 32 bits. - irsend.sendMitsubishi(0xFFF, 32); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 32, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); -} - -// Decode normal repeated Mitsubishi messages. -TEST(TestDecodeMitsubishi, NormalDecodeWithRepeatAndStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Mitsubishi 16-bit message with 2 repeats. - irsend.reset(); - irsend.sendMitsubishi(0xC2B8, MITSUBISHI_BITS, 2); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xC2B8, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - // Normal Mitsubishi 16-bit message with 0 repeats. - irsend.reset(); - irsend.sendMitsubishi(0xC2B8, MITSUBISHI_BITS, 0); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xC2B8, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} - -// Decode unsupported Mitsubishi messages. -TEST(TestDecodeMitsubishi, DecodeWithNonStrictValues) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendMitsubishi(0x0, 8); // Illegal sized Mitsubishi 8-bit message. - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(8, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); - - irsend.reset(); - // Illegal sized Mitsubishi 64-bit message. - irsend.sendMitsubishi(0xFEDCBA9876543210, 64); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFEDCBA9876543210, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - // Should fail when we are after a shorter message than we got. - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); -} - -// Decode a 'real' example via GlobalCache -TEST(TestDecodeMitsubishi, DecodeGlobalCacheExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Mitsubishi "Power On" (16-bit) code from Global Cache. - uint16_t gc_test[37] = {33000, 1, 1, 10, 70, 10, 70, 10, 70, 10, 30, 10, 30, - 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, 10, 30, - 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, 10, 936}; - irsend.sendGC(gc_test, 37); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xE242, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} - -// Fail to decode a non-Mitsubishi example via GlobalCache -TEST(TestDecodeMitsubishi, FailToDecodeNonMitsubishiExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; - irsend.sendGC(gc_test, 39); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, - false)); -} - -// Tests for Mitsubishi A/C methods. - -// Test sending typical data only. -TEST(TestSendMitsubishiAC, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t mitsub_code[MITSUBISHI_AC_STATE_LENGTH] = { - 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, - 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; - irsend.reset(); - irsend.sendMitsubishiAC(mitsub_code); - EXPECT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100", irsend.outputStr()); -} - -// Test sending with repeats. -TEST(TestSendMitsubishiAC, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - uint8_t mitsub_code[MITSUBISHI_AC_STATE_LENGTH] = { - 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, - 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; - - irsend.sendMitsubishiAC(mitsub_code, MITSUBISHI_AC_STATE_LENGTH, 0); - EXPECT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishiAC(mitsub_code, MITSUBISHI_AC_STATE_LENGTH, 2); - EXPECT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100", irsend.outputStr()); -} - -// Test sending atypical sizes. -TEST(TestSendMitsubishiAC, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t mitsub_short_code[17] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, - 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t mitsub_long_code[19] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, - 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, - 0x00}; - irsend.reset(); - irsend.sendMitsubishiAC(mitsub_short_code, 17); - ASSERT_EQ("", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishiAC(mitsub_long_code, 19); - ASSERT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m440s17100", irsend.outputStr()); -} - -// Tests for IRMitsubishiAC class. - -TEST(TestMitsubishiACClass, Power) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.on(); - EXPECT_TRUE(mitsub.getPower()); - - mitsub.off(); - EXPECT_FALSE(mitsub.getPower()); - - mitsub.setPower(true); - EXPECT_TRUE(mitsub.getPower()); - - mitsub.setPower(false); - EXPECT_FALSE(mitsub.getPower()); -} - -TEST(TestMitsubishiACClass, Temperature) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.setTemp(0); - EXPECT_EQ(MITSUBISHI_AC_MIN_TEMP, mitsub.getTemp()); - - mitsub.setTemp(255); - EXPECT_EQ(MITSUBISHI_AC_MAX_TEMP, mitsub.getTemp()); - - mitsub.setTemp(MITSUBISHI_AC_MIN_TEMP); - EXPECT_EQ(MITSUBISHI_AC_MIN_TEMP, mitsub.getTemp()); - - mitsub.setTemp(MITSUBISHI_AC_MAX_TEMP); - EXPECT_EQ(MITSUBISHI_AC_MAX_TEMP, mitsub.getTemp()); - - mitsub.setTemp(MITSUBISHI_AC_MIN_TEMP - 1); - EXPECT_EQ(MITSUBISHI_AC_MIN_TEMP, mitsub.getTemp()); - - mitsub.setTemp(MITSUBISHI_AC_MAX_TEMP + 1); - EXPECT_EQ(MITSUBISHI_AC_MAX_TEMP, mitsub.getTemp()); - - mitsub.setTemp(17); - EXPECT_EQ(17, mitsub.getTemp()); - - mitsub.setTemp(21); - EXPECT_EQ(21, mitsub.getTemp()); - - mitsub.setTemp(25); - EXPECT_EQ(25, mitsub.getTemp()); - - mitsub.setTemp(30); - EXPECT_EQ(30, mitsub.getTemp()); -} - -TEST(TestMitsubishiACClass, OperatingMode) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.setMode(MITSUBISHI_AC_AUTO); - EXPECT_EQ(MITSUBISHI_AC_AUTO, mitsub.getMode()); - - mitsub.setMode(MITSUBISHI_AC_COOL); - EXPECT_EQ(MITSUBISHI_AC_COOL, mitsub.getMode()); - - mitsub.setMode(MITSUBISHI_AC_HEAT); - EXPECT_EQ(MITSUBISHI_AC_HEAT, mitsub.getMode()); - - mitsub.setMode(MITSUBISHI_AC_DRY); - EXPECT_EQ(MITSUBISHI_AC_DRY, mitsub.getMode()); - - mitsub.setMode(MITSUBISHI_AC_AUTO + 1); - EXPECT_EQ(MITSUBISHI_AC_AUTO, mitsub.getMode()); - - mitsub.setMode(255); - EXPECT_EQ(MITSUBISHI_AC_AUTO, mitsub.getMode()); -} - -TEST(TestMitsubishiACClass, VaneMode) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO, mitsub.getVane()); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO + 1); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO + 1, mitsub.getVane()); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO_MOVE); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO_MOVE, mitsub.getVane()); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO_MOVE + 1); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO_MOVE, mitsub.getVane()); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO_MOVE - 1); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO_MOVE - 1, mitsub.getVane()); -} - -TEST(TestMitsubishiACClass, FanSpeed) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.setFan(MITSUBISHI_AC_FAN_AUTO); - EXPECT_EQ(MITSUBISHI_AC_FAN_AUTO, mitsub.getFan()); - - mitsub.setFan(255); - EXPECT_EQ(MITSUBISHI_AC_FAN_REAL_MAX, mitsub.getFan()); - - mitsub.setFan(MITSUBISHI_AC_FAN_MAX); - EXPECT_EQ(MITSUBISHI_AC_FAN_REAL_MAX, mitsub.getFan()); - - mitsub.setFan(MITSUBISHI_AC_FAN_MAX - 1); - EXPECT_EQ(MITSUBISHI_AC_FAN_MAX - 1, mitsub.getFan()); - - mitsub.setFan(1); - EXPECT_EQ(1, mitsub.getFan()); - - mitsub.setFan(2); - EXPECT_EQ(2, mitsub.getFan()); - - mitsub.setFan(3); - EXPECT_EQ(3, mitsub.getFan()); - - mitsub.setFan(4); - EXPECT_EQ(4, mitsub.getFan()); - - mitsub.setFan(MITSUBISHI_AC_FAN_SILENT); - EXPECT_EQ(MITSUBISHI_AC_FAN_SILENT, mitsub.getFan()); - - mitsub.setFan(MITSUBISHI_AC_FAN_SILENT + 1); - EXPECT_EQ(MITSUBISHI_AC_FAN_REAL_MAX, mitsub.getFan()); -} - -TEST(TestMitsubishiACClass, MessageConstuction) { - IRMitsubishiAC mitsub(0); - IRsendTest irsend(4); - mitsub.begin(); - irsend.begin(); - - mitsub.setFan(1); - mitsub.setMode(MITSUBISHI_AC_COOL); - mitsub.setTemp(27); - mitsub.setVane(3); - mitsub.on(); - - // Check everything for kicks. - EXPECT_EQ(1, mitsub.getFan()); - EXPECT_EQ(MITSUBISHI_AC_COOL, mitsub.getMode()); - EXPECT_EQ(27, mitsub.getTemp()); - EXPECT_EQ(3, mitsub.getVane()); - EXPECT_TRUE(mitsub.getPower()); - - irsend.reset(); - irsend.sendMitsubishiAC(mitsub.getRaw()); - EXPECT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s1300m450s1300m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s1300m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s1300m450s1300m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s1300m450s420" - "m440s17100", irsend.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp deleted file mode 100644 index 0eea2bc40..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendNikai(). -// Test sending typical data only. -TEST(TestSendNikai, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendNikai(0xD5F2A); // Nikai TV Power Off. - EXPECT_EQ("m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500", - irsend.outputStr()); - - irsend.reset(); -} - -// Test sending with different repeats. -TEST(TestSendNikai, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendNikai(0xD5F2A, NIKAI_BITS, 1); // 1 repeat. - EXPECT_EQ("m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500" - "m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500", - irsend.outputStr()); - irsend.sendNikai(0xD5F2A, NIKAI_BITS, 2); // 2 repeat. - EXPECT_EQ("m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500" - "m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500" - "m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500", - irsend.outputStr()); -} - -// Tests for decodeNikai(). - -// Decode normal Nikai messages. -TEST(TestDecodeNikai, NormalDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Nikai 24-bit message. - irsend.reset(); - irsend.sendNikai(0x123456); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0x123456, irsend.capture.value); - - irsend.reset(); - irsend.sendNikai(0x101); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0x101, irsend.capture.value); -} - -// Decode normal repeated Nikai messages. -TEST(TestDecodeNikai, NormalDecodeWithRepeatAndStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Nikai 24-bit message. - irsend.reset(); - irsend.sendNikai(0xD5F2A, NIKAI_BITS, 2); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0xD5F2A, irsend.capture.value); -} - -TEST(TestDecodeNikai, NormalDecodeWithNonStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Illegal under length (16-bit) message - irsend.reset(); - irsend.sendNikai(0x0, 16); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - // And it should fail when we expect more bits. - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, false)); - - // Should pass if strict off if we ask for correct nr. of bits sent. - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 16, false)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(16, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - - // Should fail as we are expecting less bits than there are. - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, 12, false)); -} - -// Decode (non-standard) 64-bit messages. -// Decode unsupported Nikai messages. -TEST(TestDecodeNikai, Decode64BitMessages) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Illegal size Nikai 64-bit message. - irsend.sendNikai(0xFFFFFFFFFFFFFFFF, 64); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 64, false)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); -} - -// Decode real example via Issue #309 -TEST(TestDecodeNikai, DecodeExamples) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Nikai TV Power Off from Issue #309 - uint16_t rawdata_off[100] = {4060, 3918, - 508, 2004, 508, 2002, 510, 2002, 508, 2004, 506, 1050, 508, 1048, - 510, 2004, 508, 1048, 508, 2002, 510, 1050, 508, 2004, 510, 1048, - 508, 1050, 508, 1048, 508, 1050, 508, 1050, 508, 2004, 508, 2002, - 510, 1048, 508, 2004, 508, 1050, 506, 2004, 508, 1048, 510, 2002, - 456, 8446, - 3956, 3998, - 508, 2004, 508, 2002, 508, 2004, 508, 1978, 532, 1050, 508, 1050, - 508, 2002, 508, 1050, 508, 2004, 508, 1050, 508, 2002, 510, 1050, - 508, 1050, 508, 1048, 508, 1050, 508, 1050, 508, 2002, 510, 2002, - 508, 1050, 508, 2002, 510, 1050, 508, 2002, 508}; - irsend.sendRaw(rawdata_off, 100, 38); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0xD5F2A, irsend.capture.value); - - // Nikai TV Volume Up from Issue #309 - uint16_t rawdata_volup[52] = {3972, 4002, - 504, 1982, 526, 2010, 502, 2010, 502, 2010, 500, 1056, 502, 1056, - 502, 2010, 500, 1056, 502, 2010, 502, 2010, 500, 2010, 502, 2010, - 502, 1056, 502, 1056, 502, 1056, 500, 1056, 502, 2010, 502, 2010, - 500, 1056, 502, 2008, 502, 1054, 504, 1054, 504, 1054, 500, 1056, - 450}; - - irsend.reset(); - irsend.sendRaw(rawdata_volup, 52, 38); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0xD0F2F, irsend.capture.value); -} - -// Fail to decode a non-Nikai example via GlobalCache -TEST(TestDecodeNikai, FailToDecodeNonNikaiExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, 21, - 22, 21, 22, 21, 22, 11, 22, 21, 22, 128, 22, 64, 22, - 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, - 22, 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, - 64, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, 64, - 22, 64, 22, 21, 22, 1820}; - irsend.sendGC(gc_test, 71); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, false)); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp deleted file mode 100644 index 3f27b90bf..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp +++ /dev/null @@ -1,457 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for encodePanasonic(). - -TEST(TestEncodePanasonic, General) { - IRsendTest irsend(4); - EXPECT_EQ(0x0, irsend.encodePanasonic(0, 0, 0, 0)); - EXPECT_EQ(0x101010101, irsend.encodePanasonic(1, 1, 1, 1)); - EXPECT_EQ(0xFFFF, irsend.encodePanasonic(0, 0, 0, 0xFF)); - EXPECT_EQ(0xFF00FF, irsend.encodePanasonic(0, 0, 0xFF, 0)); - EXPECT_EQ(0xFF0000FF, irsend.encodePanasonic(0, 0xFF, 0, 0)); - EXPECT_EQ(0xFFFF00000000, irsend.encodePanasonic(0xFFFF, 0, 0, 0)); - EXPECT_EQ(0xFFFFFFFFFFFF, irsend.encodePanasonic(0xFFFF, 0xFF, 0xFF, 0xFF)); - EXPECT_EQ(0x40040190ED7C, irsend.encodePanasonic(0x4004, 0x01, 0x90, 0xED)); -} - - -// Tests for sendPanasonic64(). - -// Test sending typical data only. -TEST(TestSendPanasonic64, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x0); - EXPECT_EQ( - "m3456s1728" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C); - EXPECT_EQ( - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.reset(); - irsend.sendPanasonic64(0xFFFFFFFFFFFF); - EXPECT_EQ( - "m3456s1728" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s129600", irsend.outputStr()); -} - -// Test sending with different repeats. -TEST(TestSendPanasonic64, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C, PANASONIC_BITS, 0); // 0 repeats. - EXPECT_EQ( - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C, PANASONIC_BITS, 1); // 1 repeat. - EXPECT_EQ( - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600" - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.sendPanasonic64(0x40040190ED7C, PANASONIC_BITS, 2); // 2 repeats. - EXPECT_EQ( - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600" - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600" - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600", irsend.outputStr()); -} - -// Test sending an atypical data size. -TEST(TestSendPanasonic64, SendUnusualSize) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x0, 8); - EXPECT_EQ( - "m3456s1728" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.reset(); - irsend.sendPanasonic64(0x1234567890ABCDEF, 64); - EXPECT_EQ( - "m3456s1728" - "m432s432m432s432m432s432m432s1296m432s432m432s432m432s1296m432s432" - "m432s432m432s432m432s1296m432s1296m432s432m432s1296m432s432m432s432" - "m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296m432s432" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s432m432s432m432s432" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296" - "m432s1296m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s1296" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s1296m432s1296" - "m432s129600", irsend.outputStr()); -} - -// Tests for sendPanasonic(). - -TEST(TestSendPanasonic, CompareToSendPanasonic64) { - IRsendTest panasonic(4); - IRsendTest panasonic64(0); - - panasonic.begin(); - panasonic64.begin(); - - panasonic.reset(); - panasonic64.reset(); - - panasonic.sendPanasonic(0x4004, 0x0190ED7C); - panasonic64.sendPanasonic64(0x40040190ED7C); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); - - panasonic.sendPanasonic(0x0, 0x0); - panasonic64.sendPanasonic64(0x0); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); - - panasonic.sendPanasonic(0x0, 0x0, 8); - panasonic64.sendPanasonic64(0x0, 8); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); - - panasonic.sendPanasonic(0x1234, 0x567890AB, 64); - panasonic64.sendPanasonic64(0x1234567890AB, 64); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); - - panasonic.sendPanasonic(0x1234, 0x567890AB, PANASONIC_BITS, 2); - panasonic64.sendPanasonic64(0x1234567890AB, PANASONIC_BITS, 2); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); -} - -// Tests for decodePanasonic(). - -// Decode normal Panasonic messages. -TEST(TestDecodePanasonic, NormalDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Panasonic 48-bit message. - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x0190ED7C, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - // Synthesised Normal Panasonic 48-bit message. - irsend.reset(); - irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x12, 0x34, 0x56)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x400412345670, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x12345670, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - // Synthesised Normal Panasonic 48-bit message. - irsend.reset(); - irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x1, 0x1, 0x1)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x400401010101, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x1010101, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} - -// Decode normal repeated Panasonic messages. -TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Panasonic 48-bit message with 2 repeats. - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C, PANASONIC_BITS, 2); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x190ED7C, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - irsend.makeDecodeResult(2 * PANASONIC_BITS + 4); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - - irsend.makeDecodeResult(2 * (2 * PANASONIC_BITS + 4)); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); -} - -// Decode Panasonic messages with unsupported values. -TEST(TestDecodePanasonic, DecodeWithNonStrictValues) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x0); // Illegal value Panasonic 48-bit message. - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - // Illegal address/Manufacturer code. The rest is legal. - irsend.sendPanasonic64(irsend.encodePanasonic(0, 1, 2, 3)); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x1020300, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x1020300, irsend.capture.command); -} - -// Decode Panasonic messages with unsupported size/lengths. -TEST(TestDecodePanasonic, DecodeWithNonStrictSize) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x12345678, 32); // Illegal size Panasonic message. - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - - irsend.makeDecodeResult(); - // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 32, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 32, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(32, irsend.capture.bits); - EXPECT_EQ(0x12345678, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x12345678, irsend.capture.command); - - // Illegal over length (56-bit) message. - irsend.reset(); - irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 1, 2, 3), 56); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - // Shouldn't pass if strict off and wrong bit size. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, false)); - // Re-decode with correct bit size. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 56, true)); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 56, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(56, irsend.capture.bits); - EXPECT_EQ(0x400401020300, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x01020300, irsend.capture.command); -} - -// Decode (non-standard) 64-bit messages. -TEST(TestDecodePanasonic, Decode64BitMessages) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Illegal value & size Panasonic 64-bit message. - irsend.sendPanasonic64(0xFFFFFFFFFFFFFFFF, 64); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 64, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 64, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); - EXPECT_EQ(0xFFFFFFFF, irsend.capture.address); - EXPECT_EQ(0xFFFFFFFF, irsend.capture.command); -} - -// Decode a 'real' example via GlobalCache -TEST(TestDecodePanasonic, DecodeGlobalCacheExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Panasonic code from Global Cache. - uint16_t gc_test[103] = {37000, 1, 1, 126, 64, 16, 17, 16, 49, 15, 16, 16, 16, - 16, 16, 16, 17, 15, 17, 15, 17, 15, 17, 15, 16, 16, - 16, 16, 16, 16, 17, 15, 49, 16, 16, 16, 16, 16, 17, - 15, 17, 15, 17, 15, 17, 15, 16, 16, 16, 16, 16, 16, - 49, 15, 49, 16, 17, 15, 17, 15, 49, 16, 16, 16, 17, - 16, 17, 15, 17, 15, 49, 16, 49, 15, 49, 16, 17, 16, - 49, 15, 49, 16, 17, 15, 48, 16, 16, 16, 49, 15, 48, - 16, 49, 15, 49, 16, 49, 15, 17, 15, 16, 16, 2721}; - irsend.sendGC(gc_test, 103); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x0190ED7C, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x0190ED7C, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} - -// Fail to decode a non-Panasonic example via GlobalCache -TEST(TestDecodePanasonic, FailToDecodeNonPanasonicExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; - irsend.sendGC(gc_test, 39); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture)); - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, false)); -} - -// Failing to decode Panasonic in Issue #245 -TEST(TestDecodePanasonic, DecodeIssue245) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - - uint16_t rawData[100] = {3550, 1750, 500, 450, 500, 1300, 500, 450, 500, 450, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 1300, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 1300, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, - 500, 450, 500, 450, 500, 450, 500, 1300, 500, 450, - 500, 1300, 500, 1300, 500, 1300, 500, 1300, 500, 450, - 500, 450, 500, 1300, 500, 450, 500, 1300, 500, 1300, - 500, 1300, 500, 1300, 500, 450, 500, 1300, 500, 5000}; - - irsend.sendRaw(rawData, 100, 37); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040100BCBD, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x100BCBD, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - irsend.reset(); - irsend.sendRaw(rawData, 99, 37); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040100BCBD, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x100BCBD, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp deleted file mode 100644 index 8c35ebebf..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendSAMSUNG(). - -// Test sending typical data only. -TEST(TestSendSamsung, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSAMSUNG(0xE0E09966); // Samsung TV Power On. - EXPECT_EQ("m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080", - irsend.outputStr()); - - irsend.reset(); -} - -// Test sending with different repeats. -TEST(TestSendSamsung, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSAMSUNG(0xE0E09966, SAMSUNG_BITS, 1); // 1 repeat. - EXPECT_EQ("m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - "m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - , irsend.outputStr()); - irsend.sendSAMSUNG(0xE0E09966, SAMSUNG_BITS, 2); // 2 repeats. - EXPECT_EQ("m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - "m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - "m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - , irsend.outputStr()); -} - -// Tests for encodeSAMSUNG(). - -TEST(TestEncodeSamsung, NormalEncoding) { - IRsendTest irsend(4); - EXPECT_EQ(0xFF, irsend.encodeSAMSUNG(0, 0)); - EXPECT_EQ(0x8080807F, irsend.encodeSAMSUNG(1, 1)); - EXPECT_EQ(0xF8F805FA, irsend.encodeSAMSUNG(0x1F, 0xA0)); - EXPECT_EQ(0xA0A0CC33, irsend.encodeSAMSUNG(0x05, 0x33)); - EXPECT_EQ(0xFFFFFF00, irsend.encodeSAMSUNG(0xFF, 0xFF)); - EXPECT_EQ(0xE0E09966, irsend.encodeSAMSUNG(0x07, 0x99)); -} - -// Tests for decodeSAMSUNG(). - -// Decode normal Samsung messages. -TEST(TestDecodeSamsung, NormalDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Samsung 32-bit message. - irsend.reset(); - irsend.sendSAMSUNG(0xE0E09966); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0xE0E09966, irsend.capture.value); - EXPECT_EQ(0x07, irsend.capture.address); - EXPECT_EQ(0x99, irsend.capture.command); - - // Synthesised Normal Samsung 32-bit message. - irsend.reset(); - irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x07, 0x99)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0xE0E09966, irsend.capture.value); - EXPECT_EQ(0x07, irsend.capture.address); - EXPECT_EQ(0x99, irsend.capture.command); - - // Synthesised Normal Samsung 32-bit message. - irsend.reset(); - irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x1, 0x1)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0x8080807F, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x1, irsend.capture.command); -} - -// Decode normal repeated Samsung messages. -TEST(TestDecodeSamsung, NormalDecodeWithRepeatAndStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Samsung 32-bit message. - irsend.reset(); - irsend.sendSAMSUNG(0xE0E09966, SAMSUNG_BITS, 2); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0xE0E09966, irsend.capture.value); - EXPECT_EQ(0x07, irsend.capture.address); - EXPECT_EQ(0x99, irsend.capture.command); -} - -// Decode unsupported Samsung messages. -TEST(TestDecodeSamsung, DecodeWithNonStrictValues) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSAMSUNG(0x0); // Illegal value Samsung 32-bit message. - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - irsend.sendSAMSUNG(0x12345678); // Illegal value Samsung 32-bit message. - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0x12345678, irsend.capture.value); - EXPECT_EQ(0x48, irsend.capture.address); - EXPECT_EQ(0x6A, irsend.capture.command); - - // Illegal over length (36-bit) message. - irsend.reset(); - irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0, 0), 36); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // Shouldn't pass if strict off and wrong expected bit size. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); - // Re-decode with correct bit size. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 36, true)); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 36, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(36, irsend.capture.bits); - EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 8 bits less. - EXPECT_EQ(0x00, irsend.capture.address); - EXPECT_EQ(0x00, irsend.capture.command); - - // Illegal under length (16-bit) message - irsend.reset(); - irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x0, 0x0), 16); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // And it should fail when we expect more bits. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); - - // Should pass if strict off if we ask for correct nr. of bits sent. - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 16, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(16, irsend.capture.bits); - EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 4 bits less. - EXPECT_EQ(0x00, irsend.capture.address); - EXPECT_EQ(0x00, irsend.capture.command); - - // Should fail as we are expecting less bits than there are. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 12, false)); -} - -// Decode (non-standard) 64-bit messages. -// Decode unsupported Samsung messages. -TEST(TestDecodeSamsung, Decode64BitMessages) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Illegal value & size Samsung 64-bit message. - irsend.sendSAMSUNG(0xFFFFFFFFFFFFFFFF, 64); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 64, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); - EXPECT_EQ(0xFF, irsend.capture.address); - EXPECT_EQ(0xFF, irsend.capture.command); -} - -// Decode a 'real' example via GlobalCache -TEST(TestDecodeSamsung, DecodeGlobalCacheExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Samsung TV Power On from Global Cache. - uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, 21, - 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, 22, 64, 22, - 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, - 22, 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, - 64, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, 64, - 22, 64, 22, 21, 22, 1820}; - irsend.sendGC(gc_test, 71); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0xE0E09966, irsend.capture.value); - EXPECT_EQ(0x07, irsend.capture.address); - EXPECT_EQ(0x99, irsend.capture.command); -} - -// Fail to decode a non-Samsung example via GlobalCache -TEST(TestDecodeSamsung, FailToDecodeNonSamsungExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, 21, - 22, 21, 22, 21, 22, 11, 22, 21, 22, 128, 22, 64, 22, - 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, - 22, 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, - 64, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, 64, - 22, 64, 22, 21, 22, 1820}; - irsend.sendGC(gc_test, 71); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp deleted file mode 100644 index b5750b3b1..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendSherwood(). - -// Test sending typical data only. -TEST(TestSendSherwood, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSherwood(0xC1A28877); - EXPECT_EQ("m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" - "m560s1680m560s560m560s1680m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); -} - -// Test sending typical data with extra repeats. -TEST(TestSendSherwood, SendDataWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSherwood(0xC1A28877, 32, 2); - EXPECT_EQ("m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" - "m560s1680m560s560m560s1680m560s1680m560s1680m560s108080" - "m8960s2240m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); -} - -// Test sending typical data with explicit no repeats. -TEST(TestSendSherwood, SendDataWithZeroRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSherwood(0xC1A28877, 32, 0); - // Should have a single NEC repeat, as we always send one. - EXPECT_EQ("m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" - "m560s1680m560s560m560s1680m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); -} - -// Test that a typical Sherwood send decodes as the appropriate NEC value. -TEST(TestSendSherwood, DecodesAsNEC) { - IRsendTest irsend(4); - IRrecv irrecv(0); - irsend.begin(); - - irsend.reset(); - irsend.sendSherwood(0xC1A28877); - irsend.makeDecodeResult(); - - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0xC1A28877, irsend.capture.value); - EXPECT_EQ(0x4583, irsend.capture.address); - EXPECT_EQ(0x11, irsend.capture.command); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp deleted file mode 100644 index 76d351441..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendSony(). - -// Test sending typical data only. -TEST(TestSendSony, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSony(0); - // We expect three 20-bit commands to be sent. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s45600", irsend.outputStr()); - - irsend.reset(); - irsend.sendSony(0x240C, SONY_20_BITS); - // We expect three 20-bit commands to be sent. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600", irsend.outputStr()); - - irsend.reset(); - irsend.sendSony(0x240C, SONY_15_BITS); - // We expect three 15-bit commands to be sent. - EXPECT_EQ("m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" - "m600s45600" - "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" - "m600s45600" - "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" - "m600s45600", irsend.outputStr()); - - irsend.reset(); - irsend.sendSony(0xA90, SONY_12_BITS); - // We expect three 15-bit commands to be sent. - EXPECT_EQ("m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" - "m600s600m1200s600m600s600m600s600m600s600m600s45600" - "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" - "m600s600m1200s600m600s600m600s600m600s600m600s45600" - "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" - "m600s600m1200s600m600s600m600s600m600s600m600s45600", - irsend.outputStr()); -} - -// Test sending with different repeats. -TEST(TestSendSony, SendWithDiffRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSony(0x240C, SONY_20_BITS, 0); // Send a command with 0 repeats. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600", irsend.outputStr()); - irsend.sendSony(0x240C, SONY_20_BITS, 1); // Send a command with 1 repeat. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600", irsend.outputStr()); - irsend.sendSony(0x240C, SONY_20_BITS, 3); // Send a command with 3 repeats. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600", irsend.outputStr()); -} - -// Tests for encodeSony(). - -TEST(TestEncodeSony, NormalSonyEncoding) { - IRsendTest irsend(4); - EXPECT_EQ(0x0, irsend.encodeSony(SONY_12_BITS, 0, 0)); - EXPECT_EQ(0xA90, irsend.encodeSony(SONY_12_BITS, 21, 1)); - EXPECT_EQ(0xFFF, irsend.encodeSony(SONY_12_BITS, 0x7F, 0x1F)); - - EXPECT_EQ(0x0, irsend.encodeSony(SONY_15_BITS, 0, 0)); - EXPECT_EQ(0x5480, irsend.encodeSony(SONY_15_BITS, 21, 1)); - EXPECT_EQ(0x5455, irsend.encodeSony(SONY_15_BITS, 21, 0xAA)); - EXPECT_EQ(0x7FFF, irsend.encodeSony(SONY_15_BITS, 0x7F, 0xFF)); - - EXPECT_EQ(0x0, irsend.encodeSony(SONY_20_BITS, 0, 0, 0)); - EXPECT_EQ(0x81080, irsend.encodeSony(SONY_20_BITS, 1, 1, 1)); - EXPECT_EQ(0xFFFFF, irsend.encodeSony(SONY_20_BITS, 0x7F, 0x1F, 0xFF)); -} - -TEST(TestEncodeSony, SonyEncodingWithOversizedValues) { - IRsendTest irsend(4); - EXPECT_EQ(0xFFF, irsend.encodeSony(SONY_12_BITS, 0xFFFF, 0xFFFF)); - - EXPECT_EQ(0x7FFF, irsend.encodeSony(SONY_15_BITS, 0xFFFF, 0xFFFF)); - - EXPECT_EQ(0xFFFFF, irsend.encodeSony(SONY_20_BITS, 0xFFFF, 0xFFFF, 0xFFFF)); -} - -// Tests for decodeSony(). - -// Decode normal Sony messages. -TEST(TestDecodeSony, NormalSonyDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Synthesised Normal Sony 20-bit message. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_20_BITS, 0x1, 0x1, 0x1)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); - EXPECT_EQ(0x81080, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x81, irsend.capture.command); - - // Synthesised Normal Sony 15-bit message. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_15_BITS, 21, 1), SONY_15_BITS); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_15_BITS, irsend.capture.bits); - EXPECT_EQ(0x5480, irsend.capture.value); - EXPECT_EQ(1, irsend.capture.address); - EXPECT_EQ(21, irsend.capture.command); - - // Synthesised Normal Sony 12-bit message. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_12_BITS, 21, 1), SONY_12_BITS); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); - EXPECT_EQ(0xA90, irsend.capture.value); - EXPECT_EQ(1, irsend.capture.address); - EXPECT_EQ(21, irsend.capture.command); -} - -// Decode unexpected Sony messages. i.e longer than minimum etc. -TEST(TestDecodeSony, SonyDecodeWithUnexpectedLegalSize) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Synthesised Normal Sony 20-bit message decoded when looking for 12-bits - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_20_BITS, 0x1, 0x1, 0x1)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); - EXPECT_EQ(0x81080, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x81, irsend.capture.command); - - // Synthesised Normal Sony 12-bit message when expecting 20-bits. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_12_BITS, 21, 1), SONY_12_BITS); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); - EXPECT_EQ(0xA90, irsend.capture.value); - EXPECT_EQ(1, irsend.capture.address); - EXPECT_EQ(21, irsend.capture.command); - - // 12-bit message should be regected when using strict and a different size. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_12_BITS, 21, 1), SONY_12_BITS); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - - // 15-bit message should be regected when using strict and a different size. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_15_BITS, 21, 1), SONY_15_BITS); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - - // 20-bit message should be regected when using strict and a different size. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_20_BITS, 1, 1, 1), SONY_20_BITS); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); -} - -// Decode unsupported Sony messages. i.e non-standard sizes. -TEST(TestDecodeSony, SonyDecodeWithIllegalSize) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSony(0xFF, 8); // Illegal 8-bit Sony-like message. - irsend.makeDecodeResult(); - // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(8, irsend.capture.bits); - EXPECT_EQ(0xFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - irsend.sendSony(0x1FFF, 13); // Illegal 13-bit Sony-like message. - irsend.makeDecodeResult(); - // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(13, irsend.capture.bits); - EXPECT_EQ(0x1FFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - irsend.sendSony(0x1FFFF, 17); // Illegal 17-bit Sony-like message. - irsend.makeDecodeResult(); - // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(17, irsend.capture.bits); - EXPECT_EQ(0x1FFFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - irsend.sendSony(0x1FFFFF, 21); // Illegal 21-bit Sony-like message. - irsend.makeDecodeResult(); - // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(21, irsend.capture.bits); - EXPECT_EQ(0x1FFFFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - // Illegal 64-bit (max) Sony-like message. - irsend.sendSony(0xFFFFFFFFFFFFFFFF, 64, 0); - irsend.makeDecodeResult(); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); -} - - -// Decode unsupported Sony messages. i.e non-standard sizes. -TEST(TestDecodeSony, DecodeGlobalCacheExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Sony "Power On" from Global Cache. - uint16_t gc_test[29] = {40000, 1, 1, 96, 24, 24, 24, 48, 24, 48, 24, 48, 24, - 24, 24, 48, 24, 24, 24, 48, 24, 24, 24, 24, 24, 24, - 24, 24, 1013}; - irsend.sendGC(gc_test, 29); - irsend.makeDecodeResult(); - - // Without strict. - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(12, irsend.capture.bits); - EXPECT_EQ(0x750, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x2E, irsend.capture.command); - // With strict and correct size. - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp deleted file mode 100644 index 9c3d316ca..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// Quick and dirty tool to decode GlobalCache (GC) codes -// Copyright 2017 Jorge Cisneros - -#include -#include -#include -#include -#include "IRsend.h" -#include "IRsend_test.h" - -#define MAX_GC_CODE_LENGHT 512 - -void str_to_uint16(char *str, uint16_t *res) { - char *end; - errno = 0; - intmax_t val = strtoimax(str, &end, 10); - if (errno == ERANGE || val < 0 || val > UINT16_MAX || - end == str || *end != '\0') - return; - *res = (uint16_t) val; -} - -std::string encoding(decode_results *results) { - switch (results->decode_type) { - default: - case UNKNOWN: return "UNKNOWN"; break; - case NEC: return "NEC"; break; - case NEC_LIKE: return "NEC (non-strict)"; break; - case SONY: return "SONY"; break; - case RC5: return "RC5"; break; - case RC5X: return "RC5X"; break; - case RC6: return "RC6"; break; - case RCMM: return "RCMM"; break; - case DISH: return "DISH"; break; - case SHARP: return "SHARP"; break; - case JVC: return "JVC"; break; - case SANYO: return "SANYO"; break; - case SANYO_LC7461: return "SANYO_LC7461"; break; - case MITSUBISHI: return "MITSUBISHI"; break; - case SAMSUNG: return "SAMSUNG"; break; - case LG: return "LG"; break; - case WHYNTER: return "WHYNTER"; break; - case AIWA_RC_T501: return "AIWA_RC_T501"; break; - case PANASONIC: return "PANASONIC"; break; - case DENON: return "DENON"; break; - case COOLIX: return "COOLIX"; break; - case NIKAI: return "NIKAI"; break; - } -} - -void usage_error(char * name) { - std::cerr << "Usage: " << name << " [-raw] " << std::endl; -} - -int main(int argc, char * argv[]) { - int argv_offset = 1; - bool dumpraw = false; - - // Check the invocation/calling usage. - if (argc < 2 || argc > 3) { - usage_error(argv[0]); - return 1; - } - if (strncmp("-raw", argv[argv_offset], 4) == 0) { - dumpraw = true; - argv_offset++; - } - if (argc - argv_offset != 1) { - usage_error(argv[0]); - return 1; - } - - uint16_t gc_test[MAX_GC_CODE_LENGHT]; - int index = 0; - char *pch; - char *saveptr1; - - pch = strtok_r(argv[argv_offset], ",", &saveptr1); - while (pch != NULL && index < MAX_GC_CODE_LENGHT) { - str_to_uint16(pch, &gc_test[index]); - pch = strtok_r(NULL, ",", &saveptr1); - index++; - } - - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - irsend.reset(); - - irsend.sendGC(gc_test, index); - irsend.makeDecodeResult(); - irrecv.decode(&irsend.capture); - - std::cout << "Code GC length " << index << std::endl - << "Code type " << irsend.capture.decode_type - << " (" << encoding(&irsend.capture) << ")" << std::endl - << "Code bits " << irsend.capture.bits << std::endl - << "Code value 0x" << std::hex << irsend.capture.value << std::endl - << "Code address 0x" << std::hex << irsend.capture.address << std::endl - << "Code command 0x" << std::hex << irsend.capture.command << std::endl; - - if (dumpraw || irsend.capture.decode_type == UNKNOWN) - irsend.dumpRawResult(); - - return 0; -} diff --git a/lib/IRremoteESP8266-2.2.1.02/.github/CONTRIBUTING.md b/lib/IRremoteESP8266-2.5.2.03/.github/CONTRIBUTING.md similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/.github/CONTRIBUTING.md rename to lib/IRremoteESP8266-2.5.2.03/.github/CONTRIBUTING.md diff --git a/lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md b/lib/IRremoteESP8266-2.5.2.03/.github/Contributors.md similarity index 91% rename from lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md rename to lib/IRremoteESP8266-2.5.2.03/.github/Contributors.md index 151a0c03d..5f75ea3b4 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md +++ b/lib/IRremoteESP8266-2.5.2.03/.github/Contributors.md @@ -10,6 +10,8 @@ - [Jonny Graham](https://github.com/jonnygraham/) - [Stu Fisher](https://github.com/stufisher/) - [Jorge Cisneros](https://github.com/jorgecis/) +- [Denes Varga](https://github.com/denxhun/) +- [Brett T. Warden](https://github.com/bwarden/) All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors). diff --git a/lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md b/lib/IRremoteESP8266-2.5.2.03/.github/issue_template.md similarity index 84% rename from lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md rename to lib/IRremoteESP8266-2.5.2.03/.github/issue_template.md index 664b99570..024a0398c 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md +++ b/lib/IRremoteESP8266-2.5.2.03/.github/issue_template.md @@ -1,7 +1,7 @@ _(Please use this template for reporting issues. You can delete what ever is not relevant. Giving us this information will help us help you faster. Please also read the [FAQ](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions) & [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide). Your problem may already have an answer there.)_ ### Version/revison of the library used -_Typically located in the `library.json` file in the root directory of the library. +_Typically located in the `library.json` & `src/IRremoteESP8266.h` files in the root directory of the library. e.g. v2.0.0, or 'master' as at 1st of June, 2017. etc._ ### Expected behavior @@ -30,10 +30,13 @@ _What can we do to (pref. reliably) repeat what is happening?_ _Include all relevant code snippets or links to the actual code files. Tip: [How to quote your code so it is still readable](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code)._ #### Circuit diagram and hardware used (if applicable) -_Link to an image of the circuit diagram used._ +_Link to an image of the circuit diagram used. Part number of the IR receiver module etc._ ### I have followed the steps in the [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide) & read the [FAQ](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions) _Yes/No._ +### Has this library/code previously worked as expected for you? +_Yes/No. If "Yes", which version last worked for you?_ + ### Other useful information _More information is always welcome. Be verbose._ diff --git a/lib/IRremoteESP8266-2.2.1.02/.gitignore b/lib/IRremoteESP8266-2.5.2.03/.gitignore similarity index 88% rename from lib/IRremoteESP8266-2.2.1.02/.gitignore rename to lib/IRremoteESP8266-2.5.2.03/.gitignore index 6d57ebaab..23e21ca3e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.gitignore +++ b/lib/IRremoteESP8266-2.5.2.03/.gitignore @@ -23,6 +23,9 @@ lib/googletest/**/* # GCC pre-compiled headers. **/*.gch +# Python compiled files +**/*.pyc + # Unit Test builds test/*.o test/*.a @@ -32,8 +35,12 @@ test/*_test tools/*.o tools/*.a tools/gc_decode +tools/mode2_decode .pioenvs .piolibdeps .clang_complete .gcc-flags.json + +#Cygwin builds +*.exe diff --git a/lib/IRremoteESP8266-2.2.1.02/.gitmodules b/lib/IRremoteESP8266-2.5.2.03/.gitmodules similarity index 85% rename from lib/IRremoteESP8266-2.2.1.02/.gitmodules rename to lib/IRremoteESP8266-2.5.2.03/.gitmodules index 80925b865..c28fe0509 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.gitmodules +++ b/lib/IRremoteESP8266-2.5.2.03/.gitmodules @@ -1,3 +1,4 @@ [submodule "lib/googletest"] path = lib/googletest url = https://github.com/google/googletest.git + branch = v1.8.x diff --git a/lib/IRremoteESP8266-2.5.2.03/.style.yapf b/lib/IRremoteESP8266-2.5.2.03/.style.yapf new file mode 100644 index 000000000..65fa0ee33 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/.style.yapf @@ -0,0 +1,3 @@ +[style] +based_on_style: google +indent_width: 2 diff --git a/lib/IRremoteESP8266-2.2.1.02/.travis.yml b/lib/IRremoteESP8266-2.5.2.03/.travis.yml similarity index 94% rename from lib/IRremoteESP8266-2.2.1.02/.travis.yml rename to lib/IRremoteESP8266-2.5.2.03/.travis.yml index 33d91ba47..4331425e9 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.travis.yml +++ b/lib/IRremoteESP8266-2.5.2.03/.travis.yml @@ -20,6 +20,7 @@ install: - arduino --board $BD --save-prefs - arduino --pref "compiler.warning_level=all" --save-prefs - sudo apt-get install jq + - sudo pip install pylint script: # Check that everything compiles. - arduino --verify --board $BD $PWD/examples/IRrecvDemo/IRrecvDemo.ino @@ -38,14 +39,17 @@ script: - arduino --verify --board $BD $PWD/examples/LGACSend/LGACSend.ino - arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.ino - arduino --verify --board $BD $PWD/examples/IRMQTTServer/IRMQTTServer.ino + - arduino --verify --board $BD $PWD/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino # Also check the tools programs compile. - (cd tools; make all) # Check for lint issues. - shopt -s nullglob - python cpplint.py --extensions=c,cc,cpp,ino --headers=h,hpp {src,test,tools}/*.{h,c,cc,cpp,hpp,ino} examples/*/*.{h,c,cc,cpp,hpp,ino} + - pylint {src,test,tools}/*.py - shopt -u nullglob # Build and run the unit tests. - (cd test; make run) + - (cd tools; make run_tests) # Check the version numbers match. - LIB_VERSION=$(egrep "^#define\s+_IRREMOTEESP8266_VERSION_\s+" src/IRremoteESP8266.h | cut -d\" -f2) - test ${LIB_VERSION} == "$(jq -r .version library.json)" diff --git a/lib/IRremoteESP8266-2.2.1.02/CPPLINT.cfg b/lib/IRremoteESP8266-2.5.2.03/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/CPPLINT.cfg rename to lib/IRremoteESP8266-2.5.2.03/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.2.1.02/LICENSE.txt b/lib/IRremoteESP8266-2.5.2.03/LICENSE.txt similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/LICENSE.txt rename to lib/IRremoteESP8266-2.5.2.03/LICENSE.txt diff --git a/lib/IRremoteESP8266-2.5.2.03/README.md b/lib/IRremoteESP8266-2.5.2.03/README.md new file mode 100644 index 000000000..bb9d5a9d8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/README.md @@ -0,0 +1,78 @@ +# IRremote ESP8266 Library + +[![Build Status](https://travis-ci.org/markszabo/IRremoteESP8266.svg?branch=master)](https://travis-ci.org/markszabo/IRremoteESP8266) +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Average time to resolve an issue") +[![Percentage of issues still open](http://isitmaintained.com/badge/open/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Percentage of issues still open") +[![GitLicense](https://gitlicense.com/badge/markszabo/IRremoteESP8266)](https://gitlicense.com/license/markszabo/IRremoteESP8266) + +This library enables you to **send _and_ receive** infra-red signals on an [ESP8266 using the Arduino framework](https://github.com/esp8266/Arduino) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* etc. + +## v2.5.2 Now Available +Version 2.5.2 of the library is now [available](https://github.com/markszabo/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. + +#### Upgrading from pre-v2.0 +Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/markszabo/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. + +#### Upgrading from pre-v2.5 +The library has changed from using constants declared as `#define` to +[const](https://google.github.io/styleguide/cppguide.html#Constant_Names) with +the appropriate naming per the +[C++ style guide](https://google.github.io/styleguide/cppguide.html). +This may potentially cause old programs to not compile. +The most likely externally used `#define`s have been _aliased_ for limited +backward compatibility for projects using the old style. Going forward, only the +new `kConstantName` style will be supported for new protocol additions. + +In the unlikely case it does break your code, then you may have been referencing +something you likely should not have. You should be able to quickly determine +the new name from the old. e.g. `CONSTANT_NAME` to `kConstantName`. +Use common sense or examining the library's code if this does affect code. + +## Troubleshooting +Before reporting an issue or asking for help, please try to follow our [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide) first. + +## Frequently Asked Questions +Some common answers to common questions and problems are on our [F.A.Q. wiki page](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions). + +## Installation +##### Official releases via the Arduino IDE v1.8+ (Windows & Linux) +1. Click the _"Sketch"_ -> _"Include Library"_ -> _"Manage Libraries..."_ Menu items. +1. Enter `IRremoteESP8266` into the _"Filter your search..."_ top right search box. +1. Click on the IRremoteESP8266 result of the search. +1. Select the version you wish to install and click _"Install"_. + +##### Manual Installation for Windows +1. Click on _"Clone or Download"_ button, then _"[Download ZIP](https://github.com/markszabo/IRremoteESP8266/archive->master.zip)"_ on the page. +1. Extract the contents of the downloaded zip file. +1. Rename the extracted folder to _"IRremoteESP8266"_. +1. Move this folder to your libraries directory. (under windows: `C:\Users\YOURNAME\Documents\Arduino\libraries\`) +1. Restart your Arduino IDE. +1. Check out the examples. + +##### Using Git to install library ( Linux ) +``` +cd ~/Arduino/libraries +git clone https://github.com/markszabo/IRremoteESP8266.git +``` +###### To Update to the latest version of the library +``` +cd ~/Arduino/libraries/IRremoteESP8266 && git pull +``` + +## Contributing +If you want to [contribute](.github/CONTRIBUTING.md#how-can-i-contribute) to this project, consider: +- [Report](.github/CONTRIBUTING.md#reporting-bugs) bugs and errors +- Ask for enhancements +- Improve our documentation +- [Create issues](.github/CONTRIBUTING.md#reporting-bugs) and [pull requests](.github/CONTRIBUTING.md#pull-requests) +- Tell other people about this library + +## Contributors +Available [here](.github/Contributors.md) + +## Library History +This library was originally based on Ken Shirriff's work (https://github.com/shirriff/Arduino-IRremote/) + +[Mark Szabo](https://github.com/markszabo/IRremoteESP8266) has updated the IRsend class to work on ESP8266 and [Sebastien Warin](https://github.com/sebastienwarin/IRremoteESP8266) the receiving & decoding part (IRrecv class). + +As of v2.0, the library was almost entirely re-written with the ESP8266's resources in mind. diff --git a/lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md b/lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md new file mode 100644 index 000000000..56e84dd89 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md @@ -0,0 +1,308 @@ +# Release Notes + +## _v2.5.2 (20181021)_ + +**[Bug Fixes]** +- Add missing send() method to IRPanasonicAC class. (#545) +- Add missing sendWhirlpoolAC() to IRMQTTServer.ino (#558) + +**[Features]** +- Add IR receiving support to IRMQTTServer. (#543) +- Pioneer support (#547) +- Add support for a second LG protocol variant. (#552) +- Support for short Panasonic A/C messages. (#553) +- Add support for Panasonic CKP series A/Cs. (#554) +- Experimental timer/clock support for Panasonic A/Cs. (#546) +- Add Made With Magic (MWM) support (#557) + +**[Misc]** +- Grammar and typo fixes (#541, #549) +- Increase Panasonic A/C message tolerances. (#542) +- Added command mode2_decode in tools/ (#557) +- General code style cleanup (#560) + + +## _v2.5.1 (20181002)_ + +**[Bug Fixes]** +- Correct the byte used for Samsung AC Swing. (#529) +- Fix not sending Samsung A/C messages in IRMQTTServer. (#529) + +**[Features]** +- Experimental support for Electra A/C messages. (#528) +- Experimental support for Panasonic A/C messages. (#535) +- Samsung A/C fixes & improvements (#529) +- IRMQTTServer v0.6.0 (#530) + +**[Misc]** +- Change required WifiManager lib version to v0.14 +- Add alias for RAWTICK to kRawTick. (#535) +- Update sendLutron() status. (#515) +- Remove leftover debug message in IRrecvDumpV2 (#526) + + +## _v2.5.0 (20180919)_ + +**[Bug Fixes]** +- Fix HTML menu error for GICABLE in IRMQTTServer. (#516) +- Fix Mitsubishi A/C mode setting. (#514) +- Add missing ',' in auto analyse tool generated code. (#513) +- Fix Fujitsu checksum validation. (#501) +- Remove errant Repeat debug statement in IRMQTTServer. (#507) + +**[Features]** +- Mitsubishi A/C decode improvements. (#514) +- Basic support for Whirlpool A/C messages. (#511) +- Basic support for Samsung A/C messages. (#512) +- Experimental support for detailed Samsung A/C messages. (#521) +- Experimental support for detailed Coolix A/C messages. (#518) +- Experimental support for Lutron protocol. (#516) +- Calculate and use average values for timings in analysing tool. (#513) + +**[Misc]** +- Style change from using #define's for constants to `const kConstantName`. +- Improve the JVC example code. + + +## _v2.4.3 (20180727)_ + +**[Bug Fixes]** +- Handle Space Gaps better in auto analyse tool. (#482) +- Correct min repeat for GICABLE in IRMQTTServer. (#494) + +**[Features]** +- Add static IP config option to IRMQTTServer (#480) +- Full decoding/encoding support for the Haier YRW02 A/C. (#485 #486 #487) + +**[Misc]** +- Update LG (28-bit) HDR mark and space timings. (#492) +- Spelling and grammar fixes (#491) + + +## _v2.4.2 (20180601)_ + +**[Bug Fixes]** +- Timing Fix: Update the period offset compensation. + +**[Features]** +- Improvements for IRMQTTServer example (#466) + + +## _v2.4.1 (20180520)_ + +**[Bug Fixes]** +- Fix crash in IRMQTTServer when compiled under Arduino IDE. (#455) +- Default bit length not set for RCMM in IRMQTTServer example. (#456) +- Bad acknowledgements for some A/C protocols in IRMQTTServer example. (#460) + +**[Features]** +- Allow disabling the use of delay() calls. (#450) +- Initial support for G.I. Cable protocol. (#458) +- Support of Hitachi A/C 13 & 53 byte messages. (#461) + +**[Misc]** +- Auto Analyse Raw Data script converted to Python. (#454) + +## _v2.4.0 (20180407)_ + +**[Bug Fixes]** +- Add missing WiFi.begin() call to IRGCTCPServer example. (#433) +- Add missing sendHaierAC() to IRMQTTServer example. (#434 & #444) +- Make mqtt clientid unique in IRMQTTServer example. (#444) + +**[Features]** + +- Initial Mitsubishi projector protocol support. (#442) +- Experimental support of Hitachi A/C messages. (#445) +- Improve transmission pulse modulation support. + Allow disabling of transmission frequency modulation.(#439) + +**[Misc]** +- IRMQTTServer example improvements. (#444) + + +## _v2.3.3 (20180302)_ + +**[Bug Fixes]** +- Ensure the IR LED is off before we start. (#405) + +**[Features]** +- Experimental decode support for Gree HVAC units (#397) +- Initial support for Haier A/Cs. (#409) +- Improve timing accuracy of unit tests. (#403) +- Rework matchData() to handle equal total data bit time protocols. (#408) + +**[Misc]** +- Add startup text to IRrecvDumpV2 and IRrecvDemo (#412) +- Tweak timings on Fujitsu A/C header (#418) +- AutoAnalyseRawData.sh: Add some support for handling larger than 64 bit codes. (#419) +- Use better comments for send GPIO in examples. (#425) + + +## _v2.3.2 (20180126)_ + +**[Bug Fixes]** +- Integer underflow caused device not to respond in `sendJVC()` (#401) + +**[Features]** +- Initial support for sending & receiving Carrier HVAC codes. (#387) +- Add Pronto HEX code support to _gc_decode_ tool. (#388) + +**[Misc]** +- Make mDNS independent of MQTT in IRMQTTServer example code. (#390 #391) + + +## _v2.3.1 (20171229)_ + +**[Bug Fixes]** +- Setting `#define SEND_FUJITSU_AC false` caused a compilation error (#375) +- Integer underflow caused huge `space()` in `sendGeneric()` (#381) + +**[Features]** +- Support sending & receiving Lasertag codes. (#374) +- Reduce the library footprint by using a new `sendGeneric()` routine. (#373) + +**[Misc]** +- Lots of grammar & typo fixes. (#378) +- Update keywords.txt for Arduino IDE users (#371) +- Update pins in examples so they are compatible with Adafruit boards. (#383) + + +## _v2.3.0 (20171208)_ + +**[Bug Fixes]** +- Panasonic-based protocols had incorrect message gap. (#358) +- Formatting error for large rawData values in example code. (#355) +- Off-by-one error in payload_copy malloc. (#337) +- Off-by-one error in unit test helper routines (#363) + +**[Features]** +- Support sending and receiving Midea A/C codes. +- Support for receiving Kelvinator A/C codes. (#332) +- Support more operation features for Daikin A/Cs. +- Support for decoding Daikin A/Cs. +- Support sending and receiving Toshiba A/Cs. (#333) +- Support sending and receiving AR-DB1 Fujitsu A/C codes. (#367) +- Add new AutoAnalyseRawData.sh & RawToGlobalCache.sh tools (#345) (#343) +- Support for MagiQuest wands. (#365) + +**[Misc]** +- Add checksum verification to Kelvinator A/C decodes. (#348) +- Changes to the threshold reporting of UNKNOWN messages (#347) +- Major re-work of Daikin A/C support. +- Sending for all A/Cs added to MQTT example code. +- MQTT example code improvements. (#334) +- IRrecvDumpV2 significant output improvements. (#363) +- Improved unit test coverage for the library. + + +## _v2.2.1 (20171025)_ + +**[Features]** +- Support for sending and decoding Nikai TV messages. (#311, #313) +- gc_decode: External utility to decode Global Cache codes. (#308, #312) +- IRMQTTServer: Example code to send IR messages via HTTP & MQTT. (#316, #323) +- Improve converting 64bit values to hexadecimal. (#318) + +**[Misc]** +- IRrecvDump.ino code is now deprecated. Use IRrecvDumpV2.ino instead. (#314) + + +## _v2.2.0 (20170922)_ + +**[Bug Fixes]** +- Add printing output of RC-MM and RC-5X protocols in example code. (#284) +- LG timing improvements based on observations (#291) + +**[Features]** +- Automatic capture timing calibration for some protocols. (#268) +- Support for creating & sending Trotec AC codes. (#279) +- Support for creating & sending Argo Ulisse 13 DCI codes. (#280 #300) +- Move to 2 microsecond timing resolution for capture of codes. (#287) +- Capture buffer changes: +- Size at runtime. (#276) +- Message timeout at runtime. (#294) +- Simplify creating & using a second buffer (#303) +- New example code: + - Trotec A/C (#279) + - LG A/C units (#289) + - Argo Ulisse 13 DCI codes. (#300) + + +## _v2.1.1 (20170711)_ + +**[Bug Fixes]** +- GlobalCache incorrectly using hardware offset for period calc. (#267) + +**[Features]** +- Support reporting of 'NEC'-like 32-bit protocols. e.g. Apple TV remote (#265) +- Add an example of sendRaw() to IRsendDemo.ino (#270) + + +## _v2.1.0 (20170704)_ + +**[Features]** +- Support for sending Pronto IR codes. (#248) +- Support for sending Fujitsu A/C codes. (#88) +- Minor improvements to examples. + + +## _v2.0.3 (20170618)_ + +**[Bug fixes]** +- Capture buffer could become corrupt after large message, breaking subsequent decodes. (#253) + + +## _v2.0.2 (20170615)_ + +**[Bug fixes]** +- Correct decode issue introduced in v2.0.1 affecting multiple protocol decoders (#243) +- Correct post-message gap for the Panasonic protocol(s) (#245) +- Incorrect display of the decoded uint64_t value in the example code. (#245) + + +## _v2.0.1 (20170614)_ + +**[Bug fixes]** +- Decoding protocols when it doesn't detect a post-command gap, and there is no more data. (#243) +- Incorrect minimum size calculation when there is no post-command gap. (#243) + + +## _v2.0.0 - 64 bit support and major improvements (20170612)_ + +**[Misc]** +- This is almost a complete re-write of the library. + +**[Features]** +- All suitable protocols now handle 64-bit data messages and are repeatable via an optional argument. +- Unit tests for all protocols. +- Far better and stricter decoding for most protocols. +- Address & command decoding for protocols where that information is available. +- Much more precise timing for generation of signals sent. +- Lower duty-cycles for some protocols. +- Several new protocols added, and some new sending and decoding routines for existing ones. +- Ability to optionally chose which protocols are included, enabling faster decoding and smaller code footprints if desired. +- Support for far larger capture buffers. (e.g. RAWLEN > 256) + +**[Bug fixes]** +- Numerous bug fixes. + + +## _v1.2.0 (20170429)_ + +**[Features]** +- Add ability to copy IR capture buffer, and continue capturing. Means faster and better IR command decoding. +- Reduce IRAM usage by 28 bytes. +- Improve capture of RC-MM & Panasonic protocols. +- Upgrade IRrecvDumpV2 to new IR capture buffer. Much fewer corrupted/truncated IR messages. + + +## _v1.1.1 (20170413)_ + +**[Bug fixes]** +- Fix a reported problem when sending the LG protocol. Preemptive fix for possible similar cases. +- Fix minor issues in examples. + +**[Features]** +- Add documentation to some examples to aid new people. +- Add ALPHA support for RC-MM protocol. (Known to be currently not 100% working.) diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/IRGCSendDemo.ino similarity index 66% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/IRGCSendDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/IRGCSendDemo.ino index b36938e3d..03c80e18b 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/IRGCSendDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/IRGCSendDemo.ino @@ -11,7 +11,8 @@ * Based on Ken Shirriff's IrsendDemo * Version 0.1 July, 2009 * - * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * An IR LED circuit *MUST* be connected to the ESP8266 on a pin + * as specified by IR_LED below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -23,12 +24,13 @@ * have enough current to drive the IR LED effectively. * * Make sure you have the IR LED polarity correct. * See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity - * * Typical digital camera/phones can be used to see if the IR LED is flashed. - * Replace the IR LED with a normal LED if you don't have a digital camera - * when debugging. + * * Typical digital camera/phones can be used to see if the IR LED is + * flashed. Replace the IR LED with a normal LED if you don't have a digital + * camera when debugging. * * Avoid using the following pins unless you really know what you are doing: * * Pin 0/D3: Can interfere with the boot/program mode & support circuits. - * * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere. + * * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will + * interfere. * * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere. * * ESP-01 modules are tricky. We suggest you use a module with more GPIOs * for your first time. e.g. ESP-12 etc. @@ -44,12 +46,15 @@ // These codes can be found in GC's Control Tower database. uint16_t Samsung_power_toggle[71] = { - 38000, 1, 1, 170, 170, 20, 63, 20, 63, 20, 63, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 63, 20, 63, 20, 63, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 63, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 63, 20, - 20, 20, 63, 20, 63, 20, 63, 20, 63, 20, 63, 20, 63, 20, 1798}; + 38000, 1, 1, 170, 170, 20, 63, 20, 63, 20, 63, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 63, 20, 63, 20, 63, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 63, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 63, 20, 20, 20, 63, 20, + 63, 20, 63, 20, 63, 20, 63, 20, 63, 20, 1798}; -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +#define IR_LED 4 // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(IR_LED); // Set the GPIO to be used to sending the message. void setup() { irsend.begin(); @@ -58,6 +63,10 @@ void setup() { void loop() { Serial.println("Toggling power"); +#if SEND_GLOBALCACHE irsend.sendGC(Samsung_power_toggle, 71); +#else // SEND_GLOBALCACHE + Serial.println("Can't send because SEND_GLOBALCACHE has been disabled."); +#endif // SEND_GLOBALCACHE delay(10000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/IRGCTCPServer.ino similarity index 89% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/IRGCTCPServer.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/IRGCTCPServer.ino index 2fd38be42..69f7299fb 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/IRGCTCPServer.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/IRGCTCPServer.ino @@ -9,7 +9,7 @@ * For more codes, visit: https://irdb.globalcache.com/ * * How to use this program: - * 1) Update "ssid" and "password" below for your WIFI network. + * 1) Update "kSsid" and "kPassword" below for your WIFI network. * 2) Compile and upload the sketch to your ESP8266 module. * 3) (Optional) Use the serial connection to confirm it started and get the * IP address. @@ -46,14 +46,16 @@ #include #include -const char* ssid = "..."; // Put your WIFI SSID here. -const char* password = "..."; // Put your WIFI password here. +const char* kSsid = "..."; // Put your WIFI SSID here. +const char* kPassword = "..."; // Put your WIFI Password here. WiFiServer server(4998); // Uses port 4998. WiFiClient client; uint16_t *code_array; -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +#define IR_LED 4 // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(IR_LED); // Set the GPIO to be used to sending the message. void sendGCString(String str) { int16_t index; @@ -89,7 +91,9 @@ void sendGCString(String str) { count++; } while (index != -1); +#if SEND_GLOBALCACHE irsend.sendGC(code_array, count); // All done. Send it. +#endif // SEND_GLOBALCACHE free(code_array); // Free up the memory allocated. } @@ -99,7 +103,7 @@ void setup() { delay(100); Serial.println(" "); Serial.println("IR TCP Server"); - + WiFi.begin(kSsid, kPassword); while (WiFi.status() != WL_CONNECTED) { delay(900); Serial.print("."); @@ -107,7 +111,7 @@ void setup() { server.begin(); IPAddress myAddress = WiFi.localIP(); - Serial.println(myAddress); + Serial.println(myAddress.toString()); irsend.begin(); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/IRMQTTServer.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino similarity index 55% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/IRMQTTServer.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino index e2c1f81d8..7851cf5dc 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/IRMQTTServer.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino @@ -1,9 +1,11 @@ /* - * Send arbitary IR codes via a web server or MQTT. - * Copyright David Conran 2016 - * Version 0.3 Oct, 2017 + * Send & receive arbitrary IR codes via a web server or MQTT. + * Copyright David Conran 2016, 2017, 2018 * - * NOTE: An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). See IR_LED + * NOTE: An IR LED circuit *MUST* be connected to ESP8266 GPIO4 (D2) if + * you want to send IR messages. See IR_LED below. + * A compatible IR RX modules *MUST* be connected to ESP8266 GPIO14 (D5) + * if you want to capture & decode IR nessages. See IR_RX below. * * WARN: This is very advanced & complicated example code. Not for beginners. * You are strongly suggested to try & look at other example code first. @@ -11,10 +13,14 @@ * # Instructions * * ## Before First Boot (i.e. Compile time) - * - Set the MQTT_SERVER define below to the address of your MQTT server. + * - Either: + * o Set the MQTT_SERVER define below to the address of your MQTT server. + * or + * o Disable MQTT by commenting out the line "#define MQTT_ENABLE" down below. + * * - Arduino IDE: * o Install the following libraries via Library Manager - * - WiFiManager (https://github.com/tzapu/WiFiManager) + * - WiFiManager (https://github.com/tzapu/WiFiManager) (Version >= 0.14) * - PubSubClient (https://pubsubclient.knolleary.net/) * o You MUST change to have the following (or larger) value: * #define MQTT_MAX_PACKET_SIZE 512 @@ -63,13 +69,17 @@ * GlobalCache (31) & "40000,1,1,96,..." (Sony Vol Up) * 25,Rrepeats,hex_code_string e.g. 25,R1,0000,006E,0022,0002,0155,00AA,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0040,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0040,0015,0040,0015,0040,0015,0640,0155,0055,0015,0E40 * Pronto (25), 1 repeat, & "0000 006E 0022 0002 ..." (Sherwood Amp Tape Input) - * 18,really_long_hexcode e.g. 18,190B8050000000E0190B8070000010f0 + * ac_protocol_num,really_long_hexcode e.g. 18,190B8050000000E0190B8070000010F0 * Kelvinator (18) Air Con on, Low Fan, 25 deg etc. + * NOTE: Ensure you zero-pad to the correct number of + * digits for the bit/byte size you want to send + * as some A/C units have units have different + * sized messages. e.g. Fujitsu A/C units. * In short: * No spaces after/before commas. * Values are comma separated. * The first value is always in Decimal. - * For simple protocols, the next value (hexcode) is always hexidecimal. + * For simple protocols, the next value (hexcode) is always hexadecimal. * The optional bit size is in decimal. * * Unix command line usage example: @@ -87,6 +97,19 @@ * # Listen to MQTT acknowledgements. * $ mosquitto_sub -h 10.20.0.253 -t ir_server/sent * + * Incoming IR messages (from an IR remote control) will be transmitted to + * the MQTT topic 'ir_server/received'. The MQTT message will be formatted + * similar to what is required to for the 'sent' topic. + * e.g. "3,C1A2F00F,32" (Protocol,Value,Bits) for simple codes + * or "18,110B805000000060110B807000001070" (Protocol,Value) for complex codes + * Note: If the protocol is listed as -1, then that is an UNKNOWN IR protocol. + * You can't use that to recreate/resend an IR message. It's only for + * matching purposes and shouldn't be trusted. + * + * Unix command line usage example: + * # Listen via MQTT for IR messages captured by this server. + * $ mosquitto_sub -h 10.20.0.253 -t ir_server/received + * * If DEBUG is turned on, there is additional information printed on the Serial * Port. * @@ -111,6 +134,7 @@ #include #include #include +#include #include #include #ifdef MQTT_ENABLE @@ -124,22 +148,43 @@ #include #include -// Configuration paramters -#define IR_LED 4 // GPIO the IR LED is connected to/controlled by. GPIO 4 = D2. -#define HTTP_PORT 80 // The port the HTTP server is listening on. +// Configuration parameters +// GPIO the IR LED is connected to/controlled by. GPIO 4 = D2. +#define IR_LED 4 +// define IR_LED 3 // For an ESP-01 we suggest you use RX/GPIO3/Pin 7. +// +// GPIO the IR RX module is connected to/controlled by. GPIO 14 = D5. +// Comment this out to disable receiving/decoding IR messages entirely. +#define IR_RX 14 +const uint16_t kHttpPort = 80; // The TCP port the HTTP server is listening on. +// Name of the device you want in mDNS. +// NOTE: Changing this will change the MQTT path too unless you override it +// via MQTTprefix below. +#define HOSTNAME "ir_server" + +// We obtain our network config via DHCP by default but allow an easy way to +// use a static IP config. +#define USE_STATIC_IP false // Change to 'true' if you don't want to use DHCP. +#if USE_STATIC_IP +const IPAddress kIPAddress = IPAddress(10, 0, 1, 78); +const IPAddress kGateway = IPAddress(10, 0, 1, 1); +const IPAddress kSubnetMask = IPAddress(255, 255, 255, 0); +#endif // USE_STATIC_IP #ifdef MQTT_ENABLE // Address of your MQTT server. #define MQTT_SERVER "10.20.0.253" // <=- CHANGE ME -#define MQTT_PORT 1883 // Default port used by MQTT servers. +const uint16_t kMqttPort = 1883; // Default port used by MQTT servers. // Set if your MQTT server requires a Username & Password to connect. const char* mqtt_user = ""; const char* mqtt_password = ""; -#define MQTT_RECONNECT_TIME 5000 // Delay(ms) between reconnect tries. +const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries. -#define MQTTprefix "ir_server" +#define MQTTprefix HOSTNAME // Change this if you want the MQTT topic to be + // independent of the hostname. #define MQTTack MQTTprefix "/sent" // Topic we send back acknowledgements on #define MQTTcommand MQTTprefix "/send" // Topic we get new commands from. +#define MQTTrecv MQTTprefix "/received" // Topic we send received IRs to. #endif // MQTT_ENABLE // HTML arguments we will parse for IR code information. @@ -147,27 +192,71 @@ const char* mqtt_password = ""; #define argData "code" #define argBits "bits" #define argRepeat "repeats" -#define DEBUG True +// Let's use a larger than normal buffer so we can handle AirCon remote codes. +const uint16_t kCaptureBufferSize = 1024; +#if DECODE_AC +// Some A/C units have gaps in their protocols of ~40ms. e.g. Kelvinator +// A value this large may swallow repeats of some protocols +const uint8_t kCaptureTimeout = 50; +#else // DECODE_AC +// Suits most messages, while not swallowing many repeats. +const uint8_t kCaptureTimeout = 15; +#endif // DECODE_AC +// Ignore unknown messages with <10 pulses +const uint16_t kMinUnknownSize = 20; + +#define _MY_VERSION_ "v0.7.0" + +// Disable debug output if any of the IR pins are on the TX (D1) pin. +#if (IR_LED != 1 && IR_RX != 1) +#undef DEBUG +#define DEBUG true // Change to 'false' to disable all serial output. +#else +#undef DEBUG +#define DEBUG false +#endif +// NOTE: Make sure you set your Serial Monitor to the same speed. +#define BAUD_RATE 115200 // Serial port Baud rate. // Globals -ESP8266WebServer server(HTTP_PORT); +ESP8266WebServer server(kHttpPort); IRsend irsend = IRsend(IR_LED); +#ifdef IR_RX +IRrecv irrecv(IR_RX, kCaptureBufferSize, kCaptureTimeout, true); +decode_results capture; // Somewhere to store inbound IR messages. +#endif // IR_RX MDNSResponder mdns; WiFiClient espClient; WiFiManager wifiManager; uint16_t *codeArray; -uint32_t lastReconnectAttempt = 0; // MQTT last attemps reconnection number +uint32_t lastReconnectAttempt = 0; // MQTT last attempt reconnection number bool boot = true; -bool ir_lock = false; // Primative locking for gating the IR LED. +bool ir_lock = false; // Primitive locking for gating the IR LED. +uint32_t sendReqCounter = 0; +bool lastSendSucceeded = false; // Store the success status of the last send. +uint32_t lastSendTime = 0; +int8_t offset; // The calculated period offset for this chip and library. #ifdef MQTT_ENABLE +String lastMqttCmd = "None"; +uint32_t lastMqttCmdTime = 0; +uint32_t lastConnectedTime = 0; +uint32_t lastDisconnectedTime = 0; +uint32_t mqttDisconnectCounter = 0; +bool wasConnected = true; +#ifdef IR_RX +String lastIrReceived = "None"; +uint32_t lastIrReceivedTime = 0; +uint32_t irRecvCounter = 0; +#endif // IR_RX + + // MQTT client parameters void callback(char* topic, byte* payload, unsigned int length); -PubSubClient mqtt_client(MQTT_SERVER, MQTT_PORT, callback, espClient); +PubSubClient mqtt_client(MQTT_SERVER, kMqttPort, callback, espClient); // Create a unique MQTT client id. -const char* mqtt_clientid = String(MQTTprefix + - String(ESP.getChipId(), HEX)).c_str(); +String mqtt_clientid = MQTTprefix + String(ESP.getChipId(), HEX); #endif // MQTT_ENABLE // Debug messages get sent to the serial port. @@ -178,6 +267,50 @@ void debug(String str) { #endif // DEBUG } +String timeSince(uint32_t const start) { + if (start == 0) + return "Never"; + uint32_t diff = 0; + uint32_t now = millis(); + if (start < now) + diff = now - start; + else + diff = UINT32_MAX - start + now; + diff /= 1000; // Convert to seconds. + if (diff == 0) return "Now"; + + // Note: millis() can only count up to 45 days, so uint8_t is safe. + uint8_t days = diff / (60 * 60 * 24); + uint8_t hours = (diff / (60 * 60)) % 24; + uint8_t minutes = (diff / 60) % 60; + uint8_t seconds = diff % 60; + + String result = ""; + if (days) + result += String(days) + " day"; + if (days > 1) result += "s"; + if (hours) + result += " " + String(hours) + " hour"; + if (hours > 1) result += "s"; + if (minutes) + result += " " + String(minutes) + " minute"; + if (minutes > 1) result += "s"; + if (seconds) + result += " " + String(seconds) + " second"; + if (seconds > 1) result += "s"; + result.trim(); + return result + " ago"; +} + +// Quick and dirty check for any unsafe chars in a string +// that may cause HTML shenanigans. e.g. An XSS. +bool hasUnsafeHTMLChars(String input) { + static char unsafe[] = "';!-\"<>=&{}()"; + for (uint8_t i = 0; unsafe[i]; i++) + if (input.indexOf(unsafe[i]) != -1) return true; + return false; +} + // Root web page with example usage etc. void handleRoot() { server.send(200, "text/html", @@ -185,13 +318,43 @@ void handleRoot() { "" "

ESP8266 IR MQTT Server

" "

" - "

Connection details

" - "

IP address: " + WiFi.localIP().toString() + "

" + "

Information

" + "

IP address: " + WiFi.localIP().toString() + "
" + "Booted: " + timeSince(1) + "
" + + "Version: " _MY_VERSION_ "
" + "Period Offset: " + String(offset) + "us
" + "IR Lib Version: " _IRREMOTEESP8266_VERSION_ "
" + "ESP8266 Core Version: " + ESP.getCoreVersion() + "
" + "IR Send GPIO: " + String(IR_LED) + "
" + "Total send requests: " + String(sendReqCounter) + "
" + "Last message sent: " + String(lastSendSucceeded ? "Ok" : "FAILED") + + " (" + timeSince(lastSendTime) + ")
" +#ifdef IR_RX + "IR Recv GPIO: " + String(IR_RX) + "
" + "Total IR Received: " + String(irRecvCounter) + "
" + "Last IR Received: " + lastIrReceived + + " (" + timeSince(lastIrReceivedTime) + ")
" +#endif // IR_RX + "

" #ifdef MQTT_ENABLE - "

MQTT server: " MQTT_SERVER ":" + String(MQTT_PORT) + " ("+ - (mqtt_client.connected() ? "Connected" : "Disconnected") + ")
" + "

MQTT Information

" + "

Server: " MQTT_SERVER ":" + String(kMqttPort) + " (" + + (mqtt_client.connected() ? "Connected " + timeSince(lastDisconnectedTime) + : "Disconnected " + timeSince(lastConnectedTime)) + + ")
" + "Disconnections: " + String(mqttDisconnectCounter - 1) + "
" + "Client id: " + mqtt_clientid + "
" "Command topic: " MQTTcommand "
" - "Acknowledgements topic: " MQTTack "

" + "Acknowledgements topic: " MQTTack "
" +#ifdef IR_RX + "IR Received topic: " MQTTrecv "
" +#endif // IR_RX + "Last MQTT command seen: " + + // lastMqttCmd is unescaped untrusted input. + // Avoid any possible HTML/XSS when displaying it. + (hasUnsafeHTMLChars(lastMqttCmd) ? + "Contains unsafe HTML characters" : lastMqttCmd) + + " (" + timeSince(lastMqttCmdTime) + ")

" #endif // MQTT_ENABLE "

" "

Hardcoded examples

" @@ -222,15 +385,24 @@ void handleRoot() { "Type: " "" " Repeats: " @@ -305,11 +479,32 @@ void handleRoot() { " " "" "

" - "

Send a Kelvinator A/C IR message

" + "

Send an Air Conditioner IR message

" "

" - "" - "State code: 0x" + "Type: " + "" + " State code: 0x" + "" " " "
" "

" @@ -340,26 +535,245 @@ void handleReset() { delay(1000); } -// Parse a Kelvinator A/C Hex String/code and send it. -void parseStringAndSendKelv(const String str) { - // str should be a 32 digit hexidecimal string. - uint8_t offset = 0; - uint8_t codeArray[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +// Parse an Air Conditioner A/C Hex String/code and send it. +// Args: +// irType: Nr. of the protocol we need to send. +// str: A hexadecimal string containing the state to be sent. +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendAirCon(const uint16_t irType, const String str) { + uint8_t strOffset = 0; + uint8_t state[kStateSizeMax] = {0}; // All array elements are set to 0. + uint16_t stateSize = 0; + if (str.startsWith("0x") || str.startsWith("0X")) - offset = 2; - for (int i = 0; i < 32; i++) { - unsigned char c = tolower(str[i + offset]); - uint8_t entry = 0; + strOffset = 2; + // Calculate how many hexadecimal characters there are. + uint16_t inputLength = str.length() - strOffset; + if (inputLength == 0) { + debug("Zero length AirCon code encountered. Ignored."); + return false; // No input. Abort. + } + + switch (irType) { // Get the correct state size for the protocol. + case KELVINATOR: + stateSize = kKelvinatorStateLength; + break; + case TOSHIBA_AC: + stateSize = kToshibaACStateLength; + break; + case DAIKIN: + stateSize = kDaikinStateLength; + break; + case ELECTRA_AC: + stateSize = kElectraAcStateLength; + break; + case MITSUBISHI_AC: + stateSize = kMitsubishiACStateLength; + break; + case PANASONIC_AC: + stateSize = kPanasonicAcStateLength; + break; + case TROTEC: + stateSize = kTrotecStateLength; + break; + case ARGO: + stateSize = kArgoStateLength; + break; + case GREE: + stateSize = kGreeStateLength; + break; + case FUJITSU_AC: + // Fujitsu has four distinct & different size states, so make a best guess + // which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, + (uint16_t) (kFujitsuAcStateLengthShort - 1)); + // If we think it isn't a "short" message. + if (stateSize > kFujitsuAcStateLengthShort) + // Then it has to be at least the smaller version of the "normal" size. + stateSize = std::max(stateSize, (uint16_t) (kFujitsuAcStateLength - 1)); + // Lastly, it should never exceed the maximum "normal" size. + stateSize = std::min(stateSize, kFujitsuAcStateLength); + break; + case HAIER_AC: + stateSize = kHaierACStateLength; + break; + case HAIER_AC_YRW02: + stateSize = kHaierACYRW02StateLength; + break; + case HITACHI_AC: + stateSize = kHitachiAcStateLength; + break; + case HITACHI_AC1: + stateSize = kHitachiAc1StateLength; + break; + case HITACHI_AC2: + stateSize = kHitachiAc2StateLength; + break; + case WHIRLPOOL_AC: + stateSize = kWhirlpoolAcStateLength; + break; + case SAMSUNG_AC: + // Samsung has two distinct & different size states, so make a best guess + // which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, (uint16_t) (kSamsungAcStateLength)); + // If we think it isn't a "normal" message. + if (stateSize > kSamsungAcStateLength) + // Then it probably the extended size. + stateSize = std::max(stateSize, + (uint16_t) (kSamsungAcExtendedStateLength)); + // Lastly, it should never exceed the maximum "extended" size. + stateSize = std::min(stateSize, kSamsungAcExtendedStateLength); + break; + case MWM: + // MWM has variable size states, so make a best guess + // which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, (uint16_t) 3); + // Cap the maximum size. + stateSize = std::min(stateSize, kStateSizeMax); + break; + default: // Not a protocol we expected. Abort. + debug("Unexpected AirCon protocol detected. Ignoring."); + return false; + } + if (inputLength > stateSize * 2) { + debug("AirCon code to large for the given protocol."); + return false; + } + + // Ptr to the least significant byte of the resulting state for this protocol. + uint8_t *statePtr = &state[stateSize - 1]; + + // Convert the string into a state array of the correct length. + for (uint16_t i = 0; i < inputLength; i++) { + // Grab the next least sigificant hexadecimal digit from the string. + uint8_t c = tolower(str[inputLength + strOffset - i - 1]); if (isxdigit(c)) { if (isdigit(c)) - codeArray[i / 2] += c - '0'; + c -= '0'; else - codeArray[i / 2] += c - 'a' + 10; + c = c - 'a' + 10; + } else { + debug("Aborting! Non-hexadecimal char found in AirCon state: " + str); + return false; + } + if (i % 2 == 1) { // Odd: Upper half of the byte. + *statePtr += (c << 4); + statePtr--; // Advance up to the next least significant byte of state. + } else { // Even: Lower half of the byte. + *statePtr = c; } - if (i % 2 == 0) - codeArray[i / 2] <<= 4; } - irsend.sendKelvinator(reinterpret_cast(codeArray)); + + // Make the appropriate call for the protocol type. + switch (irType) { +#if SEND_KELVINATOR + case KELVINATOR: + irsend.sendKelvinator(reinterpret_cast(state)); + break; +#endif +#if SEND_TOSHIBA_AC + case TOSHIBA_AC: + irsend.sendToshibaAC(reinterpret_cast(state)); + break; +#endif +#if SEND_DAIKIN + case DAIKIN: + irsend.sendDaikin(reinterpret_cast(state)); + break; +#endif +#if MITSUBISHI_AC + case MITSUBISHI_AC: + irsend.sendMitsubishiAC(reinterpret_cast(state)); + break; +#endif +#if SEND_TROTEC + case TROTEC: + irsend.sendTrotec(reinterpret_cast(state)); + break; +#endif +#if SEND_ARGO + case ARGO: + irsend.sendArgo(reinterpret_cast(state)); + break; +#endif +#if SEND_GREE + case GREE: + irsend.sendGree(reinterpret_cast(state)); + break; +#endif +#if SEND_FUJITSU_AC + case FUJITSU_AC: + irsend.sendFujitsuAC(reinterpret_cast(state), stateSize); + break; +#endif +#if SEND_HAIER_AC + case HAIER_AC: + irsend.sendHaierAC(reinterpret_cast(state)); + break; +#endif +#if SEND_HAIER_AC_YRW02 + case HAIER_AC_YRW02: + irsend.sendHaierACYRW02(reinterpret_cast(state)); + break; +#endif +#if SEND_HITACHI_AC + case HITACHI_AC: + irsend.sendHitachiAC(reinterpret_cast(state)); + break; +#endif +#if SEND_HITACHI_AC1 + case HITACHI_AC1: + irsend.sendHitachiAC1(reinterpret_cast(state)); + break; +#endif +#if SEND_HITACHI_AC2 + case HITACHI_AC2: + irsend.sendHitachiAC2(reinterpret_cast(state)); + break; +#endif +#if SEND_WHIRLPOOL_AC + case WHIRLPOOL_AC: + irsend.sendWhirlpoolAC(reinterpret_cast(state)); + break; +#endif +#if SEND_SAMSUNG_AC + case SAMSUNG_AC: + irsend.sendSamsungAC(reinterpret_cast(state), stateSize); + break; +#endif +#if SEND_ELECTRA_AC + case ELECTRA_AC: + irsend.sendElectraAC(reinterpret_cast(state)); + break; +#endif +#if SEND_PANASONIC_AC + case PANASONIC_AC: + irsend.sendPanasonicAC(reinterpret_cast(state)); + break; +#endif +#if SEND_MWM_ + case MWM: + irsend.sendMWM(reinterpret_cast(state), stateSize); + break; +#endif + default: + debug("Unexpected AirCon type in send request. Not sent."); + return false; + } + return true; // We were successful as far as we can tell. } // Count how many values are in the String. @@ -399,6 +813,7 @@ uint16_t * newCodeArray(const uint16_t size) { return result; } +#if SEND_GLOBALCACHE // Parse a GlobalCache String/code and send it. // Args: // str: A GlobalCache formatted String of comma separated numbers. @@ -407,7 +822,9 @@ uint16_t * newCodeArray(const uint16_t size) { // 20,20,20,20,20,20,20,20,20,20,20,20,20,63,20,20,20,63,20,63,20, // 63,20,63,20,63,20,63,20,1798" // Note: The leading "1:1,1," of normal GC codes should be removed. -void parseStringAndSendGC(const String str) { +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendGC(const String str) { uint16_t count; uint16_t *code_array; String tmp_str; @@ -437,22 +854,29 @@ void parseStringAndSendGC(const String str) { irsend.sendGC(code_array, count); // All done. Send it. free(code_array); // Free up the memory allocated. + if (count > 0) + return true; // We sent something. + return false; // We probably didn't. } +#endif // SEND_GLOBALCACHE +#if SEND_PRONTO // Parse a Pronto Hex String/code and send it. // Args: -// str: A comma-separated String of nr. of repeats, then hexidecimal numbers. +// str: A comma-separated String of nr. of repeats, then hexadecimal numbers. // e.g. "R1,0000,0067,0000,0015,0060,0018,0018,0018,0030,0018,0030,0018, // 0030,0018,0018,0018,0030,0018,0018,0018,0018,0018,0030,0018, // 0018,0018,0030,0018,0030,0018,0030,0018,0018,0018,0018,0018, // 0030,0018,0018,0018,0018,0018,0030,0018,0018,03f6" // or // "0000,0067,0000,0015,0060,0018". i.e. without the Repeat value -// Requires at least PRONTO_MIN_LENGTH comma-separated values. +// Requires at least kProntoMinLength comma-separated values. // sendPronto() only supports raw pronto code types, thus so does this. // repeats: Nr. of times the message is to be repeated. // This value is ignored if an embeddd repeat is found in str. -void parseStringAndSendPronto(const String str, uint16_t repeats) { +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendPronto(const String str, uint16_t repeats) { uint16_t count; uint16_t *code_array; int16_t index = -1; @@ -470,8 +894,8 @@ void parseStringAndSendPronto(const String str, uint16_t repeats) { count--; // We don't count the repeats value as part of the code array. } - // We need at least PRONTO_MIN_LENGTH values for the code part. - if (count < PRONTO_MIN_LENGTH) return; + // We need at least kProntoMinLength values for the code part. + if (count < kProntoMinLength) return false; // Now we know how many there are, allocate the memory to store them all. code_array = newCodeArray(count); @@ -481,7 +905,7 @@ void parseStringAndSendPronto(const String str, uint16_t repeats) { count = 0; do { index = str.indexOf(',', start_from); - // Convert the hexidecimal value string to an unsigned integer. + // Convert the hexadecimal value string to an unsigned integer. code_array[count] = strtoul(str.substring(start_from, index).c_str(), NULL, 16); start_from = index + 1; @@ -490,15 +914,22 @@ void parseStringAndSendPronto(const String str, uint16_t repeats) { irsend.sendPronto(code_array, count, repeats); // All done. Send it. free(code_array); // Free up the memory allocated. + if (count > 0) + return true; // We sent something. + return false; // We probably didn't. } +#endif // SEND_PRONTO -// Parse a IRremote Raw Hex String/code and send it. +#if SEND_RAW +// Parse an IRremote Raw Hex String/code and send it. // Args: // str: A comma-separated String containing the freq and raw IR data. // e.g. "38000,9000,4500,600,1450,600,900,650,1500,..." // Requires at least two comma-separated values. // First value is the transmission frequency in Hz or kHz. -void parseStringAndSendRaw(const String str) { +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendRaw(const String str) { uint16_t count; uint16_t freq = 38000; // Default to 38kHz. uint16_t *raw_array; @@ -508,7 +939,7 @@ void parseStringAndSendRaw(const String str) { // We expect the frequency as the first comma separated value, so we need at // least two values. If not, bail out. - if (count < 2) return; + if (count < 2) return false; count--; // We don't count the frequency value as part of the raw array. // Now we know how many there are, allocate the memory to store them all. @@ -530,7 +961,11 @@ void parseStringAndSendRaw(const String str) { irsend.sendRaw(raw_array, count, freq); // All done. Send it. free(raw_array); // Free up the memory allocated. + if (count > 0) + return true; // We sent something. + return false; // We probably didn't. } +#endif // SEND_RAW // Parse the URL args to find the IR code. void handleIr() { @@ -553,7 +988,8 @@ void handleIr() { repeat = atoi(server.arg(i).c_str()); } debug("New code received via HTTP"); - sendIRCode(ir_type, data, data_str.c_str(), nbits, repeat); + lastSendSucceeded = sendIRCode(ir_type, data, data_str.c_str(), nbits, + repeat); handleRoot(); } @@ -576,6 +1012,10 @@ void setup_wifi() { // We start by connecting to a WiFi network wifiManager.setTimeout(300); // Time out after 5 mins. +#if USE_STATIC_IP + // Use a static IP config rather than the one supplied via DHCP. + wifiManager.setSTAStaticIPConfig(kIPAddress, kGateway, kSubnetMask); +#endif // USE_STATIC_IP if (!wifiManager.autoConnect()) { debug("Wifi failed to connect and hit timeout."); delay(3000); @@ -584,14 +1024,27 @@ void setup_wifi() { delay(5000); } - debug("WiFi connected. IP address: " + WiFi.localIP()); + debug("WiFi connected. IP address: " + WiFi.localIP().toString()); } void setup(void) { irsend.begin(); + offset = irsend.calibrate(); +#if IR_RX +#if DECODE_HASH + // Ignore messages with less than minimum on or off pulses. + irrecv.setUnknownThreshold(kMinUnknownSize); +#endif // DECODE_HASH + irrecv.enableIRIn(); // Start the receiver +#endif // IR_RX #ifdef DEBUG - Serial.begin(115200); + // Use SERIAL_TX_ONLY so that the RX pin can be freed up for GPIO/IR use. + Serial.begin(BAUD_RATE, SERIAL_8N1, SERIAL_TX_ONLY); + while (!Serial) // Wait for the serial connection to be establised. + delay(50); + Serial.println(); + debug("IRMQTTServer " _MY_VERSION_" has booted."); #endif // DEBUG setup_wifi(); @@ -601,7 +1054,7 @@ void setup(void) { lastReconnectAttempt = 0; - if (mdns.begin(MQTTprefix, WiFi.localIP())) { + if (mdns.begin(HOSTNAME, WiFi.localIP())) { debug("MDNS responder started"); } @@ -667,12 +1120,13 @@ bool reconnect() { while (!mqtt_client.connected() && tries <= 3) { int connected = false; // Attempt to connect - debug("Attempting MQTT connection to " MQTT_SERVER ":" + String(MQTT_PORT) + + debug("Attempting MQTT connection to " MQTT_SERVER ":" + String(kMqttPort) + "... "); if (mqtt_user && mqtt_password) - connected = mqtt_client.connect(mqtt_clientid, mqtt_user, mqtt_password); + connected = mqtt_client.connect(mqtt_clientid.c_str(), mqtt_user, + mqtt_password); else - connected = mqtt_client.connect(mqtt_clientid); + connected = mqtt_client.connect(mqtt_clientid.c_str()); if (connected) { // Once connected, publish an announcement... mqtt_client.publish(MQTTack, "Connected"); @@ -692,32 +1146,57 @@ bool reconnect() { #endif // MQTT_ENABLE void loop(void) { - server.handleClient(); + server.handleClient(); // Handle any web activity #ifdef MQTT_ENABLE + uint32_t now = millis(); // MQTT client connection management if (!mqtt_client.connected()) { - uint32_t now = millis(); - // Reconnect if it's longer than MQTT_RECONNECT_TIME since we last tried. - if (now - lastReconnectAttempt > MQTT_RECONNECT_TIME) { + if (wasConnected) { + lastDisconnectedTime = now; + wasConnected = false; + mqttDisconnectCounter++; + } + // Reconnect if it's longer than kMqttReconnectTime since we last tried. + if (now - lastReconnectAttempt > kMqttReconnectTime) { lastReconnectAttempt = now; debug("client mqtt not connected, trying to connect"); // Attempt to reconnect if (reconnect()) { lastReconnectAttempt = 0; + wasConnected = true; if (boot) { mqtt_client.publish(MQTTack, "IR Server just booted"); boot = false; } else { - mqtt_client.publish(MQTTack, "IR Server just (re)connected to MQTT"); + String text = "IR Server just (re)connected to MQTT. " + "Lost connection about " + timeSince(lastConnectedTime); + mqtt_client.publish(MQTTack, text.c_str()); } + lastConnectedTime = now; + debug("successful client mqtt connection"); } } } else { + lastConnectedTime = now; // MQTT loop mqtt_client.loop(); } #endif // MQTT_ENABLE +#ifdef IR_RX + // Check if an IR code has been received via the IR RX module. + if (irrecv.decode(&capture)) { + lastIrReceivedTime = millis(); + lastIrReceived = String(capture.decode_type) + "," + + resultToHexidecimal(&capture); + // If it isn't an AC code, add the bits. + if (!hasACState(capture.decode_type)) + lastIrReceived += "," + String(capture.bits); + mqtt_client.publish(MQTTrecv, lastIrReceived.c_str()); + irRecvCounter++; + debug("Incoming IR message sent to MQTT: " + lastIrReceived); + } +#endif // IR_RX delay(100); } @@ -749,149 +1228,291 @@ uint64_t getUInt64fromHex(char const *str) { // code_str: The unparsed code to be sent. Used by complex protocol encodings. // bits: Nr. of bits in the protocol. 0 means use the protocol's default. // repeat: Nr. of times the message is to be repeated. (Not all protcols.) -void sendIRCode(int const ir_type, uint64_t const code, char const * code_str, +// Returns: +// bool: Successfully sent or not. +bool sendIRCode(int const ir_type, uint64_t const code, char const * code_str, uint16_t bits, uint16_t repeat) { // Create a pseudo-lock so we don't try to send two codes at the same time. while (ir_lock) delay(20); ir_lock = true; + bool success = true; // Assume success. + // send the IR message. switch (ir_type) { +#if SEND_RC5 case RC5: // 1 if (bits == 0) - bits = RC5_BITS; + bits = kRC5Bits; irsend.sendRC5(code, bits, repeat); break; +#endif +#if SEND_RC6 case RC6: // 2 if (bits == 0) - bits = RC6_MODE0_BITS; + bits = kRC6Mode0Bits; irsend.sendRC6(code, bits, repeat); break; +#endif +#if SEND_NEC case NEC: // 3 if (bits == 0) - bits = NEC_BITS; + bits = kNECBits; irsend.sendNEC(code, bits, repeat); break; +#endif +#if SEND_SONY case SONY: // 4 if (bits == 0) - bits = SONY_12_BITS; - repeat = std::max(repeat, (uint16_t) SONY_MIN_REPEAT); + bits = kSony12Bits; + repeat = std::max(repeat, kSonyMinRepeat); irsend.sendSony(code, bits, repeat); break; +#endif +#if SEND_PANASONIC case PANASONIC: // 5 if (bits == 0) - bits = PANASONIC_BITS; + bits = kPanasonicBits; irsend.sendPanasonic64(code, bits, repeat); break; +#endif +#if SEND_JVC case JVC: // 6 if (bits == 0) - bits = JVC_BITS; + bits = kJvcBits; irsend.sendJVC(code, bits, repeat); break; +#endif +#if SEND_SAMSUNG case SAMSUNG: // 7 if (bits == 0) - bits = SAMSUNG_BITS; + bits = kSamsungBits; irsend.sendSAMSUNG(code, bits, repeat); break; +#endif +#if SEND_WHYNTER case WHYNTER: // 8 if (bits == 0) - bits = WHYNTER_BITS; + bits = kWhynterBits; irsend.sendWhynter(code, bits, repeat); break; +#endif +#if SEND_AIWA_RC_T501 case AIWA_RC_T501: // 9 if (bits == 0) - bits = AIWA_RC_T501_BITS; - repeat = std::max(repeat, (uint16_t) AIWA_RC_T501_MIN_REPEAT); + bits = kAiwaRcT501Bits; + repeat = std::max(repeat, kAiwaRcT501MinRepeats); irsend.sendAiwaRCT501(code, bits, repeat); break; +#endif +#if SEND_LG case LG: // 10 if (bits == 0) - bits = LG_BITS; + bits = kLgBits; irsend.sendLG(code, bits, repeat); break; +#endif +#if SEND_MITSUBISHI case MITSUBISHI: // 12 if (bits == 0) - bits = MITSUBISHI_BITS; - repeat = std::max(repeat, (uint16_t) MITSUBISHI_MIN_REPEAT); + bits = kMitsubishiBits; + repeat = std::max(repeat, kMitsubishiMinRepeat); irsend.sendMitsubishi(code, bits, repeat); break; +#endif +#if SEND_DISH case DISH: // 13 if (bits == 0) - bits = DISH_BITS; - repeat = std::max(repeat, (uint16_t) DISH_MIN_REPEAT); + bits = kDishBits; + repeat = std::max(repeat, kDishMinRepeat); irsend.sendDISH(code, bits, repeat); break; +#endif +#if SEND_SHARP case SHARP: // 14 if (bits == 0) - bits = SHARP_BITS; + bits = kSharpBits; irsend.sendSharpRaw(code, bits, repeat); break; +#endif +#if SEND_COOLIX case COOLIX: // 15 if (bits == 0) - bits = COOLIX_BITS; + bits = kCoolixBits; irsend.sendCOOLIX(code, bits, repeat); break; +#endif + case DAIKIN: // 16 + case KELVINATOR: // 18 + case MITSUBISHI_AC: // 20 + case GREE: // 24 + case ARGO: // 27 + case TROTEC: // 28 + case TOSHIBA_AC: // 32 + case FUJITSU_AC: // 33 + case HAIER_AC: // 38 + case HAIER_AC_YRW02: // 44 + case HITACHI_AC: // 40 + case HITACHI_AC1: // 41 + case HITACHI_AC2: // 42 + case WHIRLPOOL_AC: // 45 + case SAMSUNG_AC: // 46 + case ELECTRA_AC: // 48 + case PANASONIC_AC: // 49 + case MWM: // 52 + success = parseStringAndSendAirCon(ir_type, code_str); + break; +#if SEND_DENON case DENON: // 17 if (bits == 0) bits = DENON_BITS; irsend.sendDenon(code, bits, repeat); break; - case KELVINATOR: // 18 - parseStringAndSendKelv(code_str); - break; +#endif +#if SEND_SHERWOOD case SHERWOOD: // 19 if (bits == 0) - bits = SHERWOOD_BITS; - repeat = std::max(repeat, (uint16_t) SHERWOOD_MIN_REPEAT); + bits = kSherwoodBits; + repeat = std::max(repeat, kSherwoodMinRepeat); irsend.sendSherwood(code, bits, repeat); break; +#endif +#if SEND_RCMM case RCMM: // 21 if (bits == 0) - bits == RCMM_BITS; + bits = kRCMMBits; irsend.sendRCMM(code, bits, repeat); break; +#endif +#if SEND_SANYO case SANYO_LC7461: // 22 if (bits == 0) - bits = SANYO_LC7461_BITS; + bits = kSanyoLC7461Bits; irsend.sendSanyoLC7461(code, bits, repeat); break; +#endif +#if SEND_RC5 case RC5X: // 23 if (bits == 0) - bits = RC5X_BITS; + bits = kRC5XBits; irsend.sendRC5(code, bits, repeat); - case PRONTO: // 25 - parseStringAndSendPronto(code_str, repeat); break; +#endif +#if SEND_PRONTO + case PRONTO: // 25 + success = parseStringAndSendPronto(code_str, repeat); + break; +#endif +#if SEND_NIKAI case NIKAI: // 29 if (bits == 0) - bits = NIKAI_BITS; + bits = kNikaiBits; irsend.sendNikai(code, bits, repeat); break; +#endif +#if SEND_RAW case RAW: // 30 - parseStringAndSendRaw(code_str); + success = parseStringAndSendRaw(code_str); break; +#endif +#if SEND_GLOBALCACHE case GLOBALCACHE: // 31 - parseStringAndSendGC(code_str); + success = parseStringAndSendGC(code_str); break; - } +#endif +#if SEND_MIDEA + case MIDEA: // 34 + if (bits == 0) + bits = kMideaBits; + irsend.sendMidea(code, bits, repeat); + break; +#endif +#if SEND_MAGIQUEST + case MAGIQUEST: // 35 + if (bits == 0) + bits = kMagiquestBits; + irsend.sendMagiQuest(code, bits, repeat); + break; +#endif +#if SEND_LASERTAG + case LASERTAG: // 36 + if (bits == 0) + bits = kLasertagBits; + irsend.sendLasertag(code, bits, repeat); + break; +#endif +#if SEND_CARRIER_AC + case CARRIER_AC: // 37 + if (bits == 0) + bits = kCarrierAcBits; + irsend.sendCarrierAC(code, bits, repeat); + break; +#endif +#if SEND_MITSUBISHI2 + case MITSUBISHI2: // 39 + if (bits == 0) + bits = kMitsubishiBits; + repeat = std::max(repeat, kMitsubishiMinRepeat); + irsend.sendMitsubishi2(code, bits, repeat); + break; +#endif +#if SEND_GICABLE + case GICABLE: // 43 + if (bits == 0) + bits = kGicableBits; + repeat = std::max(repeat, kGicableMinRepeat); + irsend.sendGICable(code, bits, repeat); + break; +#endif +#if SEND_LUTRON + case LUTRON: // 47 + if (bits == 0) + bits = kLutronBits; + irsend.sendLutron(code, bits, repeat); + break; +#endif +#if SEND_PIONEER + case PIONEER: // 50 + if (bits == 0) + bits = kPioneerBits; + irsend.sendPioneer(code, bits, repeat); + break; +#endif +#if SEND_LG + case LG2: // 51 + if (bits == 0) + bits = kLgBits; + irsend.sendLG2(code, bits, repeat); + break; +#endif + default: + // If we got here, we didn't know how to send it. + success = false; + } + lastSendTime = millis(); // Release the lock. ir_lock = false; - // Indicate that we sent the message. - debug("Sent the IR message."); + // Indicate that we sent the message or not. + if (success) { + sendReqCounter++; + debug("Sent the IR message:"); + } else { + debug("Failed to send IR Message:"); + } debug("Type: " + String(ir_type)); - switch (ir_type) { - case KELVINATOR: - case PRONTO: - case RAW: - case GLOBALCACHE: - debug("Code: "); - debug(code_str); - debug("Repeats: " + String(repeat)); - // Confirm what we were asked to send was sent. + // For "long" codes we basically repeat what we got. + if (hasACState((decode_type_t) ir_type) || + ir_type == PRONTO || + ir_type == RAW || + ir_type == GLOBALCACHE) { + debug("Code: "); + debug(code_str); + // Confirm what we were asked to send was sent. #ifdef MQTT_ENABLE + if (success) { if (ir_type == PRONTO && repeat > 0) mqtt_client.publish(MQTTack, (String(ir_type) + ",R" + String(repeat) + "," + @@ -899,20 +1520,21 @@ void sendIRCode(int const ir_type, uint64_t const code, char const * code_str, else mqtt_client.publish(MQTTack, (String(ir_type) + "," + String(code_str)).c_str()); + } #endif // MQTT_ENABLE - break; - default: - debug("Code: 0x" + uint64ToString(code, 16)); - debug("Bits: " + String(bits)); - debug("Repeats: " + String(repeat)); - + } else { // For "short" codes, we break it down a bit more before we report. + debug("Code: 0x" + uint64ToString(code, 16)); + debug("Bits: " + String(bits)); + debug("Repeats: " + String(repeat)); #ifdef MQTT_ENABLE + if (success) mqtt_client.publish(MQTTack, (String(ir_type) + "," + uint64ToString(code, 16) + "," + String(bits) + "," + String(repeat)).c_str()); #endif // MQTT_ENABLE } + return success; } #ifdef MQTT_ENABLE @@ -924,9 +1546,12 @@ void receivingMQTT(String const topic_name, String const callback_str) { debug("Receiving data by MQTT topic " + topic_name); - // Make a copy of the callback string as strtok destorys it. + // Make a copy of the callback string as strtok destroys it. char* callback_c_str = strdup(callback_str.c_str()); debug("MQTT Payload (raw): " + callback_str); + // Save the message as the last command seen (global). + lastMqttCmd = callback_str; + lastMqttCmdTime = millis(); // Get the numeric protocol type. int ir_type = strtoul(strtok_r(callback_c_str, ",", &tok_ptr), NULL, 10); @@ -952,9 +1577,10 @@ void receivingMQTT(String const topic_name, String const callback_str) { // send received MQTT value by IR signal - sendIRCode(ir_type, code, - callback_str.substring(callback_str.indexOf(",") + 1).c_str(), - nbits, repeat); + lastSendSucceeded = sendIRCode( + ir_type, code, + callback_str.substring(callback_str.indexOf(",") + 1).c_str(), + nbits, repeat); } // Callback function, when the gateway receive an MQTT value on the topics diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/platformio.ini similarity index 96% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/platformio.ini index c87e56962..27b44ddca 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/platformio.ini @@ -7,7 +7,7 @@ build_flags = -DMQTT_MAX_PACKET_SIZE=512 lib_deps_builtin = lib_deps_external = PubSubClient - WifiManager@0.12 + WifiManager@0.14 [env:nodemcuv2] platform = espressif8266 diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/IRServer.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRServer/IRServer.ino similarity index 88% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRServer/IRServer.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRServer/IRServer.ino index 82f2e7dd7..b378d3bd5 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/IRServer.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRServer/IRServer.ino @@ -3,7 +3,8 @@ * Version 0.2 June, 2017 * Copyright 2015 Mark Szabo * - * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * An IR LED circuit *MUST* be connected to the ESP8266 on a pin + * as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -35,13 +36,15 @@ #include #include -const char* ssid = "....."; -const char* password = "....."; +const char* kSsid = "....."; +const char* kPassword = "....."; MDNSResponder mdns; ESP8266WebServer server(80); -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. void handleRoot() { server.send(200, "text/html", @@ -61,7 +64,9 @@ void handleIr() { for (uint8_t i = 0; i < server.args(); i++) { if (server.argName(i) == "code") { uint32_t code = strtoul(server.arg(i).c_str(), NULL, 10); +#if SEND_NEC irsend.sendNEC(code, 32); +#endif // SEND_NEC } } handleRoot(); @@ -85,7 +90,7 @@ void setup(void) { irsend.begin(); Serial.begin(115200); - WiFi.begin(ssid, password); + WiFi.begin(kSsid, kPassword); Serial.println(""); // Wait for connection @@ -95,9 +100,9 @@ void setup(void) { } Serial.println(""); Serial.print("Connected to "); - Serial.println(ssid); + Serial.println(kSsid); Serial.print("IP address: "); - Serial.println(WiFi.localIP()); + Serial.println(WiFi.localIP().toString()); if (mdns.begin("esp8266", WiFi.localIP())) { Serial.println("MDNS responder started"); diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRServer/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/IRrecvDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/IRrecvDemo.ino similarity index 66% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/IRrecvDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/IRrecvDemo.ino index ae9ed66f9..09babe4fe 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/IRrecvDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/IRrecvDemo.ino @@ -1,6 +1,9 @@ /* * IRremoteESP8266: IRrecvDemo - demonstrates receiving IR codes with IRrecv - * An IR detector/demodulator must be connected to the input RECV_PIN. + * This is very simple teaching code to show you how to use the library. + * If you are trying to decode your Infra-Red remote(s) for later replay, + * use the IRrecvDumpV2.ino example code instead of this. + * An IR detector/demodulator must be connected to the input kRecvPin. * Copyright 2009 Ken Shirriff, http://arcfn.com * Example circuit diagram: * https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving @@ -22,15 +25,20 @@ // An IR detector/demodulator is connected to GPIO pin 14(D5 on a NodeMCU // board). -uint16_t RECV_PIN = 14; +const uint16_t kRecvPin = 14; -IRrecv irrecv(RECV_PIN); +IRrecv irrecv(kRecvPin); decode_results results; void setup() { Serial.begin(115200); irrecv.enableIRIn(); // Start the receiver + while (!Serial) // Wait for the serial connection to be establised. + delay(50); + Serial.println(); + Serial.print("IRrecvDemo is now running and waiting for IR message on Pin "); + Serial.println(kRecvPin); } void loop() { diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/IRrecvDump.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/IRrecvDump.ino similarity index 96% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/IRrecvDump.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/IRrecvDump.ino index 856449695..34f10dc83 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/IRrecvDump.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/IRrecvDump.ino @@ -86,10 +86,10 @@ void dump(decode_results *results) { if (i % 100 == 0) yield(); // Preemptive yield every 100th entry to feed the WDT. if (i & 1) { - Serial.print(results->rawbuf[i] * RAWTICK, DEC); + Serial.print(results->rawbuf[i] * kRawTick, DEC); } else { Serial.print(", "); - Serial.print((uint32_t) results->rawbuf[i] * RAWTICK, DEC); + Serial.print((uint32_t) results->rawbuf[i] * kRawTick, DEC); } } Serial.println("};"); diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/platformio.ini diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino new file mode 100644 index 000000000..d72e0814c --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -0,0 +1,262 @@ +/* + * IRremoteESP8266: IRrecvDumpV2 - dump details of IR codes with IRrecv + * An IR detector/demodulator must be connected to the input kRecvPin. + * + * Copyright 2009 Ken Shirriff, http://arcfn.com + * Copyright 2017 David Conran + * + * Example circuit diagram: + * https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving + * + * Changes: + * Version 0.4 July, 2018 + * - Minor improvements and more A/C unit support. + * Version 0.3 November, 2017 + * - Support for A/C decoding for some protcols. + * Version 0.2 April, 2017 + * - Decode from a copy of the data so we can start capturing faster thus + * reduce the likelihood of miscaptures. + * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, + */ + +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include +// The following are only needed for extended decoding of A/C Messages +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ==================== start of TUNEABLE PARAMETERS ==================== +// An IR detector/demodulator is connected to GPIO pin 14 +// e.g. D5 on a NodeMCU board. +const uint16_t kRecvPin = 14; + +// The Serial connection baud rate. +// i.e. Status message will be sent to the PC at this baud rate. +// Try to avoid slow speeds like 9600, as you will miss messages and +// cause other problems. 115200 (or faster) is recommended. +// NOTE: Make sure you set your Serial Monitor to the same speed. +const uint32_t kBaudRate = 115200; + +// As this program is a special purpose capture/decoder, let us use a larger +// than normal buffer so we can handle Air Conditioner remote codes. +const uint16_t kCaptureBufferSize = 1024; + +// kTimeout is the Nr. of milli-Seconds of no-more-data before we consider a +// message ended. +// This parameter is an interesting trade-off. The longer the timeout, the more +// complex a message it can capture. e.g. Some device protocols will send +// multiple message packets in quick succession, like Air Conditioner remotes. +// Air Coniditioner protocols often have a considerable gap (20-40+ms) between +// packets. +// The downside of a large timeout value is a lot of less complex protocols +// send multiple messages when the remote's button is held down. The gap between +// them is often also around 20+ms. This can result in the raw data be 2-3+ +// times larger than needed as it has captured 2-3+ messages in a single +// capture. Setting a low timeout value can resolve this. +// So, choosing the best kTimeout value for your use particular case is +// quite nuanced. Good luck and happy hunting. +// NOTE: Don't exceed kMaxTimeoutMs. Typically 130ms. +#if DECODE_AC +// Some A/C units have gaps in their protocols of ~40ms. e.g. Kelvinator +// A value this large may swallow repeats of some protocols +const uint8_t kTimeout = 50; +#else // DECODE_AC +// Suits most messages, while not swallowing many repeats. +const uint8_t kTimeout = 15; +#endif // DECODE_AC +// Alternatives: +// const uint8_t kTimeout = 90; +// Suits messages with big gaps like XMP-1 & some aircon units, but can +// accidentally swallow repeated messages in the rawData[] output. +// +// const uint8_t kTimeout = kMaxTimeoutMs; +// This will set it to our currently allowed maximum. +// Values this high are problematic because it is roughly the typical boundary +// where most messages repeat. +// e.g. It will stop decoding a message and start sending it to serial at +// precisely the time when the next message is likely to be transmitted, +// and may miss it. + +// Set the smallest sized "UNKNOWN" message packets we actually care about. +// This value helps reduce the false-positive detection rate of IR background +// noise as real messages. The chances of background IR noise getting detected +// as a message increases with the length of the kTimeout value. (See above) +// The downside of setting this message too large is you can miss some valid +// short messages for protocols that this library doesn't yet decode. +// +// Set higher if you get lots of random short UNKNOWN messages when nothing +// should be sending a message. +// Set lower if you are sure your setup is working, but it doesn't see messages +// from your device. (e.g. Other IR remotes work.) +// NOTE: Set this value very high to effectively turn off UNKNOWN detection. +const uint16_t kMinUnknownSize = 12; +// ==================== end of TUNEABLE PARAMETERS ==================== + +// Use turn on the save buffer feature for more complete capture coverage. +IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, true); + +decode_results results; // Somewhere to store the results + +// Display the human readable state of an A/C message if we can. +void dumpACInfo(decode_results *results) { + String description = ""; +#if DECODE_DAIKIN + if (results->decode_type == DAIKIN) { + IRDaikinESP ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_DAIKIN +#if DECODE_FUJITSU_AC + if (results->decode_type == FUJITSU_AC) { + IRFujitsuAC ac(0); + ac.setRaw(results->state, results->bits / 8); + description = ac.toString(); + } +#endif // DECODE_FUJITSU_AC +#if DECODE_KELVINATOR + if (results->decode_type == KELVINATOR) { + IRKelvinatorAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_KELVINATOR +#if DECODE_MITSUBISHI_AC + if (results->decode_type == MITSUBISHI_AC) { + IRMitsubishiAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_MITSUBISHI_AC +#if DECODE_TOSHIBA_AC + if (results->decode_type == TOSHIBA_AC) { + IRToshibaAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_TOSHIBA_AC +#if DECODE_GREE + if (results->decode_type == GREE) { + IRGreeAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_GREE +#if DECODE_MIDEA + if (results->decode_type == MIDEA) { + IRMideaAC ac(0); + ac.setRaw(results->value); // Midea uses value instead of state. + description = ac.toString(); + } +#endif // DECODE_MIDEA +#if DECODE_HAIER_AC + if (results->decode_type == HAIER_AC) { + IRHaierAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_HAIER_AC +#if DECODE_HAIER_AC_YRW02 + if (results->decode_type == HAIER_AC_YRW02) { + IRHaierACYRW02 ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_HAIER_AC_YRW02 +#if DECODE_SAMSUNG_AC + if (results->decode_type == SAMSUNG_AC) { + IRSamsungAc ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_SAMSUNG_AC +#if DECODE_COOLIX + if (results->decode_type == COOLIX) { + IRCoolixAC ac(0); + ac.setRaw(results->value); // Coolix uses value instead of state. + description = ac.toString(); + } +#endif // DECODE_COOLIX +#if DECODE_PANASONIC_AC + if (results->decode_type == PANASONIC_AC && + results->bits > kPanasonicAcShortBits) { + IRPanasonicAc ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_PANASONIC_AC +#if DECODE_HITACHI_AC + if (results->decode_type == HITACHI_AC) { + IRHitachiAc ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_HITACHI_AC + // If we got a human-readable description of the message, display it. + if (description != "") Serial.println("Mesg Desc.: " + description); +} + +// The section of code run only once at start-up. +void setup() { + Serial.begin(kBaudRate, SERIAL_8N1, SERIAL_TX_ONLY); + while (!Serial) // Wait for the serial connection to be establised. + delay(50); + Serial.println(); + Serial.print("IRrecvDumpV2 is now running and waiting for IR input on Pin "); + Serial.println(kRecvPin); + +#if DECODE_HASH + // Ignore messages with less than minimum on or off pulses. + irrecv.setUnknownThreshold(kMinUnknownSize); +#endif // DECODE_HASH + irrecv.enableIRIn(); // Start the receiver +} + +// The repeating section of the code +// +void loop() { + // Check if the IR code has been received. + if (irrecv.decode(&results)) { + // Display a crude timestamp. + uint32_t now = millis(); + Serial.printf("Timestamp : %06u.%03u\n", now / 1000, now % 1000); + if (results.overflow) + Serial.printf( + "WARNING: IR code is too big for buffer (>= %d). " + "This result shouldn't be trusted until this is resolved. " + "Edit & increase kCaptureBufferSize.\n", + kCaptureBufferSize); + // Display the basic output of what we found. + Serial.print(resultToHumanReadableBasic(&results)); + dumpACInfo(&results); // Display any extra A/C info if we have it. + yield(); // Feed the WDT as the text output can take a while to print. + + // Display the library version the message was captured with. + Serial.print("Library : v"); + Serial.println(_IRREMOTEESP8266_VERSION_); + Serial.println(); + + // Output RAW timing info of the result. + Serial.println(resultToTimingInfo(&results)); + yield(); // Feed the WDT (again) + + // Output the results as source code + Serial.println(resultToSourceCode(&results)); + Serial.println(""); // Blank line between entries + yield(); // Feed the WDT (again) + } +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/IRsendDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/IRsendDemo.ino similarity index 87% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/IRsendDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/IRsendDemo.ino index 1a688cba3..892016b3e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/IRsendDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/IRsendDemo.ino @@ -4,7 +4,8 @@ * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, * Copyright 2009 Ken Shirriff, http://arcfn.com * - * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * An IR LED circuit *MUST* be connected to the ESP8266 on a pin + * as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -33,7 +34,9 @@ #include #include -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. // Example of data captured by IRrecvDumpV2.ino uint16_t rawData[67] = {9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, @@ -50,13 +53,19 @@ void setup() { } void loop() { +#if SEND_NEC Serial.println("NEC"); irsend.sendNEC(0x00FFE01FUL, 32); +#endif // SEND_NEC delay(2000); +#if SEND_SONY Serial.println("Sony"); irsend.sendSony(0xa90, 12, 2); +#endif // SEND_SONY delay(2000); +#if SEND_RAW Serial.println("a rawData capture from IRrecvDumpV2"); irsend.sendRaw(rawData, 67, 38); // Send a raw data capture at 38kHz. +#endif // SEND_RAW delay(2000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/IRsendProntoDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/IRsendProntoDemo.ino similarity index 93% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/IRsendProntoDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/IRsendProntoDemo.ino index 0a7a014a7..3bef2179e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/IRsendProntoDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/IRsendProntoDemo.ino @@ -6,7 +6,7 @@ * Version 1.0 June, 2017 * * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2), unless you - * change the irsend() value below. + * change the kIrLed value below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -35,7 +35,9 @@ #include #include -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. // Panasonic Plasma TV Descrete code (Power On). // Acquired from: @@ -96,10 +98,15 @@ void setup() { } void loop() { +#if SEND_PRONTO Serial.println("Sending a Samsung TV 'on' command."); irsend.sendPronto(samsungProntoCode, 72); delay(2000); Serial.println("Sending a Panasonic Plasma TV 'on' command."); irsend.sendPronto(panasonicProntoCode, 104); delay(2000); +#else // SEND_PRONTO + Serial.println("Can't send because SEND_PRONTO has been disabled."); + delay(10000); +#endif // SEND_PRONTO } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino similarity index 64% rename from lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino index 9c7068000..ee2422915 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino @@ -4,7 +4,8 @@ * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, Copyright 2009 Ken Shirriff, http://arcfn.com * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) * - * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * An IR LED circuit *MUST* be connected to the ESP8266 on a pin + * as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -33,12 +34,13 @@ #include #include -#define PanasonicAddress 0x4004 // Panasonic address (Pre data) -#define PanasonicPower 0x100BCBD // Panasonic Power button +const uint16_t kPanasonicAddress = 0x4004; // Panasonic address (Pre data) +const uint32_t kPanasonicPower = 0x100BCBD; // Panasonic Power button +const uint16_t kJVCPower = 0xC5E8; -#define JVCPower 0xC5E8 +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. void setup() { irsend.begin(); @@ -46,11 +48,16 @@ void setup() { void loop() { // This should turn your TV on and off - irsend.sendPanasonic(PanasonicAddress, PanasonicPower); +#if SEND_PANASONIC + irsend.sendPanasonic(kPanasonicAddress, kPanasonicPower); +#else // SEND_PANASONIC + Serial.println("Can't send because SEND_PANASONIC has been disabled."); +#endif // SEND_PANASONIC - irsend.sendJVC(JVCPower, 16, 0); // hex value, 16 bits, no repeat - // see http://www.sbprojects.com/knowledge/ir/jvc.php for information - delayMicroseconds(50); - irsend.sendJVC(JVCPower, 16, 1); // hex value, 16 bits, repeat - delayMicroseconds(50); +#if SEND_JVC + irsend.sendJVC(kJVCPower, 16, 1); // hex value, 16 bits, single repeat +#else // SEND_JVC + Serial.println("Can't send because SEND_JVC has been disabled."); +#endif // SEND_JVC + delay(10000); // Wait 10 seconds before we repeat everything. } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/LGACSend/LGACSend.ino b/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/LGACSend.ino similarity index 95% rename from lib/IRremoteESP8266-2.2.1.02/examples/LGACSend/LGACSend.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/LGACSend.ino index 7cced0c88..9139983c9 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/LGACSend/LGACSend.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/LGACSend.ino @@ -45,7 +45,11 @@ void Ac_Send_Code(uint32_t code) { Serial.print(" : "); Serial.println(code, HEX); +#if SEND_LG irsend.sendLG(code, 28); +#else // SEND_LG + Serial.println("Can't send because SEND_LG has been disabled."); +#endif // SEND_LG } void Ac_Activate(unsigned int temperature, unsigned int air_flow, @@ -60,9 +64,9 @@ void Ac_Activate(unsigned int temperature, unsigned int air_flow, else ac_msbits4 = 0; // cooling unsigned int ac_msbits5 = (temperature < 15) ? 0 : temperature - 15; - unsigned int ac_msbits6; + unsigned int ac_msbits6 = 0; - if (0 <= air_flow && air_flow <= 2) { + if (air_flow <= 2) { if (kAc_Type == 0) ac_msbits6 = kAc_Flow_Tower[air_flow]; else @@ -128,7 +132,7 @@ void setup() { } void loop() { - char b; + char b = ' '; Serial.println("# a : mode or temp b : air_flow, temp, swing, clean," " cooling/heating"); Serial.println("# 0 : off 0"); @@ -158,7 +162,7 @@ void loop() { default: Serial.println("b="); // Prompt User for input while (Serial.available() == 0) {} - char b = Serial.read(); + b = Serial.read(); } /* @@ -171,8 +175,8 @@ void loop() { # 4 : air_flow 0 ~ 3 : flow # + : temp + 1 # - : temp - 1 - # c : cooling - # h : heating + # c : cooling + # h : heating # m : change cooling to air clean, air clean to cooling */ Serial.print("a : "); @@ -194,7 +198,7 @@ void loop() { Ac_Change_Air_Swing(1); break; case '3': // 1 : clean on, power on - if (b == '0' | b == '1') + if (b == '0' || b == '1') Ac_Air_Clean(b); break; case '4': diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/TurnOnArgoAC.ino similarity index 72% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/TurnOnArgoAC.ino index a2e450ac5..3993d1151 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/TurnOnArgoAC.ino @@ -1,5 +1,6 @@ -/* Copyright 2017 crankyoldgit -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +/* Copyright 2017, 2018 crankyoldgit +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -29,10 +30,11 @@ #include #include -IRArgoAC argoir(4); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRArgoAC ac(kIrLed); // Set the GPIO to be used to sending the message. void setup() { - argoir.begin(); + ac.begin(); Serial.begin(115200); } @@ -40,13 +42,17 @@ void loop() { Serial.println("Sending..."); // Set up what we want to send. See ir_Argo.cpp for all the options. - argoir.setPower(true); - argoir.setFan(ARGO_FAN_1); - argoir.setCoolMode(ARGO_COOL_AUTO); - argoir.setTemp(25); + ac.setPower(true); + ac.setFan(kArgoFan1); + ac.setCoolMode(kArgoCoolAuto); + ac.setTemp(25); +#if SEND_ARGO // Now send the IR signal. - argoir.send(); + ac.send(); +#else // SEND_ARGO + Serial.println("Can't send because SEND_ARGO has been disabled."); +#endif // SEND_ARGO delay(5000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino similarity index 64% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino index eb5cda5e7..b3ab757de 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino @@ -1,6 +1,7 @@ -/* Copyright 2016 sillyfrog +/* Copyright 2017 sillyfrog * -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -30,10 +31,11 @@ #include #include -IRDaikinESP dakinir(D2); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRDaikinESP ac(kIrLed); // Set the GPIO to be used to sending the message void setup() { - dakinir.begin(); + ac.begin(); Serial.begin(115200); } @@ -42,15 +44,26 @@ void loop() { Serial.println("Sending..."); // Set up what we want to send. See ir_Daikin.cpp for all the options. - dakinir.on(); - dakinir.setFan(1); - dakinir.setMode(DAIKIN_COOL); - dakinir.setTemp(25); - dakinir.setSwingVertical(0); - dakinir.setSwingHorizontal(0); + ac.on(); + ac.setFan(1); + ac.setMode(kDaikinCool); + ac.setTemp(25); + ac.setSwingVertical(false); + ac.setSwingHorizontal(false); + + // Set the current time to 1:33PM (13:33) + // Time works in minutes past midnight + ac.setCurrentTime(13 * 60 + 33); + // Turn off about 1 hour later at 2:30PM (14:30) + ac.enableOffTimer(14 * 60 + 30); + + // Display what we are going to send. + Serial.println(ac.toString()); // Now send the IR signal. - dakinir.send(); +#if SEND_DAIKIN + ac.send(); +#endif // SEND_DAIKIN - delay(5000); + delay(15000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino new file mode 100644 index 000000000..823a3f485 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino @@ -0,0 +1,50 @@ +// Copyright 2017 Jonny Graham, 2018 David Conran +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include + +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRFujitsuAC ac(kIrLed); + +void printState() { + // Display the settings. + Serial.println("Fujitsu A/C remote is in the following state:"); + Serial.printf(" %s\n", ac.toString().c_str()); + // Display the encoded IR sequence. + unsigned char* ir_code = ac.getRaw(); + Serial.print("IR Code: 0x"); + for (uint8_t i = 0; i < ac.getStateLength(); i++) + Serial.printf("%02X", ir_code[i]); + Serial.println(); +} + +void setup() { + ac.begin(); + Serial.begin(115200); + delay(200); + + // Set up what we want to send. See ir_Fujitsu.cpp for all the options. + Serial.println("Default state of the remote."); + printState(); + Serial.println("Setting desired state for A/C."); + ac.setCmd(kFujitsuAcCmdTurnOn); + ac.setSwing(kFujitsuAcSwingBoth); + ac.setMode(kFujitsuAcModeCool); + ac.setFanSpeed(kFujitsuAcFanHigh); + ac.setTemp(24); // 24C +} + +void loop() { + // Now send the IR signal. + Serial.println("Sending IR command to A/C ..."); +#if SEND_FUJITSU_AC + ac.send(); +#else // SEND_FUJITSU_AC + Serial.println("Can't send because SEND_FUJITSU_AC has been disabled."); +#endif // SEND_FUJITSU_AC + printState(); + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino index 393ba28ff..b9b700741 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino @@ -1,6 +1,7 @@ -/* Copyright 2016 David Conran +/* Copyright 2016, 2018 David Conran * -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -29,29 +30,23 @@ #include #include -IRKelvinatorAC kelvir(D2); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRKelvinatorAC ac(kIrLed); // Set the GPIO to be used for sending messages. void printState() { // Display the settings. Serial.println("Kelvinator A/C remote is in the following state:"); - Serial.printf(" Basic\n Power: %d, Mode: %d, Temp: %dC, Fan Speed: %d\n", - kelvir.getPower(), kelvir.getMode(), kelvir.getTemp(), - kelvir.getFan()); - Serial.printf(" Options\n X-Fan: %d, Light: %d, Ion Filter: %d\n", - kelvir.getXFan(), kelvir.getLight(), kelvir.getIonFilter()); - Serial.printf(" Swing (V): %d, Swing (H): %d, Turbo: %d, Quiet: %d\n", - kelvir.getSwingVertical(), kelvir.getSwingHorizontal(), - kelvir.getTurbo(), kelvir.getQuiet()); + Serial.printf(" %s\n", ac.toString().c_str()); // Display the encoded IR sequence. - unsigned char* ir_code = kelvir.getRaw(); + unsigned char* ir_code = ac.getRaw(); Serial.print("IR Code: 0x"); - for (uint8_t i = 0; i < KELVINATOR_STATE_LENGTH; i++) + for (uint8_t i = 0; i < kKelvinatorStateLength; i++) Serial.printf("%02X", ir_code[i]); Serial.println(); } void setup() { - kelvir.begin(); + ac.begin(); Serial.begin(115200); delay(200); @@ -60,21 +55,23 @@ void setup() { Serial.println("Default state of the remote."); printState(); Serial.println("Setting desired state for A/C."); - kelvir.on(); - kelvir.setFan(1); - kelvir.setMode(KELVINATOR_COOL); - kelvir.setTemp(26); - kelvir.setSwingVertical(false); - kelvir.setSwingHorizontal(true); - kelvir.setXFan(true); - kelvir.setIonFilter(false); - kelvir.setLight(true); + ac.on(); + ac.setFan(1); + ac.setMode(kKelvinatorCool); + ac.setTemp(26); + ac.setSwingVertical(false); + ac.setSwingHorizontal(true); + ac.setXFan(true); + ac.setIonFilter(false); + ac.setLight(true); } void loop() { // Now send the IR signal. +#if SEND_KELVINATOR Serial.println("Sending IR command to A/C ..."); - kelvir.send(); + ac.send(); +#endif // SEND_KELVINATOR printState(); delay(5000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino similarity index 72% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino index 1ea9b0d31..e719af68e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino @@ -1,6 +1,7 @@ -/* Copyright 2017 David Conran +/* Copyright 2017, 2018 David Conran * -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -29,25 +30,23 @@ #include #include -IRMitsubishiAC mitsubir(D2); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRMitsubishiAC ac(kIrLed); // Set the GPIO used for sending messages. void printState() { // Display the settings. Serial.println("Mitsubishi A/C remote is in the following state:"); - Serial.printf(" Power: %d, Mode: %d, Temp: %dC, Fan Speed: %d," \ - " Vane Mode: %d\n", - mitsubir.getPower(), mitsubir.getMode(), mitsubir.getTemp(), - mitsubir.getFan(), mitsubir.getVane()); + Serial.printf(" %s\n", ac.toString().c_str()); // Display the encoded IR sequence. - unsigned char* ir_code = mitsubir.getRaw(); + unsigned char* ir_code = ac.getRaw(); Serial.print("IR Code: 0x"); - for (uint8_t i = 0; i < MITSUBISHI_AC_STATE_LENGTH; i++) + for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) Serial.printf("%02X", ir_code[i]); Serial.println(); } void setup() { - mitsubir.begin(); + ac.begin(); Serial.begin(115200); delay(200); @@ -55,17 +54,19 @@ void setup() { Serial.println("Default state of the remote."); printState(); Serial.println("Setting desired state for A/C."); - mitsubir.on(); - mitsubir.setFan(1); - mitsubir.setMode(MITSUBISHI_AC_COOL); - mitsubir.setTemp(26); - mitsubir.setVane(MITSUBISHI_AC_VANE_AUTO); + ac.on(); + ac.setFan(1); + ac.setMode(kMitsubishiAcCool); + ac.setTemp(26); + ac.setVane(kMitsubishiAcVaneAuto); } void loop() { // Now send the IR signal. +#if SEND_MITSUBISHI_AC Serial.println("Sending IR command to A/C ..."); - mitsubir.send(); + ac.send(); +#endif // SEND_MITSUBISHI_AC printState(); delay(5000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino new file mode 100644 index 000000000..d78178098 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino @@ -0,0 +1,71 @@ +/* Copyright 2017, 2018 David Conran +* +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. +* +* TL;DR: The IR LED needs to be driven by a transistor for a good result. +* +* Suggested circuit: +* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending +* +* Common mistakes & tips: +* * Don't just connect the IR LED directly to the pin, it won't +* have enough current to drive the IR LED effectively. +* * Make sure you have the IR LED polarity correct. +* See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity +* * Typical digital camera/phones can be used to see if the IR LED is flashed. +* Replace the IR LED with a normal LED if you don't have a digital camera +* when debugging. +* * Avoid using the following pins unless you really know what you are doing: +* * Pin 0/D3: Can interfere with the boot/program mode & support circuits. +* * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere. +* * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere. +* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs +* for your first time. e.g. ESP-12 etc. +*/ +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include + +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRToshibaAC ac(kIrLed); // Set the GPIO to be used for sending messages. + +void printState() { + // Display the settings. + Serial.println("Toshiba A/C remote is in the following state:"); + Serial.printf(" %s\n", ac.toString().c_str()); + // Display the encoded IR sequence. + unsigned char* ir_code = ac.getRaw(); + Serial.print("IR Code: 0x"); + for (uint8_t i = 0; i < kToshibaACStateLength; i++) + Serial.printf("%02X", ir_code[i]); + Serial.println(); +} + +void setup() { + ac.begin(); + Serial.begin(115200); + delay(200); + + // Set up what we want to send. See ir_Toshiba.cpp for all the options. + Serial.println("Default state of the remote."); + printState(); + Serial.println("Setting desired state for A/C."); + ac.on(); + ac.setFan(1); + ac.setMode(kToshibaAcCool); + ac.setTemp(26); +} + +void loop() { + // Now send the IR signal. +#if SEND_TOSHIBA_AC + Serial.println("Sending IR command to A/C ..."); + ac.send(); +#endif // SEND_TOSHIBA_AC + printState(); + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino similarity index 74% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino index 2476ff557..b7881eead 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino @@ -1,5 +1,6 @@ /* Copyright 2017 stufisher -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -29,10 +30,11 @@ #include #include -IRTrotecESP trotecir(D2); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRTrotecESP ac(kIrLed); // Set the GPIO to be used for sending messages. void setup() { - trotecir.begin(); + ac.begin(); Serial.begin(115200); } @@ -40,13 +42,17 @@ void loop() { Serial.println("Sending..."); // Set up what we want to send. See ir_Trotec.cpp for all the options. - trotecir.setPower(true); - trotecir.setSpeed(TROTEC_FAN_LOW); - trotecir.setMode(TROTEC_COOL); - trotecir.setTemp(25); + ac.setPower(true); + ac.setSpeed(kTrotecFanLow); + ac.setMode(kTrotecCool); + ac.setTemp(25); // Now send the IR signal. - trotecir.send(); +#if SEND_TROTEC + ac.send(); +#else // SEND_TROTEC + Serial.println("Can't send because SEND_TROTEC has been disabled."); +#endif // SEND_TROTEC delay(5000); } diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/keywords.txt b/lib/IRremoteESP8266-2.5.2.03/keywords.txt new file mode 100644 index 000000000..ac3f43fe1 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/keywords.txt @@ -0,0 +1,1645 @@ +######################################### +# Syntax Coloring Map For IRremoteESP8266 +######################################### + +################################################ +# WARNING: Do NOT edit this file directly. +# It is generated by 'tools/mkkeywords' +# e.g. tools/mkkeywords > keywords.txt +################################################ + +####################################################### +# The Arduino IDE requires the use of a tab separator +# between the name and identifier. Without this tab the +# keyword is not highlighted. +# +# Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords +####################################################### + +####################################### +# Datatypes & Classes (KEYWORD1) +####################################### + +IRArgoAC KEYWORD1 +IRCoolixAC KEYWORD1 +IRDaikinESP KEYWORD1 +IRFujitsuAC KEYWORD1 +IRGreeAC KEYWORD1 +IRHaierAC KEYWORD1 +IRHaierACYRW02 KEYWORD1 +IRKelvinatorAC KEYWORD1 +IRMideaAC KEYWORD1 +IRMitsubishiAC KEYWORD1 +IRPanasonicAc KEYWORD1 +IRSamsungAc KEYWORD1 +IRToshibaAC KEYWORD1 +IRTrotecESP KEYWORD1 +IRrecv KEYWORD1 +IRsend KEYWORD1 +IRtimer KEYWORD1 +decode_results KEYWORD1 +ir_params_t KEYWORD1 +match_result_t KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +_delayMicroseconds KEYWORD2 +add KEYWORD2 +addbit KEYWORD2 +begin KEYWORD2 +buildFromState KEYWORD2 +buildState KEYWORD2 +calcBlockChecksum KEYWORD2 +calcChecksum KEYWORD2 +calcLGChecksum KEYWORD2 +calcUSecPeriod KEYWORD2 +calculateChecksum KEYWORD2 +calibrate KEYWORD2 +cancelOffTimer KEYWORD2 +cancelOnTimer KEYWORD2 +cancelTimers KEYWORD2 +checkheader KEYWORD2 +checksum KEYWORD2 +clearBit KEYWORD2 +clearSensorTemp KEYWORD2 +compare KEYWORD2 +copyIrParams KEYWORD2 +decode KEYWORD2 +decodeAiwaRCT501 KEYWORD2 +decodeCOOLIX KEYWORD2 +decodeCarrierAC KEYWORD2 +decodeDISH KEYWORD2 +decodeDaikin KEYWORD2 +decodeDenon KEYWORD2 +decodeElectraAC KEYWORD2 +decodeFujitsuAC KEYWORD2 +decodeGICable KEYWORD2 +decodeGree KEYWORD2 +decodeHaierAC KEYWORD2 +decodeHaierACYRW02 KEYWORD2 +decodeHash KEYWORD2 +decodeHitachiAC KEYWORD2 +decodeJVC KEYWORD2 +decodeKelvinator KEYWORD2 +decodeLG KEYWORD2 +decodeLasertag KEYWORD2 +decodeLutron KEYWORD2 +decodeMWM KEYWORD2 +decodeMagiQuest KEYWORD2 +decodeMidea KEYWORD2 +decodeMitsubishi KEYWORD2 +decodeMitsubishi2 KEYWORD2 +decodeMitsubishiAC KEYWORD2 +decodeNEC KEYWORD2 +decodeNikai KEYWORD2 +decodePanasonic KEYWORD2 +decodePanasonicAC KEYWORD2 +decodePioneer KEYWORD2 +decodeRC5 KEYWORD2 +decodeRC6 KEYWORD2 +decodeRCMM KEYWORD2 +decodeSAMSUNG KEYWORD2 +decodeSamsungAC KEYWORD2 +decodeSanyo KEYWORD2 +decodeSanyoLC7461 KEYWORD2 +decodeSharp KEYWORD2 +decodeSony KEYWORD2 +decodeToshibaAC KEYWORD2 +decodeWhirlpoolAC KEYWORD2 +decodeWhynter KEYWORD2 +disableIRIn KEYWORD2 +disableOffTimer KEYWORD2 +disableOnTimer KEYWORD2 +elapsed KEYWORD2 +enableIRIn KEYWORD2 +enableIROut KEYWORD2 +enableOffTimer KEYWORD2 +enableOnTimer KEYWORD2 +encodeJVC KEYWORD2 +encodeLG KEYWORD2 +encodeMagiQuest KEYWORD2 +encodeNEC KEYWORD2 +encodePanasonic KEYWORD2 +encodePioneer KEYWORD2 +encodeRC5 KEYWORD2 +encodeRC5X KEYWORD2 +encodeRC6 KEYWORD2 +encodeSAMSUNG KEYWORD2 +encodeSanyoLC7461 KEYWORD2 +encodeSharp KEYWORD2 +encodeSony KEYWORD2 +encodeTime KEYWORD2 +fixChecksum KEYWORD2 +fixup KEYWORD2 +getBeep KEYWORD2 +getBit KEYWORD2 +getBufSize KEYWORD2 +getButton KEYWORD2 +getClean KEYWORD2 +getClock KEYWORD2 +getCmd KEYWORD2 +getCommand KEYWORD2 +getCoolMode KEYWORD2 +getCorrectedRawLength KEYWORD2 +getCurrTime KEYWORD2 +getCurrentTime KEYWORD2 +getEcono KEYWORD2 +getEye KEYWORD2 +getFan KEYWORD2 +getFanSpeed KEYWORD2 +getFlap KEYWORD2 +getHealth KEYWORD2 +getHeatMode KEYWORD2 +getIonFilter KEYWORD2 +getLed KEYWORD2 +getLight KEYWORD2 +getMax KEYWORD2 +getMode KEYWORD2 +getMold KEYWORD2 +getNight KEYWORD2 +getOffTime KEYWORD2 +getOffTimer KEYWORD2 +getOffTimerEnabled KEYWORD2 +getOnTime KEYWORD2 +getOnTimer KEYWORD2 +getOnTimerEnabled KEYWORD2 +getPower KEYWORD2 +getPowerful KEYWORD2 +getQuiet KEYWORD2 +getRClevel KEYWORD2 +getRaw KEYWORD2 +getSensor KEYWORD2 +getSensorTemp KEYWORD2 +getSleep KEYWORD2 +getSpeed KEYWORD2 +getStartClock KEYWORD2 +getStateLength KEYWORD2 +getStopClock KEYWORD2 +getSwing KEYWORD2 +getSwingHorizontal KEYWORD2 +getSwingVertical KEYWORD2 +getSwingVerticalAuto KEYWORD2 +getSwingVerticalPosition KEYWORD2 +getTemp KEYWORD2 +getTempRaw KEYWORD2 +getTime KEYWORD2 +getTimer KEYWORD2 +getTurbo KEYWORD2 +getVane KEYWORD2 +getXFan KEYWORD2 +getZoneFollow KEYWORD2 +getiFeel KEYWORD2 +hasACState KEYWORD2 +invertBits KEYWORD2 +isOffTimerEnabled KEYWORD2 +isOnTimerEnabled KEYWORD2 +ledOff KEYWORD2 +ledOn KEYWORD2 +mark KEYWORD2 +match KEYWORD2 +matchAtLeast KEYWORD2 +matchData KEYWORD2 +matchMark KEYWORD2 +matchSpace KEYWORD2 +off KEYWORD2 +on KEYWORD2 +printState KEYWORD2 +readbits KEYWORD2 +renderTime KEYWORD2 +reset KEYWORD2 +resultToHexidecimal KEYWORD2 +resultToHumanReadableBasic KEYWORD2 +resultToSourceCode KEYWORD2 +resultToTimingInfo KEYWORD2 +resume KEYWORD2 +reverseBits KEYWORD2 +send KEYWORD2 +sendAiwaRCT501 KEYWORD2 +sendArgo KEYWORD2 +sendCOOLIX KEYWORD2 +sendCarrierAC KEYWORD2 +sendDISH KEYWORD2 +sendDaikin KEYWORD2 +sendData KEYWORD2 +sendDenon KEYWORD2 +sendElectraAC KEYWORD2 +sendExtended KEYWORD2 +sendFujitsuAC KEYWORD2 +sendGC KEYWORD2 +sendGICable KEYWORD2 +sendGeneric KEYWORD2 +sendGree KEYWORD2 +sendHaierAC KEYWORD2 +sendHaierACYRW02 KEYWORD2 +sendHitachiAC KEYWORD2 +sendHitachiAC1 KEYWORD2 +sendHitachiAC2 KEYWORD2 +sendJVC KEYWORD2 +sendKelvinator KEYWORD2 +sendLG KEYWORD2 +sendLG2 KEYWORD2 +sendLasertag KEYWORD2 +sendLutron KEYWORD2 +sendMWM KEYWORD2 +sendMagiQuest KEYWORD2 +sendMidea KEYWORD2 +sendMitsubishi KEYWORD2 +sendMitsubishi2 KEYWORD2 +sendMitsubishiAC KEYWORD2 +sendNEC KEYWORD2 +sendNikai KEYWORD2 +sendPanasonic KEYWORD2 +sendPanasonic64 KEYWORD2 +sendPanasonicAC KEYWORD2 +sendPioneer KEYWORD2 +sendPronto KEYWORD2 +sendRC5 KEYWORD2 +sendRC6 KEYWORD2 +sendRCMM KEYWORD2 +sendRaw KEYWORD2 +sendSAMSUNG KEYWORD2 +sendSamsungAC KEYWORD2 +sendSanyoLC7461 KEYWORD2 +sendSharp KEYWORD2 +sendSharpRaw KEYWORD2 +sendSherwood KEYWORD2 +sendSony KEYWORD2 +sendToshibaAC KEYWORD2 +sendTrotec KEYWORD2 +sendWhirlpoolAC KEYWORD2 +sendWhynter KEYWORD2 +serialPrintUint64 KEYWORD2 +setBeep KEYWORD2 +setBit KEYWORD2 +setButton KEYWORD2 +setClean KEYWORD2 +setClock KEYWORD2 +setCmd KEYWORD2 +setCommand KEYWORD2 +setCoolMode KEYWORD2 +setCurrTime KEYWORD2 +setCurrentTime KEYWORD2 +setEcono KEYWORD2 +setEye KEYWORD2 +setFan KEYWORD2 +setFanSpeed KEYWORD2 +setFlap KEYWORD2 +setHealth KEYWORD2 +setHeatMode KEYWORD2 +setIonFilter KEYWORD2 +setLed KEYWORD2 +setLight KEYWORD2 +setMax KEYWORD2 +setMode KEYWORD2 +setModel KEYWORD2 +setMold KEYWORD2 +setNight KEYWORD2 +setOffTimer KEYWORD2 +setOnTimer KEYWORD2 +setPower KEYWORD2 +setPowerful KEYWORD2 +setQuiet KEYWORD2 +setRaw KEYWORD2 +setRoomTemp KEYWORD2 +setSensor KEYWORD2 +setSensorTemp KEYWORD2 +setSensorTempRaw KEYWORD2 +setSleep KEYWORD2 +setSpeed KEYWORD2 +setStartClock KEYWORD2 +setStopClock KEYWORD2 +setSwing KEYWORD2 +setSwingHorizontal KEYWORD2 +setSwingVertical KEYWORD2 +setTemp KEYWORD2 +setTempRaw KEYWORD2 +setTime KEYWORD2 +setTimer KEYWORD2 +setTurbo KEYWORD2 +setUnknownThreshold KEYWORD2 +setVane KEYWORD2 +setXFan KEYWORD2 +setZoneFollow KEYWORD2 +setiFeel KEYWORD2 +space KEYWORD2 +stateReset KEYWORD2 +stepHoriz KEYWORD2 +stepVert KEYWORD2 +sumBytes KEYWORD2 +ticksHigh KEYWORD2 +ticksLow KEYWORD2 +timeToString KEYWORD2 +toString KEYWORD2 +toggleRC5 KEYWORD2 +toggleRC6 KEYWORD2 +typeToString KEYWORD2 +uint64ToString KEYWORD2 +validChecksum KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +AIWA_RC_T501 LITERAL1 +AIWA_RC_T501_BITS LITERAL1 +ALLOW_DELAY_CALLS LITERAL1 +ARDB1 LITERAL1 +ARGO LITERAL1 +ARGO_COMMAND_LENGTH LITERAL1 +ARGO_COOL_AUTO LITERAL1 +ARGO_COOL_OFF LITERAL1 +ARGO_COOL_ON LITERAL1 +ARGO_COOl_HUM LITERAL1 +ARGO_FAN_1 LITERAL1 +ARGO_FAN_2 LITERAL1 +ARGO_FAN_3 LITERAL1 +ARGO_FAN_AUTO LITERAL1 +ARGO_FLAP_1 LITERAL1 +ARGO_FLAP_2 LITERAL1 +ARGO_FLAP_3 LITERAL1 +ARGO_FLAP_4 LITERAL1 +ARGO_FLAP_5 LITERAL1 +ARGO_FLAP_6 LITERAL1 +ARGO_FLAP_AUTO LITERAL1 +ARGO_FLAP_FULL LITERAL1 +ARGO_HEAT_AUTO LITERAL1 +ARGO_HEAT_BLINK LITERAL1 +ARGO_HEAT_ON LITERAL1 +ARGO_MAX_TEMP LITERAL1 +ARGO_MIN_TEMP LITERAL1 +ARRAH2E LITERAL1 +CARRIER_AC LITERAL1 +CARRIER_AC_BITS LITERAL1 +COOLIX LITERAL1 +COOLIX_BITS LITERAL1 +DAIKIN LITERAL1 +DAIKIN_AUTO LITERAL1 +DAIKIN_COMMAND_LENGTH LITERAL1 +DAIKIN_COOL LITERAL1 +DAIKIN_DEBUG LITERAL1 +DAIKIN_DRY LITERAL1 +DAIKIN_FAN LITERAL1 +DAIKIN_FAN_AUTO LITERAL1 +DAIKIN_FAN_MAX LITERAL1 +DAIKIN_FAN_MIN LITERAL1 +DAIKIN_FAN_QUIET LITERAL1 +DAIKIN_HEAT LITERAL1 +DAIKIN_MAX_TEMP LITERAL1 +DAIKIN_MIN_TEMP LITERAL1 +DECODE_AC LITERAL1 +DECODE_AIWA_RC_T501 LITERAL1 +DECODE_ARGO LITERAL1 +DECODE_CARRIER_AC LITERAL1 +DECODE_COOLIX LITERAL1 +DECODE_DAIKIN LITERAL1 +DECODE_DENON LITERAL1 +DECODE_DISH LITERAL1 +DECODE_ELECTRA_AC LITERAL1 +DECODE_FUJITSU_AC LITERAL1 +DECODE_GICABLE LITERAL1 +DECODE_GLOBALCACHE LITERAL1 +DECODE_GREE LITERAL1 +DECODE_HAIER_AC LITERAL1 +DECODE_HAIER_AC_YRW02 LITERAL1 +DECODE_HASH LITERAL1 +DECODE_HITACHI_AC LITERAL1 +DECODE_HITACHI_AC1 LITERAL1 +DECODE_HITACHI_AC2 LITERAL1 +DECODE_JVC LITERAL1 +DECODE_KELVINATOR LITERAL1 +DECODE_LASERTAG LITERAL1 +DECODE_LG LITERAL1 +DECODE_LUTRON LITERAL1 +DECODE_MAGIQUEST LITERAL1 +DECODE_MIDEA LITERAL1 +DECODE_MITSUBISHI LITERAL1 +DECODE_MITSUBISHI2 LITERAL1 +DECODE_MITSUBISHI_AC LITERAL1 +DECODE_MWM LITERAL1 +DECODE_NEC LITERAL1 +DECODE_NIKAI LITERAL1 +DECODE_PANASONIC LITERAL1 +DECODE_PANASONIC_AC LITERAL1 +DECODE_PIONEER LITERAL1 +DECODE_PRONTO LITERAL1 +DECODE_RC5 LITERAL1 +DECODE_RC6 LITERAL1 +DECODE_RCMM LITERAL1 +DECODE_SAMSUNG LITERAL1 +DECODE_SAMSUNG_AC LITERAL1 +DECODE_SANYO LITERAL1 +DECODE_SHARP LITERAL1 +DECODE_SHERWOOD LITERAL1 +DECODE_SONY LITERAL1 +DECODE_TOSHIBA_AC LITERAL1 +DECODE_TROTEC LITERAL1 +DECODE_WHIRLPOOL_AC LITERAL1 +DECODE_WHYNTER LITERAL1 +DENON LITERAL1 +DENON_48_BITS LITERAL1 +DENON_BITS LITERAL1 +DENON_LEGACY_BITS LITERAL1 +DISH LITERAL1 +DISH_BITS LITERAL1 +ELECTRA_AC LITERAL1 +FUJITSU_AC LITERAL1 +FUJITSU_AC_BITS LITERAL1 +FUJITSU_AC_CMD_STAY_ON LITERAL1 +FUJITSU_AC_CMD_STEP_HORIZ LITERAL1 +FUJITSU_AC_CMD_STEP_VERT LITERAL1 +FUJITSU_AC_CMD_TURN_OFF LITERAL1 +FUJITSU_AC_CMD_TURN_ON LITERAL1 +FUJITSU_AC_FAN_AUTO LITERAL1 +FUJITSU_AC_FAN_HIGH LITERAL1 +FUJITSU_AC_FAN_LOW LITERAL1 +FUJITSU_AC_FAN_MED LITERAL1 +FUJITSU_AC_FAN_QUIET LITERAL1 +FUJITSU_AC_MAX_TEMP LITERAL1 +FUJITSU_AC_MIN_BITS LITERAL1 +FUJITSU_AC_MIN_REPEAT LITERAL1 +FUJITSU_AC_MIN_TEMP LITERAL1 +FUJITSU_AC_MODE_AUTO LITERAL1 +FUJITSU_AC_MODE_COOL LITERAL1 +FUJITSU_AC_MODE_DRY LITERAL1 +FUJITSU_AC_MODE_FAN LITERAL1 +FUJITSU_AC_MODE_HEAT LITERAL1 +FUJITSU_AC_STATE_LENGTH LITERAL1 +FUJITSU_AC_STATE_LENGTH_SHORT LITERAL1 +FUJITSU_AC_SWING_BOTH LITERAL1 +FUJITSU_AC_SWING_HORIZ LITERAL1 +FUJITSU_AC_SWING_OFF LITERAL1 +FUJITSU_AC_SWING_VERT LITERAL1 +GICABLE LITERAL1 +GICABLE_BITS LITERAL1 +GLOBALCACHE LITERAL1 +GREE LITERAL1 +GREE_AUTO LITERAL1 +GREE_COOL LITERAL1 +GREE_DRY LITERAL1 +GREE_FAN LITERAL1 +GREE_FAN_MAX LITERAL1 +GREE_HEAT LITERAL1 +GREE_MAX_TEMP LITERAL1 +GREE_MIN_TEMP LITERAL1 +GREE_STATE_LENGTH LITERAL1 +GREE_SWING_AUTO LITERAL1 +GREE_SWING_DOWN LITERAL1 +GREE_SWING_DOWN_AUTO LITERAL1 +GREE_SWING_LAST_POS LITERAL1 +GREE_SWING_MIDDLE LITERAL1 +GREE_SWING_MIDDLE_AUTO LITERAL1 +GREE_SWING_MIDDLE_DOWN LITERAL1 +GREE_SWING_MIDDLE_UP LITERAL1 +GREE_SWING_UP LITERAL1 +GREE_SWING_UP_AUTO LITERAL1 +HAIER_AC LITERAL1 +HAIER_AC_AUTO LITERAL1 +HAIER_AC_CMD_FAN LITERAL1 +HAIER_AC_CMD_HEALTH LITERAL1 +HAIER_AC_CMD_MODE LITERAL1 +HAIER_AC_CMD_OFF LITERAL1 +HAIER_AC_CMD_ON LITERAL1 +HAIER_AC_CMD_SLEEP LITERAL1 +HAIER_AC_CMD_SWING LITERAL1 +HAIER_AC_CMD_TEMP_DOWN LITERAL1 +HAIER_AC_CMD_TEMP_UP LITERAL1 +HAIER_AC_CMD_TIMER_CANCEL LITERAL1 +HAIER_AC_CMD_TIMER_SET LITERAL1 +HAIER_AC_COOL LITERAL1 +HAIER_AC_DEF_TEMP LITERAL1 +HAIER_AC_DRY LITERAL1 +HAIER_AC_FAN LITERAL1 +HAIER_AC_FAN_AUTO LITERAL1 +HAIER_AC_FAN_HIGH LITERAL1 +HAIER_AC_FAN_LOW LITERAL1 +HAIER_AC_FAN_MED LITERAL1 +HAIER_AC_HEAT LITERAL1 +HAIER_AC_MAX_TEMP LITERAL1 +HAIER_AC_MIN_TEMP LITERAL1 +HAIER_AC_STATE_LENGTH LITERAL1 +HAIER_AC_SWING_CHG LITERAL1 +HAIER_AC_SWING_DOWN LITERAL1 +HAIER_AC_SWING_OFF LITERAL1 +HAIER_AC_SWING_UP LITERAL1 +HAIER_AC_YRW02 LITERAL1 +HAIER_AC_YRW02_AUTO LITERAL1 +HAIER_AC_YRW02_BUTTON_FAN LITERAL1 +HAIER_AC_YRW02_BUTTON_HEALTH LITERAL1 +HAIER_AC_YRW02_BUTTON_MODE LITERAL1 +HAIER_AC_YRW02_BUTTON_POWER LITERAL1 +HAIER_AC_YRW02_BUTTON_SLEEP LITERAL1 +HAIER_AC_YRW02_BUTTON_SWING LITERAL1 +HAIER_AC_YRW02_BUTTON_TEMP_DOWN LITERAL1 +HAIER_AC_YRW02_BUTTON_TEMP_UP LITERAL1 +HAIER_AC_YRW02_BUTTON_TURBO LITERAL1 +HAIER_AC_YRW02_COOL LITERAL1 +HAIER_AC_YRW02_DRY LITERAL1 +HAIER_AC_YRW02_FAN LITERAL1 +HAIER_AC_YRW02_FAN_AUTO LITERAL1 +HAIER_AC_YRW02_FAN_HIGH LITERAL1 +HAIER_AC_YRW02_FAN_LOW LITERAL1 +HAIER_AC_YRW02_FAN_MED LITERAL1 +HAIER_AC_YRW02_HEAT LITERAL1 +HAIER_AC_YRW02_STATE_LENGTH LITERAL1 +HAIER_AC_YRW02_SWING_AUTO LITERAL1 +HAIER_AC_YRW02_SWING_BOTTOM LITERAL1 +HAIER_AC_YRW02_SWING_DOWN LITERAL1 +HAIER_AC_YRW02_SWING_MIDDLE LITERAL1 +HAIER_AC_YRW02_SWING_OFF LITERAL1 +HAIER_AC_YRW02_SWING_TOP LITERAL1 +HAIER_AC_YRW02_TURBO_HIGH LITERAL1 +HAIER_AC_YRW02_TURBO_LOW LITERAL1 +HAIER_AC_YRW02_TURBO_OFF LITERAL1 +HIGH LITERAL1 +HITACHI_AC LITERAL1 +HITACHI_AC1 LITERAL1 +HITACHI_AC1_BITS LITERAL1 +HITACHI_AC1_STATE_LENGTH LITERAL1 +HITACHI_AC2 LITERAL1 +HITACHI_AC2_BITS LITERAL1 +HITACHI_AC2_STATE_LENGTH LITERAL1 +HITACHI_AC_BITS LITERAL1 +HITACHI_AC_STATE_LENGTH LITERAL1 +ICACHE_RAM_ATTR LITERAL1 +JVC LITERAL1 +JVC_BITS LITERAL1 +KELVINATOR LITERAL1 +KELVINATOR_AUTO LITERAL1 +KELVINATOR_AUTO_TEMP LITERAL1 +KELVINATOR_BASIC_FAN_MAX LITERAL1 +KELVINATOR_COOL LITERAL1 +KELVINATOR_DRY LITERAL1 +KELVINATOR_FAN LITERAL1 +KELVINATOR_FAN_AUTO LITERAL1 +KELVINATOR_FAN_MAX LITERAL1 +KELVINATOR_HEAT LITERAL1 +KELVINATOR_MAX_TEMP LITERAL1 +KELVINATOR_MIN_TEMP LITERAL1 +KELVINATOR_STATE_LENGTH LITERAL1 +LASERTAG LITERAL1 +LASERTAG_BITS LITERAL1 +LG LITERAL1 +LG2 LITERAL1 +LG32_BITS LITERAL1 +LG_BITS LITERAL1 +LOW LITERAL1 +LUTRON LITERAL1 +MAGIQUEST LITERAL1 +MAGIQUEST_BITS LITERAL1 +MIDEA LITERAL1 +MIDEA_AC_AUTO LITERAL1 +MIDEA_AC_COOL LITERAL1 +MIDEA_AC_DRY LITERAL1 +MIDEA_AC_FAN LITERAL1 +MIDEA_AC_FAN_AUTO LITERAL1 +MIDEA_AC_FAN_HI LITERAL1 +MIDEA_AC_FAN_LOW LITERAL1 +MIDEA_AC_FAN_MED LITERAL1 +MIDEA_AC_HEAT LITERAL1 +MIDEA_AC_MAX_TEMP_C LITERAL1 +MIDEA_AC_MAX_TEMP_F LITERAL1 +MIDEA_AC_MIN_TEMP_C LITERAL1 +MIDEA_AC_MIN_TEMP_F LITERAL1 +MIDEA_AC_POWER LITERAL1 +MIDEA_AC_SLEEP LITERAL1 +MIDEA_BITS LITERAL1 +MITSUBISHI LITERAL1 +MITSUBISHI2 LITERAL1 +MITSUBISHI_AC LITERAL1 +MITSUBISHI_AC_AUTO LITERAL1 +MITSUBISHI_AC_COOL LITERAL1 +MITSUBISHI_AC_DRY LITERAL1 +MITSUBISHI_AC_FAN_AUTO LITERAL1 +MITSUBISHI_AC_FAN_MAX LITERAL1 +MITSUBISHI_AC_FAN_REAL_MAX LITERAL1 +MITSUBISHI_AC_FAN_SILENT LITERAL1 +MITSUBISHI_AC_HEAT LITERAL1 +MITSUBISHI_AC_MAX_TEMP LITERAL1 +MITSUBISHI_AC_MIN_TEMP LITERAL1 +MITSUBISHI_AC_POWER LITERAL1 +MITSUBISHI_AC_STATE_LENGTH LITERAL1 +MITSUBISHI_AC_VANE_AUTO LITERAL1 +MITSUBISHI_AC_VANE_AUTO_MOVE LITERAL1 +MITSUBISHI_BITS LITERAL1 +MWM LITERAL1 +NEC LITERAL1 +NEC_BITS LITERAL1 +NEC_LIKE LITERAL1 +NIKAI LITERAL1 +NIKAI_BITS LITERAL1 +ONCE LITERAL1 +PANASONIC LITERAL1 +PANASONIC_AC LITERAL1 +PANASONIC_BITS LITERAL1 +PIONEER LITERAL1 +PRONTO LITERAL1 +RAW LITERAL1 +RAWTICK LITERAL1 +RC5 LITERAL1 +RC5X LITERAL1 +RC5X_BITS LITERAL1 +RC5_BITS LITERAL1 +RC6 LITERAL1 +RC6_36_BITS LITERAL1 +RC6_MODE0_BITS LITERAL1 +RCMM LITERAL1 +RCMM_BITS LITERAL1 +SAMSUNG LITERAL1 +SAMSUNG_AC LITERAL1 +SAMSUNG_BITS LITERAL1 +SANYO LITERAL1 +SANYO_LC7461 LITERAL1 +SANYO_LC7461_BITS LITERAL1 +SANYO_SA8650B_BITS LITERAL1 +SEND_AIWA_RC_T501 LITERAL1 +SEND_ARGO LITERAL1 +SEND_CARRIER_AC LITERAL1 +SEND_COOLIX LITERAL1 +SEND_DAIKIN LITERAL1 +SEND_DENON LITERAL1 +SEND_DISH LITERAL1 +SEND_ELECTRA_AC LITERAL1 +SEND_FUJITSU_AC LITERAL1 +SEND_GICABLE LITERAL1 +SEND_GLOBALCACHE LITERAL1 +SEND_GREE LITERAL1 +SEND_HAIER_AC LITERAL1 +SEND_HAIER_AC_YRW02 LITERAL1 +SEND_HITACHI_AC LITERAL1 +SEND_HITACHI_AC1 LITERAL1 +SEND_HITACHI_AC2 LITERAL1 +SEND_JVC LITERAL1 +SEND_KELVINATOR LITERAL1 +SEND_LASERTAG LITERAL1 +SEND_LG LITERAL1 +SEND_LUTRON LITERAL1 +SEND_MAGIQUEST LITERAL1 +SEND_MIDEA LITERAL1 +SEND_MITSUBISHI LITERAL1 +SEND_MITSUBISHI2 LITERAL1 +SEND_MITSUBISHI_AC LITERAL1 +SEND_MWM LITERAL1 +SEND_NEC LITERAL1 +SEND_NIKAI LITERAL1 +SEND_PANASONIC LITERAL1 +SEND_PANASONIC_AC LITERAL1 +SEND_PIONEER LITERAL1 +SEND_PRONTO LITERAL1 +SEND_RAW LITERAL1 +SEND_RC5 LITERAL1 +SEND_RC6 LITERAL1 +SEND_RCMM LITERAL1 +SEND_SAMSUNG LITERAL1 +SEND_SAMSUNG_AC LITERAL1 +SEND_SANYO LITERAL1 +SEND_SHARP LITERAL1 +SEND_SHERWOOD LITERAL1 +SEND_SONY LITERAL1 +SEND_TOSHIBA_AC LITERAL1 +SEND_TROTEC LITERAL1 +SEND_WHIRLPOOL_AC LITERAL1 +SEND_WHYNTER LITERAL1 +SHARP LITERAL1 +SHARP_BITS LITERAL1 +SHERWOOD LITERAL1 +SHERWOOD_BITS LITERAL1 +SONY LITERAL1 +SONY_12_BITS LITERAL1 +SONY_15_BITS LITERAL1 +SONY_20_BITS LITERAL1 +TIMEOUT_MS LITERAL1 +TOSHIBA_AC LITERAL1 +TOSHIBA_AC_AUTO LITERAL1 +TOSHIBA_AC_COOL LITERAL1 +TOSHIBA_AC_DRY LITERAL1 +TOSHIBA_AC_FAN_AUTO LITERAL1 +TOSHIBA_AC_FAN_MAX LITERAL1 +TOSHIBA_AC_HEAT LITERAL1 +TOSHIBA_AC_MAX_TEMP LITERAL1 +TOSHIBA_AC_MIN_TEMP LITERAL1 +TOSHIBA_AC_POWER LITERAL1 +TOSHIBA_AC_STATE_LENGTH LITERAL1 +TROTEC LITERAL1 +TROTEC_AUTO LITERAL1 +TROTEC_COMMAND_LENGTH LITERAL1 +TROTEC_COOL LITERAL1 +TROTEC_DRY LITERAL1 +TROTEC_FAN LITERAL1 +TROTEC_FAN_HIGH LITERAL1 +TROTEC_FAN_LOW LITERAL1 +TROTEC_FAN_MED LITERAL1 +TROTEC_MAX_TEMP LITERAL1 +TROTEC_MAX_TIMER LITERAL1 +TROTEC_MIN_TEMP LITERAL1 +TROTEC_MIN_TIMER LITERAL1 +UNKNOWN LITERAL1 +UNUSED LITERAL1 +WHIRLPOOL_AC LITERAL1 +WHYNTER LITERAL1 +WHYNTER_BITS LITERAL1 +kAiwaRcT501Bits LITERAL1 +kAiwaRcT501MinRepeats LITERAL1 +kAiwaRcT501PostBits LITERAL1 +kAiwaRcT501PostData LITERAL1 +kAiwaRcT501PreBits LITERAL1 +kAiwaRcT501PreData LITERAL1 +kArgoBitMark LITERAL1 +kArgoCoolAuto LITERAL1 +kArgoCoolHum LITERAL1 +kArgoCoolOff LITERAL1 +kArgoCoolOn LITERAL1 +kArgoFan1 LITERAL1 +kArgoFan2 LITERAL1 +kArgoFan3 LITERAL1 +kArgoFanAuto LITERAL1 +kArgoFlap1 LITERAL1 +kArgoFlap2 LITERAL1 +kArgoFlap3 LITERAL1 +kArgoFlap4 LITERAL1 +kArgoFlap5 LITERAL1 +kArgoFlap6 LITERAL1 +kArgoFlapAuto LITERAL1 +kArgoFlapFull LITERAL1 +kArgoHdrMark LITERAL1 +kArgoHdrSpace LITERAL1 +kArgoHeatAuto LITERAL1 +kArgoHeatBlink LITERAL1 +kArgoHeatOn LITERAL1 +kArgoMaxTemp LITERAL1 +kArgoMinTemp LITERAL1 +kArgoOneSpace LITERAL1 +kArgoStateLength LITERAL1 +kArgoZeroSpace LITERAL1 +kCarrierAcBitMark LITERAL1 +kCarrierAcBits LITERAL1 +kCarrierAcGap LITERAL1 +kCarrierAcHdrMark LITERAL1 +kCarrierAcHdrSpace LITERAL1 +kCarrierAcMinRepeat LITERAL1 +kCarrierAcOneSpace LITERAL1 +kCarrierAcZeroSpace LITERAL1 +kCoolixAuto LITERAL1 +kCoolixBitMark LITERAL1 +kCoolixBitMarkTicks LITERAL1 +kCoolixBits LITERAL1 +kCoolixClean LITERAL1 +kCoolixCool LITERAL1 +kCoolixDefaultState LITERAL1 +kCoolixDry LITERAL1 +kCoolixFan LITERAL1 +kCoolixFanAuto LITERAL1 +kCoolixFanFixed LITERAL1 +kCoolixFanMask LITERAL1 +kCoolixFanMax LITERAL1 +kCoolixFanMed LITERAL1 +kCoolixFanMin LITERAL1 +kCoolixFanTempCode LITERAL1 +kCoolixFanZoneFollow LITERAL1 +kCoolixHdrMark LITERAL1 +kCoolixHdrMarkTicks LITERAL1 +kCoolixHdrSpace LITERAL1 +kCoolixHdrSpaceTicks LITERAL1 +kCoolixHeat LITERAL1 +kCoolixLed LITERAL1 +kCoolixMinGap LITERAL1 +kCoolixMinGapTicks LITERAL1 +kCoolixModeMask LITERAL1 +kCoolixOff LITERAL1 +kCoolixOneSpace LITERAL1 +kCoolixOneSpaceTicks LITERAL1 +kCoolixPrefix LITERAL1 +kCoolixSensorTempIgnoreCode LITERAL1 +kCoolixSensorTempMask LITERAL1 +kCoolixSensorTempMax LITERAL1 +kCoolixSensorTempMin LITERAL1 +kCoolixSleep LITERAL1 +kCoolixSwing LITERAL1 +kCoolixTempMap LITERAL1 +kCoolixTempMask LITERAL1 +kCoolixTempMax LITERAL1 +kCoolixTempMin LITERAL1 +kCoolixTempRange LITERAL1 +kCoolixTick LITERAL1 +kCoolixTurbo LITERAL1 +kCoolixUnknown LITERAL1 +kCoolixZeroSpace LITERAL1 +kCoolixZeroSpaceTicks LITERAL1 +kCoolixZoneFollowMask LITERAL1 +kDaikinAuto LITERAL1 +kDaikinBitEcono LITERAL1 +kDaikinBitEye LITERAL1 +kDaikinBitMark LITERAL1 +kDaikinBitMold LITERAL1 +kDaikinBitOffTimer LITERAL1 +kDaikinBitOnTimer LITERAL1 +kDaikinBitPower LITERAL1 +kDaikinBitPowerful LITERAL1 +kDaikinBitSensor LITERAL1 +kDaikinBitSilent LITERAL1 +kDaikinBits LITERAL1 +kDaikinByteEcono LITERAL1 +kDaikinByteEye LITERAL1 +kDaikinByteMold LITERAL1 +kDaikinByteOffTimer LITERAL1 +kDaikinByteOnTimer LITERAL1 +kDaikinBytePower LITERAL1 +kDaikinBytePowerful LITERAL1 +kDaikinByteSensor LITERAL1 +kDaikinByteSilent LITERAL1 +kDaikinCool LITERAL1 +kDaikinCurBit LITERAL1 +kDaikinCurIndex LITERAL1 +kDaikinDry LITERAL1 +kDaikinFan LITERAL1 +kDaikinFanAuto LITERAL1 +kDaikinFanMax LITERAL1 +kDaikinFanMin LITERAL1 +kDaikinFanQuiet LITERAL1 +kDaikinFirstHeader64 LITERAL1 +kDaikinGap LITERAL1 +kDaikinHdrMark LITERAL1 +kDaikinHdrSpace LITERAL1 +kDaikinHeat LITERAL1 +kDaikinMarkExcess LITERAL1 +kDaikinMaxTemp LITERAL1 +kDaikinMinTemp LITERAL1 +kDaikinOneSpace LITERAL1 +kDaikinRawBits LITERAL1 +kDaikinStateLength LITERAL1 +kDaikinTolerance LITERAL1 +kDaikinZeroSpace LITERAL1 +kDenonBitMark LITERAL1 +kDenonBitMarkTicks LITERAL1 +kDenonBits LITERAL1 +kDenonHdrMark LITERAL1 +kDenonHdrMarkTicks LITERAL1 +kDenonHdrSpace LITERAL1 +kDenonHdrSpaceTicks LITERAL1 +kDenonLegacyBits LITERAL1 +kDenonManufacturer LITERAL1 +kDenonMinCommandLengthTicks LITERAL1 +kDenonMinGap LITERAL1 +kDenonMinGapTicks LITERAL1 +kDenonOneSpace LITERAL1 +kDenonOneSpaceTicks LITERAL1 +kDenonTick LITERAL1 +kDenonZeroSpace LITERAL1 +kDenonZeroSpaceTicks LITERAL1 +kDishBitMark LITERAL1 +kDishBitMarkTicks LITERAL1 +kDishBits LITERAL1 +kDishHdrMark LITERAL1 +kDishHdrMarkTicks LITERAL1 +kDishHdrSpace LITERAL1 +kDishHdrSpaceTicks LITERAL1 +kDishMinRepeat LITERAL1 +kDishOneSpace LITERAL1 +kDishOneSpaceTicks LITERAL1 +kDishRptSpace LITERAL1 +kDishRptSpaceTicks LITERAL1 +kDishTick LITERAL1 +kDishZeroSpace LITERAL1 +kDishZeroSpaceTicks LITERAL1 +kDutyDefault LITERAL1 +kDutyMax LITERAL1 +kElectraAcBitMark LITERAL1 +kElectraAcBits LITERAL1 +kElectraAcHdrMark LITERAL1 +kElectraAcHdrSpace LITERAL1 +kElectraAcMessageGap LITERAL1 +kElectraAcOneSpace LITERAL1 +kElectraAcStateLength LITERAL1 +kElectraAcZeroSpace LITERAL1 +kFnvBasis32 LITERAL1 +kFnvPrime32 LITERAL1 +kFooter LITERAL1 +kFujitsuAcBitMark LITERAL1 +kFujitsuAcBits LITERAL1 +kFujitsuAcCmdStayOn LITERAL1 +kFujitsuAcCmdStepHoriz LITERAL1 +kFujitsuAcCmdStepVert LITERAL1 +kFujitsuAcCmdTurnOff LITERAL1 +kFujitsuAcCmdTurnOn LITERAL1 +kFujitsuAcFanAuto LITERAL1 +kFujitsuAcFanHigh LITERAL1 +kFujitsuAcFanLow LITERAL1 +kFujitsuAcFanMed LITERAL1 +kFujitsuAcFanQuiet LITERAL1 +kFujitsuAcHdrMark LITERAL1 +kFujitsuAcHdrSpace LITERAL1 +kFujitsuAcMaxTemp LITERAL1 +kFujitsuAcMinBits LITERAL1 +kFujitsuAcMinGap LITERAL1 +kFujitsuAcMinRepeat LITERAL1 +kFujitsuAcMinTemp LITERAL1 +kFujitsuAcModeAuto LITERAL1 +kFujitsuAcModeCool LITERAL1 +kFujitsuAcModeDry LITERAL1 +kFujitsuAcModeFan LITERAL1 +kFujitsuAcModeHeat LITERAL1 +kFujitsuAcOneSpace LITERAL1 +kFujitsuAcStateLength LITERAL1 +kFujitsuAcStateLengthShort LITERAL1 +kFujitsuAcSwingBoth LITERAL1 +kFujitsuAcSwingHoriz LITERAL1 +kFujitsuAcSwingOff LITERAL1 +kFujitsuAcSwingVert LITERAL1 +kFujitsuAcZeroSpace LITERAL1 +kGicableBitMark LITERAL1 +kGicableBits LITERAL1 +kGicableHdrMark LITERAL1 +kGicableHdrSpace LITERAL1 +kGicableMinCommandLength LITERAL1 +kGicableMinGap LITERAL1 +kGicableMinRepeat LITERAL1 +kGicableOneSpace LITERAL1 +kGicableRptSpace LITERAL1 +kGicableZeroSpace LITERAL1 +kGlobalCacheFreqIndex LITERAL1 +kGlobalCacheMaxRepeat LITERAL1 +kGlobalCacheMinUsec LITERAL1 +kGlobalCacheRptIndex LITERAL1 +kGlobalCacheRptStartIndex LITERAL1 +kGlobalCacheStartIndex LITERAL1 +kGreeAuto LITERAL1 +kGreeBitMark LITERAL1 +kGreeBits LITERAL1 +kGreeBlockFooter LITERAL1 +kGreeBlockFooterBits LITERAL1 +kGreeCool LITERAL1 +kGreeDry LITERAL1 +kGreeFan LITERAL1 +kGreeFanMask LITERAL1 +kGreeFanMax LITERAL1 +kGreeHdrMark LITERAL1 +kGreeHdrSpace LITERAL1 +kGreeHeat LITERAL1 +kGreeLightMask LITERAL1 +kGreeMaxTemp LITERAL1 +kGreeMinTemp LITERAL1 +kGreeModeMask LITERAL1 +kGreeMsgSpace LITERAL1 +kGreeOneSpace LITERAL1 +kGreePower1Mask LITERAL1 +kGreePower2Mask LITERAL1 +kGreeSleepMask LITERAL1 +kGreeStateLength LITERAL1 +kGreeSwingAuto LITERAL1 +kGreeSwingAutoMask LITERAL1 +kGreeSwingDown LITERAL1 +kGreeSwingDownAuto LITERAL1 +kGreeSwingLastPos LITERAL1 +kGreeSwingMiddle LITERAL1 +kGreeSwingMiddleAuto LITERAL1 +kGreeSwingMiddleDown LITERAL1 +kGreeSwingMiddleUp LITERAL1 +kGreeSwingPosMask LITERAL1 +kGreeSwingUp LITERAL1 +kGreeSwingUpAuto LITERAL1 +kGreeTurboMask LITERAL1 +kGreeXfanMask LITERAL1 +kGreeZeroSpace LITERAL1 +kHaierACBits LITERAL1 +kHaierACStateLength LITERAL1 +kHaierACYRW02Bits LITERAL1 +kHaierACYRW02StateLength LITERAL1 +kHaierAcAuto LITERAL1 +kHaierAcBitMark LITERAL1 +kHaierAcCmdFan LITERAL1 +kHaierAcCmdHealth LITERAL1 +kHaierAcCmdMode LITERAL1 +kHaierAcCmdOff LITERAL1 +kHaierAcCmdOn LITERAL1 +kHaierAcCmdSleep LITERAL1 +kHaierAcCmdSwing LITERAL1 +kHaierAcCmdTempDown LITERAL1 +kHaierAcCmdTempUp LITERAL1 +kHaierAcCmdTimerCancel LITERAL1 +kHaierAcCmdTimerSet LITERAL1 +kHaierAcCool LITERAL1 +kHaierAcDefTemp LITERAL1 +kHaierAcDry LITERAL1 +kHaierAcFan LITERAL1 +kHaierAcFanAuto LITERAL1 +kHaierAcFanHigh LITERAL1 +kHaierAcFanLow LITERAL1 +kHaierAcFanMed LITERAL1 +kHaierAcHdr LITERAL1 +kHaierAcHdrGap LITERAL1 +kHaierAcHeat LITERAL1 +kHaierAcMaxTemp LITERAL1 +kHaierAcMaxTime LITERAL1 +kHaierAcMinGap LITERAL1 +kHaierAcMinTemp LITERAL1 +kHaierAcOneSpace LITERAL1 +kHaierAcPrefix LITERAL1 +kHaierAcSwingChg LITERAL1 +kHaierAcSwingDown LITERAL1 +kHaierAcSwingOff LITERAL1 +kHaierAcSwingUp LITERAL1 +kHaierAcYrw02Auto LITERAL1 +kHaierAcYrw02ButtonFan LITERAL1 +kHaierAcYrw02ButtonHealth LITERAL1 +kHaierAcYrw02ButtonMode LITERAL1 +kHaierAcYrw02ButtonPower LITERAL1 +kHaierAcYrw02ButtonSleep LITERAL1 +kHaierAcYrw02ButtonSwing LITERAL1 +kHaierAcYrw02ButtonTempDown LITERAL1 +kHaierAcYrw02ButtonTempUp LITERAL1 +kHaierAcYrw02ButtonTurbo LITERAL1 +kHaierAcYrw02Cool LITERAL1 +kHaierAcYrw02Dry LITERAL1 +kHaierAcYrw02Fan LITERAL1 +kHaierAcYrw02FanAuto LITERAL1 +kHaierAcYrw02FanHigh LITERAL1 +kHaierAcYrw02FanLow LITERAL1 +kHaierAcYrw02FanMed LITERAL1 +kHaierAcYrw02Heat LITERAL1 +kHaierAcYrw02Power LITERAL1 +kHaierAcYrw02Prefix LITERAL1 +kHaierAcYrw02Sleep LITERAL1 +kHaierAcYrw02SwingAuto LITERAL1 +kHaierAcYrw02SwingBottom LITERAL1 +kHaierAcYrw02SwingDown LITERAL1 +kHaierAcYrw02SwingMiddle LITERAL1 +kHaierAcYrw02SwingOff LITERAL1 +kHaierAcYrw02SwingTop LITERAL1 +kHaierAcYrw02TurboHigh LITERAL1 +kHaierAcYrw02TurboLow LITERAL1 +kHaierAcYrw02TurboOff LITERAL1 +kHaierAcZeroSpace LITERAL1 +kHeader LITERAL1 +kHitachiAc1Bits LITERAL1 +kHitachiAc1HdrMark LITERAL1 +kHitachiAc1HdrSpace LITERAL1 +kHitachiAc1StateLength LITERAL1 +kHitachiAc2Bits LITERAL1 +kHitachiAc2StateLength LITERAL1 +kHitachiAcBitMark LITERAL1 +kHitachiAcBits LITERAL1 +kHitachiAcHdrMark LITERAL1 +kHitachiAcHdrSpace LITERAL1 +kHitachiAcMinGap LITERAL1 +kHitachiAcOneSpace LITERAL1 +kHitachiAcStateLength LITERAL1 +kHitachiAcZeroSpace LITERAL1 +kIdleState LITERAL1 +kJvcBitMark LITERAL1 +kJvcBitMarkTicks LITERAL1 +kJvcBits LITERAL1 +kJvcHdrMark LITERAL1 +kJvcHdrMarkTicks LITERAL1 +kJvcHdrSpace LITERAL1 +kJvcHdrSpaceTicks LITERAL1 +kJvcMinGap LITERAL1 +kJvcMinGapTicks LITERAL1 +kJvcOneSpace LITERAL1 +kJvcOneSpaceTicks LITERAL1 +kJvcRptLength LITERAL1 +kJvcRptLengthTicks LITERAL1 +kJvcTick LITERAL1 +kJvcZeroSpace LITERAL1 +kJvcZeroSpaceTicks LITERAL1 +kKelvinatorAuto LITERAL1 +kKelvinatorAutoTemp LITERAL1 +kKelvinatorBasicFanMask LITERAL1 +kKelvinatorBasicFanMax LITERAL1 +kKelvinatorBitMark LITERAL1 +kKelvinatorBitMarkTicks LITERAL1 +kKelvinatorBits LITERAL1 +kKelvinatorChecksumStart LITERAL1 +kKelvinatorCmdFooter LITERAL1 +kKelvinatorCmdFooterBits LITERAL1 +kKelvinatorCool LITERAL1 +kKelvinatorDry LITERAL1 +kKelvinatorFan LITERAL1 +kKelvinatorFanAuto LITERAL1 +kKelvinatorFanMask LITERAL1 +kKelvinatorFanMax LITERAL1 +kKelvinatorFanOffset LITERAL1 +kKelvinatorGapSpace LITERAL1 +kKelvinatorGapSpaceTicks LITERAL1 +kKelvinatorHdrMark LITERAL1 +kKelvinatorHdrMarkTicks LITERAL1 +kKelvinatorHdrSpace LITERAL1 +kKelvinatorHdrSpaceTicks LITERAL1 +kKelvinatorHeat LITERAL1 +kKelvinatorIonFilter LITERAL1 +kKelvinatorIonFilterOffset LITERAL1 +kKelvinatorLight LITERAL1 +kKelvinatorLightOffset LITERAL1 +kKelvinatorMaxTemp LITERAL1 +kKelvinatorMinTemp LITERAL1 +kKelvinatorModeMask LITERAL1 +kKelvinatorOneSpace LITERAL1 +kKelvinatorOneSpaceTicks LITERAL1 +kKelvinatorPower LITERAL1 +kKelvinatorQuiet LITERAL1 +kKelvinatorQuietOffset LITERAL1 +kKelvinatorSleep1And3 LITERAL1 +kKelvinatorStateLength LITERAL1 +kKelvinatorTick LITERAL1 +kKelvinatorTurbo LITERAL1 +kKelvinatorTurboOffset LITERAL1 +kKelvinatorVentSwing LITERAL1 +kKelvinatorVentSwingH LITERAL1 +kKelvinatorVentSwingOffset LITERAL1 +kKelvinatorVentSwingV LITERAL1 +kKelvinatorXfan LITERAL1 +kKelvinatorXfanOffset LITERAL1 +kKelvinatorZeroSpace LITERAL1 +kKelvinatorZeroSpaceTicks LITERAL1 +kLasertagBits LITERAL1 +kLasertagDelta LITERAL1 +kLasertagExcess LITERAL1 +kLasertagMinGap LITERAL1 +kLasertagMinRepeat LITERAL1 +kLasertagMinSamples LITERAL1 +kLasertagTick LITERAL1 +kLasertagTolerance LITERAL1 +kLg2BitMark LITERAL1 +kLg2BitMarkTicks LITERAL1 +kLg2HdrMark LITERAL1 +kLg2HdrMarkTicks LITERAL1 +kLg2HdrSpace LITERAL1 +kLg2HdrSpaceTicks LITERAL1 +kLg32Bits LITERAL1 +kLg32HdrMark LITERAL1 +kLg32HdrMarkTicks LITERAL1 +kLg32HdrSpace LITERAL1 +kLg32HdrSpaceTicks LITERAL1 +kLg32RptHdrMark LITERAL1 +kLg32RptHdrMarkTicks LITERAL1 +kLgBitMark LITERAL1 +kLgBitMarkTicks LITERAL1 +kLgBits LITERAL1 +kLgHdrMark LITERAL1 +kLgHdrMarkTicks LITERAL1 +kLgHdrSpace LITERAL1 +kLgHdrSpaceTicks LITERAL1 +kLgMinGap LITERAL1 +kLgMinGapTicks LITERAL1 +kLgMinMessageLength LITERAL1 +kLgMinMessageLengthTicks LITERAL1 +kLgOneSpace LITERAL1 +kLgOneSpaceTicks LITERAL1 +kLgRptSpace LITERAL1 +kLgRptSpaceTicks LITERAL1 +kLgTick LITERAL1 +kLgZeroSpace LITERAL1 +kLgZeroSpaceTicks LITERAL1 +kLutronBits LITERAL1 +kLutronDelta LITERAL1 +kLutronGap LITERAL1 +kLutronTick LITERAL1 +kMWMDelta LITERAL1 +kMWMExcess LITERAL1 +kMWMMaxWidth LITERAL1 +kMWMMinGap LITERAL1 +kMWMMinSamples LITERAL1 +kMWMTick LITERAL1 +kMWMTolerance LITERAL1 +kMagiQuestGap LITERAL1 +kMagiQuestMarkOne LITERAL1 +kMagiQuestMarkZero LITERAL1 +kMagiQuestOneRatio LITERAL1 +kMagiQuestSpaceOne LITERAL1 +kMagiQuestSpaceZero LITERAL1 +kMagiQuestTotalUsec LITERAL1 +kMagiQuestZeroRatio LITERAL1 +kMagiquestBits LITERAL1 +kMark LITERAL1 +kMarkExcess LITERAL1 +kMarkState LITERAL1 +kMaxAccurateUsecDelay LITERAL1 +kMaxTimeoutMs LITERAL1 +kMideaACAuto LITERAL1 +kMideaACChecksumMask LITERAL1 +kMideaACCool LITERAL1 +kMideaACDry LITERAL1 +kMideaACFan LITERAL1 +kMideaACFanAuto LITERAL1 +kMideaACFanHigh LITERAL1 +kMideaACFanLow LITERAL1 +kMideaACFanMask LITERAL1 +kMideaACFanMed LITERAL1 +kMideaACHeat LITERAL1 +kMideaACMaxTempC LITERAL1 +kMideaACMaxTempF LITERAL1 +kMideaACMinTempC LITERAL1 +kMideaACMinTempF LITERAL1 +kMideaACModeMask LITERAL1 +kMideaACPower LITERAL1 +kMideaACSleep LITERAL1 +kMideaACStateMask LITERAL1 +kMideaACTempMask LITERAL1 +kMideaBitMark LITERAL1 +kMideaBitMarkTicks LITERAL1 +kMideaBits LITERAL1 +kMideaHdrMark LITERAL1 +kMideaHdrMarkTicks LITERAL1 +kMideaHdrSpace LITERAL1 +kMideaHdrSpaceTicks LITERAL1 +kMideaMinGap LITERAL1 +kMideaMinGapTicks LITERAL1 +kMideaMinRepeat LITERAL1 +kMideaOneSpace LITERAL1 +kMideaOneSpaceTicks LITERAL1 +kMideaTick LITERAL1 +kMideaTolerance LITERAL1 +kMideaZeroSpace LITERAL1 +kMideaZeroSpaceTicks LITERAL1 +kMitsubishi2BitMark LITERAL1 +kMitsubishi2HdrMark LITERAL1 +kMitsubishi2HdrSpace LITERAL1 +kMitsubishi2MinGap LITERAL1 +kMitsubishi2OneSpace LITERAL1 +kMitsubishi2ZeroSpace LITERAL1 +kMitsubishiACBits LITERAL1 +kMitsubishiACMinRepeat LITERAL1 +kMitsubishiACStateLength LITERAL1 +kMitsubishiAcAuto LITERAL1 +kMitsubishiAcBitMark LITERAL1 +kMitsubishiAcCool LITERAL1 +kMitsubishiAcDry LITERAL1 +kMitsubishiAcFanAuto LITERAL1 +kMitsubishiAcFanMax LITERAL1 +kMitsubishiAcFanRealMax LITERAL1 +kMitsubishiAcFanSilent LITERAL1 +kMitsubishiAcHdrMark LITERAL1 +kMitsubishiAcHdrSpace LITERAL1 +kMitsubishiAcHeat LITERAL1 +kMitsubishiAcMaxTemp LITERAL1 +kMitsubishiAcMinTemp LITERAL1 +kMitsubishiAcNoTimer LITERAL1 +kMitsubishiAcOneSpace LITERAL1 +kMitsubishiAcPower LITERAL1 +kMitsubishiAcRptMark LITERAL1 +kMitsubishiAcRptSpace LITERAL1 +kMitsubishiAcStartStopTimer LITERAL1 +kMitsubishiAcStartTimer LITERAL1 +kMitsubishiAcStopTimer LITERAL1 +kMitsubishiAcVaneAuto LITERAL1 +kMitsubishiAcVaneAutoMove LITERAL1 +kMitsubishiAcZeroSpace LITERAL1 +kMitsubishiBitMark LITERAL1 +kMitsubishiBitMarkTicks LITERAL1 +kMitsubishiBits LITERAL1 +kMitsubishiMinCommandLength LITERAL1 +kMitsubishiMinCommandLengthTicks LITERAL1 +kMitsubishiMinGap LITERAL1 +kMitsubishiMinGapTicks LITERAL1 +kMitsubishiMinRepeat LITERAL1 +kMitsubishiOneSpace LITERAL1 +kMitsubishiOneSpaceTicks LITERAL1 +kMitsubishiTick LITERAL1 +kMitsubishiZeroSpace LITERAL1 +kMitsubishiZeroSpaceTicks LITERAL1 +kNECBits LITERAL1 +kNecBitMark LITERAL1 +kNecBitMarkTicks LITERAL1 +kNecHdrMark LITERAL1 +kNecHdrMarkTicks LITERAL1 +kNecHdrSpace LITERAL1 +kNecHdrSpaceTicks LITERAL1 +kNecMinCommandLength LITERAL1 +kNecMinCommandLengthTicks LITERAL1 +kNecMinGap LITERAL1 +kNecMinGapTicks LITERAL1 +kNecOneSpace LITERAL1 +kNecOneSpaceTicks LITERAL1 +kNecRptLength LITERAL1 +kNecRptSpace LITERAL1 +kNecRptSpaceTicks LITERAL1 +kNecTick LITERAL1 +kNecZeroSpace LITERAL1 +kNecZeroSpaceTicks LITERAL1 +kNikaiBitMark LITERAL1 +kNikaiBitMarkTicks LITERAL1 +kNikaiBits LITERAL1 +kNikaiHdrMark LITERAL1 +kNikaiHdrMarkTicks LITERAL1 +kNikaiHdrSpace LITERAL1 +kNikaiHdrSpaceTicks LITERAL1 +kNikaiMinGap LITERAL1 +kNikaiMinGapTicks LITERAL1 +kNikaiOneSpace LITERAL1 +kNikaiOneSpaceTicks LITERAL1 +kNikaiTick LITERAL1 +kNikaiZeroSpace LITERAL1 +kNikaiZeroSpaceTicks LITERAL1 +kNoRepeat LITERAL1 +kPanasonicAcAuto LITERAL1 +kPanasonicAcBits LITERAL1 +kPanasonicAcChecksumInit LITERAL1 +kPanasonicAcCool LITERAL1 +kPanasonicAcDry LITERAL1 +kPanasonicAcExcess LITERAL1 +kPanasonicAcFan LITERAL1 +kPanasonicAcFanAuto LITERAL1 +kPanasonicAcFanMax LITERAL1 +kPanasonicAcFanMin LITERAL1 +kPanasonicAcFanModeTemp LITERAL1 +kPanasonicAcFanOffset LITERAL1 +kPanasonicAcHeat LITERAL1 +kPanasonicAcMaxTemp LITERAL1 +kPanasonicAcMessageGap LITERAL1 +kPanasonicAcMinTemp LITERAL1 +kPanasonicAcOffTimer LITERAL1 +kPanasonicAcOnTimer LITERAL1 +kPanasonicAcPower LITERAL1 +kPanasonicAcPowerful LITERAL1 +kPanasonicAcPowerfulCkp LITERAL1 +kPanasonicAcQuiet LITERAL1 +kPanasonicAcQuietCkp LITERAL1 +kPanasonicAcSection1Length LITERAL1 +kPanasonicAcSectionGap LITERAL1 +kPanasonicAcShortBits LITERAL1 +kPanasonicAcStateLength LITERAL1 +kPanasonicAcStateShortLength LITERAL1 +kPanasonicAcSwingHAuto LITERAL1 +kPanasonicAcSwingHFullLeft LITERAL1 +kPanasonicAcSwingHFullRight LITERAL1 +kPanasonicAcSwingHLeft LITERAL1 +kPanasonicAcSwingHMiddle LITERAL1 +kPanasonicAcSwingHRight LITERAL1 +kPanasonicAcSwingVAuto LITERAL1 +kPanasonicAcSwingVDown LITERAL1 +kPanasonicAcSwingVUp LITERAL1 +kPanasonicAcTimeMax LITERAL1 +kPanasonicAcTimeSpecial LITERAL1 +kPanasonicAcTolerance LITERAL1 +kPanasonicBitMark LITERAL1 +kPanasonicBitMarkTicks LITERAL1 +kPanasonicBits LITERAL1 +kPanasonicCkp LITERAL1 +kPanasonicDke LITERAL1 +kPanasonicEndGap LITERAL1 +kPanasonicFreq LITERAL1 +kPanasonicHdrMark LITERAL1 +kPanasonicHdrMarkTicks LITERAL1 +kPanasonicHdrSpace LITERAL1 +kPanasonicHdrSpaceTicks LITERAL1 +kPanasonicJke LITERAL1 +kPanasonicKnownGoodState LITERAL1 +kPanasonicLke LITERAL1 +kPanasonicManufacturer LITERAL1 +kPanasonicMinCommandLength LITERAL1 +kPanasonicMinCommandLengthTicks LITERAL1 +kPanasonicMinGap LITERAL1 +kPanasonicMinGapTicks LITERAL1 +kPanasonicNke LITERAL1 +kPanasonicOneSpace LITERAL1 +kPanasonicOneSpaceTicks LITERAL1 +kPanasonicTick LITERAL1 +kPanasonicUnknown LITERAL1 +kPanasonicZeroSpace LITERAL1 +kPanasonicZeroSpaceTicks LITERAL1 +kPeriodOffset LITERAL1 +kPioneerBits LITERAL1 +kProntoDataOffset LITERAL1 +kProntoFreqFactor LITERAL1 +kProntoFreqOffset LITERAL1 +kProntoMinLength LITERAL1 +kProntoSeq1LenOffset LITERAL1 +kProntoSeq2LenOffset LITERAL1 +kProntoTypeOffset LITERAL1 +kRC5Bits LITERAL1 +kRC5RawBits LITERAL1 +kRC5XBits LITERAL1 +kRC6Mode0Bits LITERAL1 +kRC6_36Bits LITERAL1 +kRCMMBits LITERAL1 +kRawBuf LITERAL1 +kRawTick LITERAL1 +kRc5MinCommandLength LITERAL1 +kRc5MinGap LITERAL1 +kRc5SamplesMin LITERAL1 +kRc5T1 LITERAL1 +kRc5ToggleMask LITERAL1 +kRc6HdrMark LITERAL1 +kRc6HdrMarkTicks LITERAL1 +kRc6HdrSpace LITERAL1 +kRc6HdrSpaceTicks LITERAL1 +kRc6RptLength LITERAL1 +kRc6RptLengthTicks LITERAL1 +kRc6Tick LITERAL1 +kRc6ToggleMask LITERAL1 +kRc6_36ToggleMask LITERAL1 +kRcmmBitMark LITERAL1 +kRcmmBitMarkTicks LITERAL1 +kRcmmBitSpace0 LITERAL1 +kRcmmBitSpace0Ticks LITERAL1 +kRcmmBitSpace1 LITERAL1 +kRcmmBitSpace1Ticks LITERAL1 +kRcmmBitSpace2 LITERAL1 +kRcmmBitSpace2Ticks LITERAL1 +kRcmmBitSpace3 LITERAL1 +kRcmmBitSpace3Ticks LITERAL1 +kRcmmExcess LITERAL1 +kRcmmHdrMark LITERAL1 +kRcmmHdrMarkTicks LITERAL1 +kRcmmHdrSpace LITERAL1 +kRcmmHdrSpaceTicks LITERAL1 +kRcmmMinGap LITERAL1 +kRcmmMinGapTicks LITERAL1 +kRcmmRptLength LITERAL1 +kRcmmRptLengthTicks LITERAL1 +kRcmmTick LITERAL1 +kRcmmTolerance LITERAL1 +kRepeat LITERAL1 +kSamsungACSectionLength LITERAL1 +kSamsungAcAuto LITERAL1 +kSamsungAcAutoTemp LITERAL1 +kSamsungAcBeepMask LITERAL1 +kSamsungAcBitMark LITERAL1 +kSamsungAcBits LITERAL1 +kSamsungAcCleanMask10 LITERAL1 +kSamsungAcCleanMask11 LITERAL1 +kSamsungAcCool LITERAL1 +kSamsungAcDry LITERAL1 +kSamsungAcExtendedBits LITERAL1 +kSamsungAcExtendedStateLength LITERAL1 +kSamsungAcFan LITERAL1 +kSamsungAcFanAuto LITERAL1 +kSamsungAcFanAuto2 LITERAL1 +kSamsungAcFanHigh LITERAL1 +kSamsungAcFanLow LITERAL1 +kSamsungAcFanMask LITERAL1 +kSamsungAcFanMed LITERAL1 +kSamsungAcFanTurbo LITERAL1 +kSamsungAcHdrMark LITERAL1 +kSamsungAcHdrSpace LITERAL1 +kSamsungAcHeat LITERAL1 +kSamsungAcMaxTemp LITERAL1 +kSamsungAcMinTemp LITERAL1 +kSamsungAcModeMask LITERAL1 +kSamsungAcOneSpace LITERAL1 +kSamsungAcPowerMask1 LITERAL1 +kSamsungAcPowerMask2 LITERAL1 +kSamsungAcPowerSection LITERAL1 +kSamsungAcQuietMask11 LITERAL1 +kSamsungAcSectionGap LITERAL1 +kSamsungAcSectionMark LITERAL1 +kSamsungAcSectionSpace LITERAL1 +kSamsungAcSections LITERAL1 +kSamsungAcStateLength LITERAL1 +kSamsungAcSwingMask LITERAL1 +kSamsungAcSwingMove LITERAL1 +kSamsungAcSwingStop LITERAL1 +kSamsungAcTempMask LITERAL1 +kSamsungAcZeroSpace LITERAL1 +kSamsungBitMark LITERAL1 +kSamsungBitMarkTicks LITERAL1 +kSamsungBits LITERAL1 +kSamsungHdrMark LITERAL1 +kSamsungHdrMarkTicks LITERAL1 +kSamsungHdrSpace LITERAL1 +kSamsungHdrSpaceTicks LITERAL1 +kSamsungMinGap LITERAL1 +kSamsungMinGapTicks LITERAL1 +kSamsungMinMessageLength LITERAL1 +kSamsungMinMessageLengthTicks LITERAL1 +kSamsungOneSpace LITERAL1 +kSamsungOneSpaceTicks LITERAL1 +kSamsungRptSpace LITERAL1 +kSamsungRptSpaceTicks LITERAL1 +kSamsungTick LITERAL1 +kSamsungZeroSpace LITERAL1 +kSamsungZeroSpaceTicks LITERAL1 +kSanyoLC7461AddressBits LITERAL1 +kSanyoLC7461Bits LITERAL1 +kSanyoLC7461CommandBits LITERAL1 +kSanyoLc7461AddressMask LITERAL1 +kSanyoLc7461BitMark LITERAL1 +kSanyoLc7461CommandMask LITERAL1 +kSanyoLc7461HdrMark LITERAL1 +kSanyoLc7461HdrSpace LITERAL1 +kSanyoLc7461MinCommandLength LITERAL1 +kSanyoLc7461MinGap LITERAL1 +kSanyoLc7461OneSpace LITERAL1 +kSanyoLc7461ZeroSpace LITERAL1 +kSanyoSA8650BBits LITERAL1 +kSanyoSa8650bDoubleSpaceUsecs LITERAL1 +kSanyoSa8650bHdrMark LITERAL1 +kSanyoSa8650bHdrSpace LITERAL1 +kSanyoSa8650bOneMark LITERAL1 +kSanyoSa8650bRptLength LITERAL1 +kSanyoSa8650bZeroMark LITERAL1 +kSharpAddressBits LITERAL1 +kSharpAddressMask LITERAL1 +kSharpBitMark LITERAL1 +kSharpBitMarkTicks LITERAL1 +kSharpBits LITERAL1 +kSharpCommandBits LITERAL1 +kSharpCommandMask LITERAL1 +kSharpGap LITERAL1 +kSharpGapTicks LITERAL1 +kSharpOneSpace LITERAL1 +kSharpOneSpaceTicks LITERAL1 +kSharpTick LITERAL1 +kSharpToggleMask LITERAL1 +kSharpZeroSpace LITERAL1 +kSharpZeroSpaceTicks LITERAL1 +kSherwoodBits LITERAL1 +kSherwoodMinRepeat LITERAL1 +kSingleRepeat LITERAL1 +kSony12Bits LITERAL1 +kSony15Bits LITERAL1 +kSony20Bits LITERAL1 +kSonyHdrMark LITERAL1 +kSonyHdrMarkTicks LITERAL1 +kSonyMinBits LITERAL1 +kSonyMinGap LITERAL1 +kSonyMinGapTicks LITERAL1 +kSonyMinRepeat LITERAL1 +kSonyOneMark LITERAL1 +kSonyOneMarkTicks LITERAL1 +kSonyRptLength LITERAL1 +kSonyRptLengthTicks LITERAL1 +kSonySpace LITERAL1 +kSonySpaceTicks LITERAL1 +kSonyTick LITERAL1 +kSonyZeroMark LITERAL1 +kSonyZeroMarkTicks LITERAL1 +kSpace LITERAL1 +kSpaceState LITERAL1 +kStartOffset LITERAL1 +kStateSizeMax LITERAL1 +kStopState LITERAL1 +kTimeoutMs LITERAL1 +kTolerance LITERAL1 +kToshibaACBits LITERAL1 +kToshibaACMinRepeat LITERAL1 +kToshibaACStateLength LITERAL1 +kToshibaAcAuto LITERAL1 +kToshibaAcBitMark LITERAL1 +kToshibaAcCool LITERAL1 +kToshibaAcDry LITERAL1 +kToshibaAcFanAuto LITERAL1 +kToshibaAcFanMax LITERAL1 +kToshibaAcHdrMark LITERAL1 +kToshibaAcHdrSpace LITERAL1 +kToshibaAcHeat LITERAL1 +kToshibaAcMaxTemp LITERAL1 +kToshibaAcMinGap LITERAL1 +kToshibaAcMinTemp LITERAL1 +kToshibaAcOneSpace LITERAL1 +kToshibaAcPower LITERAL1 +kToshibaAcZeroSpace LITERAL1 +kTrotecAuto LITERAL1 +kTrotecCool LITERAL1 +kTrotecDefTemp LITERAL1 +kTrotecDry LITERAL1 +kTrotecFan LITERAL1 +kTrotecFanHigh LITERAL1 +kTrotecFanLow LITERAL1 +kTrotecFanMed LITERAL1 +kTrotecGap LITERAL1 +kTrotecGapEnd LITERAL1 +kTrotecHdrMark LITERAL1 +kTrotecHdrSpace LITERAL1 +kTrotecIntro1 LITERAL1 +kTrotecIntro2 LITERAL1 +kTrotecMaxTemp LITERAL1 +kTrotecMaxTimer LITERAL1 +kTrotecMinTemp LITERAL1 +kTrotecMinTimer LITERAL1 +kTrotecOff LITERAL1 +kTrotecOn LITERAL1 +kTrotecOneMark LITERAL1 +kTrotecOneSpace LITERAL1 +kTrotecSleepOn LITERAL1 +kTrotecStateLength LITERAL1 +kTrotecTimerOn LITERAL1 +kTrotecZeroMark LITERAL1 +kTrotecZeroSpace LITERAL1 +kUnknownThreshold LITERAL1 +kWhirlpoolAcBitMark LITERAL1 +kWhirlpoolAcBits LITERAL1 +kWhirlpoolAcGap LITERAL1 +kWhirlpoolAcHdrMark LITERAL1 +kWhirlpoolAcHdrSpace LITERAL1 +kWhirlpoolAcMinGap LITERAL1 +kWhirlpoolAcOneSpace LITERAL1 +kWhirlpoolAcSections LITERAL1 +kWhirlpoolAcStateLength LITERAL1 +kWhirlpoolAcZeroSpace LITERAL1 +kWhynterBitMark LITERAL1 +kWhynterBitMarkTicks LITERAL1 +kWhynterBits LITERAL1 +kWhynterHdrMark LITERAL1 +kWhynterHdrMarkTicks LITERAL1 +kWhynterHdrSpace LITERAL1 +kWhynterHdrSpaceTicks LITERAL1 +kWhynterMinCommandLength LITERAL1 +kWhynterMinCommandLengthTicks LITERAL1 +kWhynterMinGap LITERAL1 +kWhynterMinGapTicks LITERAL1 +kWhynterOneSpace LITERAL1 +kWhynterOneSpaceTicks LITERAL1 +kWhynterTick LITERAL1 +kWhynterZeroSpace LITERAL1 +kWhynterZeroSpaceTicks LITERAL1 diff --git a/lib/IRremoteESP8266-2.2.1.02/library.json b/lib/IRremoteESP8266-2.5.2.03/library.json similarity index 97% rename from lib/IRremoteESP8266-2.2.1.02/library.json rename to lib/IRremoteESP8266-2.5.2.03/library.json index b8141a2eb..3fc14f027 100644 --- a/lib/IRremoteESP8266-2.2.1.02/library.json +++ b/lib/IRremoteESP8266-2.5.2.03/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.2.1", + "version": "2.5.2", "keywords": "infrared, ir, remote, esp8266", "description": "Send and receive infrared signals with multiple protocols (ESP8266)", "repository": diff --git a/lib/IRremoteESP8266-2.2.1.02/library.properties b/lib/IRremoteESP8266-2.5.2.03/library.properties similarity index 96% rename from lib/IRremoteESP8266-2.2.1.02/library.properties rename to lib/IRremoteESP8266-2.5.2.03/library.properties index ae6f93da7..e71dc4154 100644 --- a/lib/IRremoteESP8266-2.2.1.02/library.properties +++ b/lib/IRremoteESP8266-2.5.2.03/library.properties @@ -1,5 +1,5 @@ name=IRremoteESP8266 -version=2.2.1 +version=2.5.2 author=Sebastien Warin, Mark Szabo, Ken Shirriff, David Conran maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto sentence=Send and receive infrared signals with multiple protocols (ESP8266) diff --git a/lib/IRremoteESP8266-2.2.1.02/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/platformio.ini diff --git a/lib/IRremoteESP8266-2.5.2.03/pylintrc b/lib/IRremoteESP8266-2.5.2.03/pylintrc new file mode 100644 index 000000000..987c6abf9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/pylintrc @@ -0,0 +1,12 @@ +[REPORTS] + +# Tells whether to display a full report or only the messages +reports=no + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# String used as indentation unit. +indent-string=' ' diff --git a/lib/IRremoteESP8266-2.2.1.02/src/CPPLINT.cfg b/lib/IRremoteESP8266-2.5.2.03/src/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/src/CPPLINT.cfg rename to lib/IRremoteESP8266-2.5.2.03/src/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp b/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.cpp similarity index 59% rename from lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/IRrecv.cpp index d8e390633..b2c984396 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.cpp @@ -7,13 +7,14 @@ #include #ifndef UNIT_TEST extern "C" { - #include - #include +#include +#include } #include #endif #include #include "IRremoteESP8266.h" +#include "IRutils.h" #ifdef UNIT_TEST #undef ICACHE_RAM_ATTR @@ -34,8 +35,7 @@ irparams_t *irparams_save; // A copy of the interrupt state while decoding. #ifndef UNIT_TEST static void ICACHE_RAM_ATTR read_timeout(void *arg __attribute__((unused))) { os_intr_lock(); - if (irparams.rawlen) - irparams.rcvstate = STATE_STOP; + if (irparams.rawlen) irparams.rcvstate = kStopState; os_intr_unlock(); } @@ -57,25 +57,24 @@ static void ICACHE_RAM_ATTR gpio_intr() { if (rawlen >= irparams.bufsize) { irparams.overflow = true; - irparams.rcvstate = STATE_STOP; + irparams.rcvstate = kStopState; } - if (irparams.rcvstate == STATE_STOP) - return; + if (irparams.rcvstate == kStopState) return; - if (irparams.rcvstate == STATE_IDLE) { - irparams.rcvstate = STATE_MARK; + if (irparams.rcvstate == kIdleState) { + irparams.rcvstate = kMarkState; irparams.rawbuf[rawlen] = 1; } else { if (now < start) - irparams.rawbuf[rawlen] = (UINT32_MAX - start + now) / RAWTICK; + irparams.rawbuf[rawlen] = (UINT32_MAX - start + now) / kRawTick; else - irparams.rawbuf[rawlen] = (now - start) / RAWTICK; + irparams.rawbuf[rawlen] = (now - start) / kRawTick; } irparams.rawlen++; start = now; - #define ONCE 0 +#define ONCE 0 os_timer_arm(&timer, irparams.timeout, ONCE); } #endif // UNIT_TEST @@ -85,23 +84,24 @@ static void ICACHE_RAM_ATTR gpio_intr() { // Class constructor // Args: // recvpin: GPIO pin the IR receiver module's data pin is connected to. -// bufsize: Nr. of entries to have in the capture buffer. (Default: RAWBUF) +// bufsize: Nr. of entries to have in the capture buffer. (Default: kRawBuf) // timeout: Nr. of milli-Seconds of no signal before we stop capturing data. -// (Default: TIMEOUT_MS) +// (Default: kTimeoutMs) // save_buffer: Use a second (save) buffer to decode from. (Def: false) // Returns: -// A IRrecv class object. +// An IRrecv class object. IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize, uint8_t timeout, bool save_buffer) { irparams.recvpin = recvpin; irparams.bufsize = bufsize; // Ensure we are going to be able to store all possible values in the // capture buffer. - irparams.timeout = std::min(timeout, (uint8_t) MAX_TIMEOUT_MS); + irparams.timeout = std::min(timeout, (uint8_t)kMaxTimeoutMs); irparams.rawbuf = new uint16_t[bufsize]; if (irparams.rawbuf == NULL) { - DPRINTLN("Could not allocate memory for the primary IR buffer.\n" - "Try a smaller size for CAPTURE_BUFFER_SIZE.\nRebooting!"); + DPRINTLN( + "Could not allocate memory for the primary IR buffer.\n" + "Try a smaller size for CAPTURE_BUFFER_SIZE.\nRebooting!"); #ifndef UNIT_TEST ESP.restart(); // Mem alloc failure. Reboot. #endif @@ -112,8 +112,9 @@ IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize, uint8_t timeout, irparams_save->rawbuf = new uint16_t[bufsize]; // Check we allocated the memory successfully. if (irparams_save->rawbuf == NULL) { - DPRINTLN("Could not allocate memory for the second IR buffer.\n" - "Try a smaller size for CAPTURE_BUFFER_SIZE.\nRebooting!"); + DPRINTLN( + "Could not allocate memory for the second IR buffer.\n" + "Try a smaller size for CAPTURE_BUFFER_SIZE.\nRebooting!"); #ifndef UNIT_TEST ESP.restart(); // Mem alloc failure. Reboot. #endif @@ -121,13 +122,16 @@ IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize, uint8_t timeout, } else { irparams_save = NULL; } +#if DECODE_HASH + unknown_threshold = kUnknownThreshold; +#endif // DECODE_HASH } // Class destructor IRrecv::~IRrecv(void) { - delete [] irparams.rawbuf; + delete[] irparams.rawbuf; if (irparams_save != NULL) { - delete [] irparams_save->rawbuf; + delete[] irparams_save->rawbuf; delete irparams_save; } } @@ -156,7 +160,7 @@ void IRrecv::disableIRIn() { } void IRrecv::resume() { - irparams.rcvstate = STATE_IDLE; + irparams.rcvstate = kIdleState; irparams.rawlen = 0; irparams.overflow = false; } @@ -164,15 +168,15 @@ void IRrecv::resume() { // Make a copy of the interrupt state & buffer data. // Needed because irparams is marked as volatile, thus memcpy() isn't allowed. // Only call this when you know the interrupt handlers won't modify anything. -// i.e. In STATE_STOP. +// i.e. In kStopState. // // Args: // src: Pointer to an irparams_t structure to copy from. // dst: Pointer to an irparams_t structure to copy to. void IRrecv::copyIrParams(volatile irparams_t *src, irparams_t *dst) { // Typecast src and dst addresses to (char *) - char *csrc = (char *) src; // NOLINT(readability/casting) - char *cdst = (char *) dst; // NOLINT(readability/casting) + char *csrc = (char *)src; // NOLINT(readability/casting) + char *cdst = (char *)dst; // NOLINT(readability/casting) // Save the pointer to the destination's rawbuf so we don't lose it as // the for-loop/copy after this will overwrite it with src's rawbuf pointer. @@ -181,22 +185,25 @@ void IRrecv::copyIrParams(volatile irparams_t *src, irparams_t *dst) { dst_rawbuf_ptr = dst->rawbuf; // Copy contents of src[] to dst[] - for (uint16_t i = 0; i < sizeof(irparams_t); i++) - cdst[i] = csrc[i]; + for (uint16_t i = 0; i < sizeof(irparams_t); i++) cdst[i] = csrc[i]; // Restore the buffer pointer dst->rawbuf = dst_rawbuf_ptr; // Copy the rawbuf - for (uint16_t i = 0; i < dst->bufsize; i++) - dst->rawbuf[i] = src->rawbuf[i]; + for (uint16_t i = 0; i < dst->bufsize; i++) dst->rawbuf[i] = src->rawbuf[i]; } // Obtain the maximum number of entries possible in the capture buffer. // i.e. It's size. -uint16_t IRrecv::getBufSize() { - return irparams.bufsize; +uint16_t IRrecv::getBufSize() { return irparams.bufsize; } + +#if DECODE_HASH +// Set the minimum length we will consider for reporting UNKNOWN message types. +void IRrecv::setUnknownThreshold(uint16_t length) { + unknown_threshold = length; } +#endif // DECODE_HASH // Decodes the received IR message. // If the interrupt state is saved, we will immediately resume waiting @@ -213,8 +220,7 @@ uint16_t IRrecv::getBufSize() { bool IRrecv::decode(decode_results *results, irparams_t *save) { // Proceed only if an IR message been received. #ifndef UNIT_TEST - if (irparams.rcvstate != STATE_STOP) - return false; + if (irparams.rcvstate != kStopState) return false; #endif // Clear the entry we are currently pointing to when we got the timeout. @@ -230,8 +236,7 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { bool resumed = false; // Flag indicating if we have resumed. // If we were requested to use a save buffer previously, do so. - if (save == NULL) - save = irparams_save; + if (save == NULL) save = irparams_save; if (save == NULL) { // We haven't been asked to copy it so use the existing memory. @@ -263,8 +268,7 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { // Try decodeAiwaRCT501() before decodeSanyoLC7461() & decodeNEC() // because the protocols are similar. This protocol is more specific than // those ones, so should got before them. - if (decodeAiwaRCT501(results)) - return true; + if (decodeAiwaRCT501(results)) return true; #endif #if DECODE_SANYO DPRINTLN("Attempting Sanyo LC7461 decode"); @@ -272,97 +276,135 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { // similar in timings & structure, but the Sanyo one is much longer than the // NEC protocol (42 vs 32 bits) so this one should be tried first to try to // reduce false detection as a NEC packet. - if (decodeSanyoLC7461(results)) - return true; + if (decodeSanyoLC7461(results)) return true; +#endif +#if DECODE_CARRIER_AC + DPRINTLN("Attempting Carrier AC decode"); + // Try decodeCarrierAC() before decodeNEC() because the protocols are + // similar in timings & structure, but the Carrier one is much longer than the + // NEC protocol (3x32 bits vs 1x32 bits) so this one should be tried first to + // try to reduce false detection as a NEC packet. + if (decodeCarrierAC(results)) return true; +#endif +#if DECODE_PIONEER + DPRINTLN("Attempting Pioneer decode"); + // Try decodePioneer() before decodeNEC() because the protocols are + // similar in timings & structure, but the Pioneer one is much longer than the + // NEC protocol (2x32 bits vs 1x32 bits) so this one should be tried first to + // try to reduce false detection as a NEC packet. + if (decodePioneer(results)) return true; #endif #if DECODE_NEC DPRINTLN("Attempting NEC decode"); - if (decodeNEC(results)) - return true; + if (decodeNEC(results)) return true; #endif #if DECODE_SONY DPRINTLN("Attempting Sony decode"); - if (decodeSony(results)) - return true; + if (decodeSony(results)) return true; #endif #if DECODE_MITSUBISHI DPRINTLN("Attempting Mitsubishi decode"); - if (decodeMitsubishi(results)) - return true; + if (decodeMitsubishi(results)) return true; +#endif +#if DECODE_MITSUBISHI_AC + DPRINTLN("Attempting Mitsubishi AC decode"); + if (decodeMitsubishiAC(results)) return true; +#endif +#if DECODE_MITSUBISHI2 + DPRINTLN("Attempting Mitsubishi2 decode"); + if (decodeMitsubishi2(results)) return true; #endif #if DECODE_RC5 DPRINTLN("Attempting RC5 decode"); - if (decodeRC5(results)) - return true; + if (decodeRC5(results)) return true; #endif #if DECODE_RC6 DPRINTLN("Attempting RC6 decode"); - if (decodeRC6(results)) - return true; + if (decodeRC6(results)) return true; #endif #if DECODE_RCMM DPRINTLN("Attempting RC-MM decode"); - if (decodeRCMM(results)) - return true; + if (decodeRCMM(results)) return true; +#endif +#if DECODE_FUJITSU_AC + // Fujitsu A/C needs to precede Panasonic and Denon as it has a short + // message which looks exactly the same as a Panasonic/Denon message. + DPRINTLN("Attempting Fujitsu A/C decode"); + if (decodeFujitsuAC(results)) return true; #endif #if DECODE_DENON // Denon needs to precede Panasonic as it is a special case of Panasonic. -#ifdef DEBUG DPRINTLN("Attempting Denon decode"); -#endif - if (decodeDenon(results, DENON_48_BITS) || - decodeDenon(results, DENON_BITS) || - decodeDenon(results, DENON_LEGACY_BITS)) + if (decodeDenon(results, DENON_48_BITS) || decodeDenon(results, DENON_BITS) || + decodeDenon(results, kDenonLegacyBits)) return true; #endif #if DECODE_PANASONIC DPRINTLN("Attempting Panasonic decode"); - if (decodePanasonic(results)) - return true; + if (decodePanasonic(results)) return true; #endif #if DECODE_LG DPRINTLN("Attempting LG (28-bit) decode"); - if (decodeLG(results, LG_BITS, true)) - return true; + if (decodeLG(results, kLgBits, true)) return true; DPRINTLN("Attempting LG (32-bit) decode"); // LG32 should be tried before Samsung - if (decodeLG(results, LG32_BITS, true)) - return true; + if (decodeLG(results, kLg32Bits, true)) return true; +#endif +#if DECODE_GICABLE + // Note: Needs to happen before JVC decode, because it looks similar except + // with a required NEC-like repeat code. + DPRINTLN("Attempting GICable decode"); + if (decodeGICable(results)) return true; #endif #if DECODE_JVC DPRINTLN("Attempting JVC decode"); - if (decodeJVC(results)) - return true; + if (decodeJVC(results)) return true; #endif #if DECODE_SAMSUNG DPRINTLN("Attempting SAMSUNG decode"); - if (decodeSAMSUNG(results)) - return true; + if (decodeSAMSUNG(results)) return true; #endif #if DECODE_WHYNTER DPRINTLN("Attempting Whynter decode"); - if (decodeWhynter(results)) - return true; + if (decodeWhynter(results)) return true; #endif #if DECODE_DISH DPRINTLN("Attempting DISH decode"); - if (decodeDISH(results)) - return true; + if (decodeDISH(results)) return true; #endif #if DECODE_SHARP DPRINTLN("Attempting Sharp decode"); - if (decodeSharp(results)) - return true; + if (decodeSharp(results)) return true; #endif #if DECODE_COOLIX DPRINTLN("Attempting Coolix decode"); - if (decodeCOOLIX(results)) - return true; + if (decodeCOOLIX(results)) return true; #endif #if DECODE_NIKAI DPRINTLN("Attempting Nikai decode"); - if (decodeNikai(results)) - return true; + if (decodeNikai(results)) return true; +#endif +#if DECODE_KELVINATOR + // Kelvinator based-devices use a similar code to Gree ones, to avoid false + // matches this needs to happen before decodeGree(). + DPRINTLN("Attempting Kelvinator decode"); + if (decodeKelvinator(results)) return true; +#endif +#if DECODE_DAIKIN + DPRINTLN("Attempting Daikin decode"); + if (decodeDaikin(results)) return true; +#endif +#if DECODE_TOSHIBA_AC + DPRINTLN("Attempting Toshiba AC decode"); + if (decodeToshibaAC(results)) return true; +#endif +#if DECODE_MIDEA + DPRINTLN("Attempting Midea decode"); + if (decodeMidea(results)) return true; +#endif +#if DECODE_MAGIQUEST + DPRINTLN("Attempting Magiquest decode"); + if (decodeMagiQuest(results)) return true; #endif /* NOTE: Disabled due to poor quality. #if DECODE_SANYO @@ -380,18 +422,81 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { // This needs to be done after all other codes that use strict and some // other protocols that are NEC-like as well, as turning off strict may // cause this to match other valid protocols. - DPRINTLN("Attempting NEC (non-stict) decode"); - if (decodeNEC(results, NEC_BITS, false)) { + DPRINTLN("Attempting NEC (non-strict) decode"); + if (decodeNEC(results, kNECBits, false)) { results->decode_type = NEC_LIKE; return true; } #endif +#if DECODE_LASERTAG + DPRINTLN("Attempting Lasertag decode"); + if (decodeLasertag(results)) return true; +#endif +#if DECODE_GREE + // Gree based-devices use a similar code to Kelvinator ones, to avoid false + // matches this needs to happen after decodeKelvinator(). + DPRINTLN("Attempting Gree decode"); + if (decodeGree(results)) return true; +#endif +#if DECODE_HAIER_AC + DPRINTLN("Attempting Haier AC decode"); + if (decodeHaierAC(results)) return true; +#endif +#if DECODE_HAIER_AC_YRW02 + DPRINTLN("Attempting Haier AC YR-W02 decode"); + if (decodeHaierACYRW02(results)) return true; +#endif +#if DECODE_HITACHI_AC2 + // HitachiAC2 should be checked before HitachiAC + DPRINTLN("Attempting Hitachi AC2 decode"); + if (decodeHitachiAC(results, kHitachiAc2Bits)) return true; +#endif +#if DECODE_HITACHI_AC + DPRINTLN("Attempting Hitachi AC decode"); + if (decodeHitachiAC(results, kHitachiAcBits)) return true; +#endif +#if DECODE_HITACHI_AC1 + DPRINTLN("Attempting Hitachi AC1 decode"); + if (decodeHitachiAC(results, kHitachiAc1Bits)) return true; +#endif +#if DECODE_WHIRLPOOL_AC + DPRINTLN("Attempting Whirlpool AC decode"); + if (decodeWhirlpoolAC(results)) return true; +#endif +#if DECODE_SAMSUNG_AC + DPRINTLN("Attempting Samsung AC (extended) decode"); + // Check the extended size first, as it should fail fast due to longer length. + if (decodeSamsungAC(results, kSamsungAcExtendedBits, false)) return true; + // Now check for the more common length. + DPRINTLN("Attempting Samsung AC decode"); + if (decodeSamsungAC(results, kSamsungAcBits)) return true; +#endif +#if DECODE_ELECTRA_AC + DPRINTLN("Attempting Electra AC decode"); + if (decodeElectraAC(results)) return true; +#endif +#if DECODE_PANASONIC_AC + DPRINTLN("Attempting Panasonic AC decode"); + if (decodePanasonicAC(results)) return true; + DPRINTLN("Attempting Panasonic AC short decode"); + if (decodePanasonicAC(results, kPanasonicAcShortBits)) return true; +#endif +#if DECODE_LUTRON + DPRINTLN("Attempting Lutron decode"); + if (decodeLutron(results)) return true; +#endif +#if DECODE_MWM + DPRINTLN("Attempting MWM decode"); + if (decodeMWM(results)) return true; +#endif +#if DECODE_HASH // decodeHash returns a hash on any input. // Thus, it needs to be last in the list. // If you add any decodes, add them before this. if (decodeHash(results)) { return true; } +#endif // DECODE_HASH // Throw away and start over if (!resumed) // Check if we have already resumed. resume(); @@ -403,11 +508,13 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { // Args: // usecs: Nr. of uSeconds. // tolerance: Percent as an integer. e.g. 10 is 10% +// delta: A non-scaling amount to reduce usecs by. // Returns: // Nr. of ticks. -uint32_t IRrecv::ticksLow(uint32_t usecs, uint8_t tolerance) { +uint32_t IRrecv::ticksLow(uint32_t usecs, uint8_t tolerance, uint16_t delta) { // max() used to ensure the result can't drop below 0 before the cast. - return((uint32_t) std::max((int32_t) (usecs * (1.0 - tolerance / 100.0)), 0)); + return ((uint32_t)std::max( + (int32_t)(usecs * (1.0 - tolerance / 100.0) - delta), 0)); } // Calculate the upper bound of the nr. of ticks. @@ -415,49 +522,52 @@ uint32_t IRrecv::ticksLow(uint32_t usecs, uint8_t tolerance) { // Args: // usecs: Nr. of uSeconds. // tolerance: Percent as an integer. e.g. 10 is 10% +// delta: A non-scaling amount to increase usecs by. // Returns: // Nr. of ticks. -uint32_t IRrecv::ticksHigh(uint32_t usecs, uint8_t tolerance) { - return((uint32_t) (usecs * (1.0 + tolerance / 100.0)) + 1); +uint32_t IRrecv::ticksHigh(uint32_t usecs, uint8_t tolerance, uint16_t delta) { + return ((uint32_t)(usecs * (1.0 + tolerance / 100.0)) + 1 + delta); } // Check if we match a pulse(measured) with the desired within -// +/-tolerance percent. +// +/-tolerance percent and/or +/- a fixed delta range. // // Args: // measured: The recorded period of the signal pulse. // desired: The expected period (in useconds) we are matching against. // tolerance: A percentage expressed as an integer. e.g. 10 is 10%. +// delta: A non-scaling (+/-) error margin (in useconds). // // Returns: // Boolean: true if it matches, false if it doesn't. -bool IRrecv::match(uint32_t measured, uint32_t desired, - uint8_t tolerance) { - measured *= RAWTICK; // Convert to uSecs. +bool IRrecv::match(uint32_t measured, uint32_t desired, uint8_t tolerance, + uint16_t delta) { + measured *= kRawTick; // Convert to uSecs. DPRINT("Matching: "); - DPRINT(ticksLow(desired, tolerance)); + DPRINT(ticksLow(desired, tolerance, delta)); DPRINT(" <= "); DPRINT(measured); DPRINT(" <= "); - DPRINTLN(ticksHigh(desired, tolerance)); - return (measured >= ticksLow(desired, tolerance) && - measured <= ticksHigh(desired, tolerance)); + DPRINTLN(ticksHigh(desired, tolerance, delta)); + return (measured >= ticksLow(desired, tolerance, delta) && + measured <= ticksHigh(desired, tolerance, delta)); } - // Check if we match a pulse(measured) of at least desired within -// +/-tolerance percent. +// tolerance percent and/or a fixed delta margin. // // Args: // measured: The recorded period of the signal pulse. // desired: The expected period (in useconds) we are matching against. // tolerance: A percentage expressed as an integer. e.g. 10 is 10%. +// delta: A non-scaling amount to reduce usecs by. + // // Returns: // Boolean: true if it matches, false if it doesn't. bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired, - uint8_t tolerance) { - measured *= RAWTICK; // Convert to uSecs. + uint8_t tolerance, uint16_t delta) { + measured *= kRawTick; // Convert to uSecs. DPRINT("Matching ATLEAST "); DPRINT(measured); DPRINT(" vs "); @@ -465,17 +575,18 @@ bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired, DPRINT(". Matching: "); DPRINT(measured); DPRINT(" >= "); - DPRINT(ticksLow(std::min(desired, MS_TO_USEC(irparams.timeout)), tolerance)); + DPRINT(ticksLow(std::min(desired, MS_TO_USEC(irparams.timeout)), tolerance, + delta)); DPRINT(" [min("); - DPRINT(ticksLow(desired, tolerance)); + DPRINT(ticksLow(desired, tolerance, delta)); DPRINT(", "); - DPRINT(ticksLow(MS_TO_USEC(irparams.timeout), tolerance)); + DPRINT(ticksLow(MS_TO_USEC(irparams.timeout), tolerance, delta)); DPRINTLN(")]"); // We really should never get a value of 0, except as the last value // in the buffer. If that is the case, then assume infinity and return true. if (measured == 0) return true; return measured >= ticksLow(std::min(desired, MS_TO_USEC(irparams.timeout)), - tolerance); + tolerance, delta); } // Check if we match a mark signal(measured) with the desired within @@ -489,10 +600,10 @@ bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired, // // Returns: // Boolean: true if it matches, false if it doesn't. -bool IRrecv::matchMark(uint32_t measured, uint32_t desired, - uint8_t tolerance, int16_t excess) { +bool IRrecv::matchMark(uint32_t measured, uint32_t desired, uint8_t tolerance, + int16_t excess) { DPRINT("Matching MARK "); - DPRINT(measured * RAWTICK); + DPRINT(measured * kRawTick); DPRINT(" vs "); DPRINT(desired); DPRINT(" + "); @@ -512,10 +623,10 @@ bool IRrecv::matchMark(uint32_t measured, uint32_t desired, // // Returns: // Boolean: true if it matches, false if it doesn't. -bool IRrecv::matchSpace(uint32_t measured, uint32_t desired, - uint8_t tolerance, int16_t excess) { +bool IRrecv::matchSpace(uint32_t measured, uint32_t desired, uint8_t tolerance, + int16_t excess) { DPRINT("Matching SPACE "); - DPRINT(measured * RAWTICK); + DPRINT(measured * kRawTick); DPRINT(" vs "); DPRINT(desired); DPRINT(" - "); @@ -550,15 +661,15 @@ int16_t IRrecv::compare(uint16_t oldval, uint16_t newval) { return 1; } +#if DECODE_HASH /* Converts the raw code values into a 32-bit hash code. * Hopefully this code is unique for each button. * This isn't a "real" decoding, just an arbitrary value. */ bool IRrecv::decodeHash(decode_results *results) { - // Require at least 6 samples to prevent triggering on noise - if (results->rawlen < 6) - return false; - int32_t hash = FNV_BASIS_32; + // Require at least some samples to prevent triggering on noise + if (results->rawlen < unknown_threshold) return false; + int32_t hash = kFnvBasis32; // 'rawlen - 2' to avoid the look ahead from going out of bounds. // Should probably be -3 to avoid comparing the trailing space entry, // however it is left this way for compatibility with previously captured @@ -566,7 +677,7 @@ bool IRrecv::decodeHash(decode_results *results) { for (uint16_t i = 1; i < results->rawlen - 2; i++) { int16_t value = compare(results->rawbuf[i], results->rawbuf[i + 2]); // Add value into the hash - hash = (hash * FNV_PRIME_32) ^ value; + hash = (hash * kFnvPrime32) ^ value; } results->value = hash & 0xFFFFFFFF; results->bits = results->rawlen / 2; @@ -575,9 +686,11 @@ bool IRrecv::decodeHash(decode_results *results) { results->decode_type = UNKNOWN; return true; } +#endif // DECODE_HASH // Match & decode the typical data section of an IR message. -// The data value constructed as the Most Significant Bit first. +// The data value is stored in the least significant bits reguardless of the +// bit ordering requested. // // Args: // data_ptr: A pointer to where we are at in the capture buffer. @@ -586,46 +699,35 @@ bool IRrecv::decodeHash(decode_results *results) { // onespace: Nr. of uSeconds in an expected space signal for a '1' bit. // zeromark: Nr. of uSeconds in an expected mark signal for a '0' bit. // zerospace: Nr. of uSeconds in an expected space signal for a '0' bit. +// tolerance: Percentage error margin to allow. (Def: kTolerance) +// excess: Nr. of useconds. (Def: kMarkExcess) +// MSBfirst: Bit order to save the data in. (Def: true) // Returns: // A match_result_t structure containing the success (or not), the data value, // and how many buffer entries were used. -match_result_t IRrecv::matchData(volatile uint16_t *data_ptr, uint16_t nbits, - uint16_t onemark, uint32_t onespace, - uint16_t zeromark, uint32_t zerospace) { +match_result_t IRrecv::matchData( + volatile uint16_t *data_ptr, const uint16_t nbits, const uint16_t onemark, + const uint32_t onespace, const uint16_t zeromark, const uint32_t zerospace, + const uint8_t tolerance, const int16_t excess, const bool MSBfirst) { match_result_t result; - result.success = false; + result.success = false; // Fail by default. result.data = 0; - if (onemark == zeromark) { // Is this space encoded data format? - for (result.used = 0; - result.used < nbits * 2; - result.used += 2, data_ptr++) { - if (!matchMark(*data_ptr, onemark)) - return result; // Fail - data_ptr++; - if (matchSpace(*data_ptr, onespace)) - result.data = (result.data << 1) | 1; - else if (matchSpace(*data_ptr, zerospace)) - result.data <<= 1; - else - return result; // Fail + for (result.used = 0; result.used < nbits * 2; + result.used += 2, data_ptr += 2) { + // Is the bit a '1'? + if (matchMark(*data_ptr, onemark, tolerance, excess) && + matchSpace(*(data_ptr + 1), onespace, tolerance, excess)) { + result.data = (result.data << 1) | 1; + } else if (matchMark(*data_ptr, zeromark, tolerance, excess) && + matchSpace(*(data_ptr + 1), zerospace, tolerance, excess)) { + result.data <<= 1; // The bit is a '0'. + } else { + if (!MSBfirst) result.data = reverseBits(result.data, result.used / 2); + return result; // It's neither, so fail. } - result.success = true; - } else if (onespace == zerospace) { // Is this mark encoded data format? - for (result.used = 0; - result.used < nbits * 2; - result.used += 2, data_ptr++) { - if (matchMark(*data_ptr, onemark)) - result.data = (result.data << 1) | 1; - else if (matchMark(*data_ptr, zeromark)) - result.data <<= 1; - else - return result; // Fail - data_ptr++; - if (!matchSpace(*data_ptr, onespace)) - return result; // Fail - } - result.success = true; } + result.success = true; + if (!MSBfirst) result.data = reverseBits(result.data, nbits); return result; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h b/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h new file mode 100644 index 000000000..c0f5e781a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h @@ -0,0 +1,335 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2015 Mark Szabo +// Copyright 2015 Sebastien Warin +// Copyright 2017 David Conran + +#ifndef IRRECV_H_ +#define IRRECV_H_ + +#ifndef UNIT_TEST +#include +#endif +#include +#define __STDC_LIMIT_MACROS +#include +#include "IRremoteESP8266.h" + +// Constants +const uint16_t kHeader = 2; // Usual nr. of header entries. +const uint16_t kFooter = 2; // Usual nr. of footer (stop bits) entries. +const uint16_t kStartOffset = 1; // Usual rawbuf entry to start from. +#define MS_TO_USEC(x) (x * 1000U) // Convert milli-Seconds to micro-Seconds. +// Marks tend to be 100us too long, and spaces 100us too short +// when received due to sensor lag. +const uint16_t kMarkExcess = 50; +const uint16_t kRawBuf = 100; // Default length of raw capture buffer +const uint64_t kRepeat = UINT64_MAX; +// Default min size of reported UNKNOWN messages. +const uint16_t kUnknownThreshold = 6; + +// receiver states +const uint8_t kIdleState = 2; +const uint8_t kMarkState = 3; +const uint8_t kSpaceState = 4; +const uint8_t kStopState = 5; +const uint8_t kTolerance = 25; // default percent tolerance in measurements. +const uint16_t kRawTick = 2; // Capture tick to uSec factor. +#define RAWTICK kRawTick // Deprecated. For legacy user code support only. +// How long (ms) before we give up wait for more data? +// Don't exceed kMaxTimeoutMs without a good reason. +// That is the capture buffers maximum value size. (UINT16_MAX / kRawTick) +// Typically messages/protocols tend to repeat around the 100ms timeframe, +// thus we should timeout before that to give us some time to try to decode +// before we need to start capturing a possible new message. +// Typically 15ms suits most applications. However, some protocols demand a +// higher value. e.g. 90ms for XMP-1 and some aircon units. +const uint8_t kTimeoutMs = 15; // In MilliSeconds. +#define TIMEOUT_MS kTimeoutMs // For legacy documentation. +const uint16_t kMaxTimeoutMs = kRawTick * (UINT16_MAX / MS_TO_USEC(1)); + +// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param +const uint32_t kFnvPrime32 = 16777619UL; +const uint32_t kFnvBasis32 = 2166136261UL; + +#if DECODE_AC +// Hitachi AC is the current largest state size. +const uint16_t kStateSizeMax = kHitachiAc2StateLength; +#else +// Just define something +const uint16_t kStateSizeMax = 0; +#endif + +// Types +// information for the interrupt handler +typedef struct { + uint8_t recvpin; // pin for IR data from detector + uint8_t rcvstate; // state machine + uint16_t timer; // state timer, counts 50uS ticks. + uint16_t bufsize; // max. nr. of entries in the capture buffer. + uint16_t *rawbuf; // raw data + // uint16_t is used for rawlen as it saves 3 bytes of iram in the interrupt + // handler. Don't ask why, I don't know. It just does. + uint16_t rawlen; // counter of entries in rawbuf. + uint8_t overflow; // Buffer overflow indicator. + uint8_t timeout; // Nr. of milliSeconds before we give up. +} irparams_t; + +// results from a data match +typedef struct { + bool success; // Was the match successful? + uint64_t data; // The data found. + uint16_t used; // How many buffer positions were used. +} match_result_t; + +// Classes + +// Results returned from the decoder +class decode_results { + public: + decode_type_t decode_type; // NEC, SONY, RC5, UNKNOWN + // value, address, & command are all mutually exclusive with state. + // i.e. They MUST NOT be used at the same time as state, so we can use a union + // structure to save us a handful of valuable bytes of memory. + union { + struct { + uint64_t value; // Decoded value + uint32_t address; // Decoded device address. + uint32_t command; // Decoded command. + }; + uint8_t state[kStateSizeMax]; // Multi-byte results. + }; + uint16_t bits; // Number of bits in decoded value + volatile uint16_t *rawbuf; // Raw intervals in .5 us ticks + uint16_t rawlen; // Number of records in rawbuf. + bool overflow; + bool repeat; // Is the result a repeat code? +}; + +// main class for receiving IR +class IRrecv { + public: + explicit IRrecv(uint16_t recvpin, uint16_t bufsize = kRawBuf, + uint8_t timeout = kTimeoutMs, + bool save_buffer = false); // Constructor + ~IRrecv(); // Destructor + bool decode(decode_results *results, irparams_t *save = NULL); + void enableIRIn(); + void disableIRIn(); + void resume(); + uint16_t getBufSize(); +#if DECODE_HASH + void setUnknownThreshold(uint16_t length); +#endif + static bool match(uint32_t measured, uint32_t desired, + uint8_t tolerance = kTolerance, uint16_t delta = 0); + static bool matchMark(uint32_t measured, uint32_t desired, + uint8_t tolerance = kTolerance, + int16_t excess = kMarkExcess); + static bool matchSpace(uint32_t measured, uint32_t desired, + uint8_t tolerance = kTolerance, + int16_t excess = kMarkExcess); +#ifndef UNIT_TEST + + private: +#endif + irparams_t *irparams_save; +#if DECODE_HASH + uint16_t unknown_threshold; +#endif + // These are called by decode + void copyIrParams(volatile irparams_t *src, irparams_t *dst); + int16_t compare(uint16_t oldval, uint16_t newval); + static uint32_t ticksLow(uint32_t usecs, uint8_t tolerance = kTolerance, + uint16_t delta = 0); + static uint32_t ticksHigh(uint32_t usecs, uint8_t tolerance = kTolerance, + uint16_t delta = 0); + bool matchAtLeast(uint32_t measured, uint32_t desired, + uint8_t tolerance = kTolerance, uint16_t delta = 0); + match_result_t matchData(volatile uint16_t *data_ptr, const uint16_t nbits, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint8_t tolerance = kTolerance, + const int16_t excess = kMarkExcess, + const bool MSBfirst = true); + bool decodeHash(decode_results *results); +#if (DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || SEND_SANYO) + bool decodeNEC(decode_results *results, uint16_t nbits = kNECBits, + bool strict = true); +#endif +#if DECODE_SONY + bool decodeSony(decode_results *results, uint16_t nbits = kSonyMinBits, + bool strict = false); +#endif +#if DECODE_SANYO + // DISABLED due to poor quality. + // bool decodeSanyo(decode_results *results, + // uint16_t nbits = kSanyoSA8650BBits, + // bool strict = false); + bool decodeSanyoLC7461(decode_results *results, + uint16_t nbits = kSanyoLC7461Bits, bool strict = true); +#endif +#if DECODE_MITSUBISHI + bool decodeMitsubishi(decode_results *results, + uint16_t nbits = kMitsubishiBits, bool strict = true); +#endif +#if DECODE_MITSUBISHI2 + bool decodeMitsubishi2(decode_results *results, + uint16_t nbits = kMitsubishiBits, bool strict = true); +#endif +#if DECODE_MITSUBISHI_AC + bool decodeMitsubishiAC(decode_results *results, + uint16_t nbits = kMitsubishiACBits, + bool strict = false); +#endif +#if (DECODE_RC5 || DECODE_R6 || DECODE_LASERTAG || DECODE_MWM) + int16_t getRClevel(decode_results *results, uint16_t *offset, uint16_t *used, + uint16_t bitTime, uint8_t tolerance = kTolerance, + int16_t excess = kMarkExcess, uint16_t delta = 0, + uint8_t maxwidth = 3); +#endif +#if DECODE_RC5 + bool decodeRC5(decode_results *results, uint16_t nbits = kRC5XBits, + bool strict = true); +#endif +#if DECODE_RC6 + bool decodeRC6(decode_results *results, uint16_t nbits = kRC6Mode0Bits, + bool strict = false); +#endif +#if DECODE_RCMM + bool decodeRCMM(decode_results *results, uint16_t nbits = kRCMMBits, + bool strict = false); +#endif +#if (DECODE_PANASONIC || DECODE_DENON) + bool decodePanasonic(decode_results *results, uint16_t nbits = kPanasonicBits, + bool strict = false, + uint32_t manufacturer = kPanasonicManufacturer); +#endif +#if DECODE_LG + bool decodeLG(decode_results *results, uint16_t nbits = kLgBits, + bool strict = false); +#endif +#if DECODE_JVC + bool decodeJVC(decode_results *results, uint16_t nbits = kJvcBits, + bool strict = true); +#endif +#if DECODE_SAMSUNG + bool decodeSAMSUNG(decode_results *results, uint16_t nbits = kSamsungBits, + bool strict = true); +#endif +#if DECODE_SAMSUNG_AC + bool decodeSamsungAC(decode_results *results, uint16_t nbits = kSamsungAcBits, + bool strict = true); +#endif +#if DECODE_WHYNTER + bool decodeWhynter(decode_results *results, uint16_t nbits = kWhynterBits, + bool strict = true); +#endif +#if DECODE_COOLIX + bool decodeCOOLIX(decode_results *results, uint16_t nbits = kCoolixBits, + bool strict = true); +#endif +#if DECODE_DENON + bool decodeDenon(decode_results *results, uint16_t nbits = DENON_BITS, + bool strict = true); +#endif +#if DECODE_DISH + bool decodeDISH(decode_results *results, uint16_t nbits = kDishBits, + bool strict = true); +#endif +#if (DECODE_SHARP || DECODE_DENON) + bool decodeSharp(decode_results *results, uint16_t nbits = kSharpBits, + bool strict = true, bool expansion = true); +#endif +#if DECODE_AIWA_RC_T501 + bool decodeAiwaRCT501(decode_results *results, + uint16_t nbits = kAiwaRcT501Bits, bool strict = true); +#endif +#if DECODE_NIKAI + bool decodeNikai(decode_results *results, uint16_t nbits = kNikaiBits, + bool strict = true); +#endif +#if DECODE_MAGIQUEST + bool decodeMagiQuest(decode_results *results, uint16_t nbits = kMagiquestBits, + bool strict = true); +#endif +#if DECODE_KELVINATOR + bool decodeKelvinator(decode_results *results, + uint16_t nbits = kKelvinatorBits, bool strict = true); +#endif +#if DECODE_DAIKIN + bool decodeDaikin(decode_results *results, uint16_t nbits = kDaikinRawBits, + bool strict = true); +#endif +#if DECODE_TOSHIBA_AC + bool decodeToshibaAC(decode_results *results, + uint16_t nbytes = kToshibaACBits, bool strict = true); +#endif +#if DECODE_MIDEA + bool decodeMidea(decode_results *results, uint16_t nbits = kMideaBits, + bool strict = true); +#endif +#if DECODE_FUJITSU_AC + bool decodeFujitsuAC(decode_results *results, uint16_t nbits = kFujitsuAcBits, + bool strict = false); +#endif +#if DECODE_LASERTAG + bool decodeLasertag(decode_results *results, uint16_t nbits = kLasertagBits, + bool strict = true); +#endif +#if DECODE_CARRIER_AC + bool decodeCarrierAC(decode_results *results, uint16_t nbits = kCarrierAcBits, + bool strict = true); +#endif +#if DECODE_GREE + bool decodeGree(decode_results *results, uint16_t nbits = kGreeBits, + bool strict = true); +#endif +#if (DECODE_HAIER_AC | DECODE_HAIER_AC_YRW02) + bool decodeHaierAC(decode_results *results, uint16_t nbits = kHaierACBits, + bool strict = true); +#endif +#if DECODE_HAIER_AC_YRW02 + bool decodeHaierACYRW02(decode_results *results, + uint16_t nbits = kHaierACYRW02Bits, + bool strict = true); +#endif +#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC2) + bool decodeHitachiAC(decode_results *results, uint16_t nbits = kHitachiAcBits, + bool strict = true); +#endif +#if DECODE_HITACHI_AC1 + bool decodeHitachiAC1(decode_results *results, + uint16_t nbits = kHitachiAc1Bits, bool strict = true); +#endif +#if DECODE_GICABLE + bool decodeGICable(decode_results *results, uint16_t nbits = kGicableBits, + bool strict = true); +#endif +#if DECODE_WHIRLPOOL_AC + bool decodeWhirlpoolAC(decode_results *results, + uint16_t nbits = kWhirlpoolAcBits, bool strict = true); +#endif +#if DECODE_LUTRON + bool decodeLutron(decode_results *results, uint16_t nbits = kLutronBits, + bool strict = true); +#endif +#if DECODE_ELECTRA_AC + bool decodeElectraAC(decode_results *results, uint16_t nbits = kElectraAcBits, + bool strict = true); +#endif +#if DECODE_PANASONIC_AC + bool decodePanasonicAC(decode_results *results, + uint16_t nbits = kPanasonicAcBits, bool strict = true); +#endif +#if DECODE_PIONEER + bool decodePioneer(decode_results *results, + const uint16_t nbits = kPioneerBits, + const bool strict = true); +#endif +#if DECODE_MWM + bool decodeMWM(decode_results *results, uint16_t nbits = 24, + bool strict = true); +#endif +}; + +#endif // IRRECV_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h new file mode 100644 index 000000000..e228cbcb0 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h @@ -0,0 +1,601 @@ + /*************************************************** + * IRremote for ESP8266 + * + * Based on the IRremote library for Arduino by Ken Shirriff + * Version 0.11 August, 2009 + * Copyright 2009 Ken Shirriff + * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html + * + * Edited by Mitra to add new controller SANYO + * + * Interrupt code based on NECIRrcv by Joe Knapp + * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 + * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ + * + * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) + * LG added by Darryl Smith (based on the JVC protocol) + * Whynter A/C ARC-110WD added by Francesco Meschia + * Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit + * Denon: sendDenon, decodeDenon added by Massimiliano Pinto + (from https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp) + * Kelvinator A/C and Sherwood added by crankyoldgit + * Mitsubishi (TV) sending added by crankyoldgit + * Pronto code sending added by crankyoldgit + * Mitsubishi & Toshiba A/C added by crankyoldgit + * (derived from https://github.com/r45635/HVAC-IR-Control) + * DISH decode by marcosamarinho + * Gree Heatpump sending added by Ville Skyttä (scop) + * (derived from https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp) + * Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for sending IR code on ESP8266 + * Updated by Sebastien Warin (http://sebastien.warin.fr) for receiving IR code on ESP8266 + * + * Updated by sillyfrog for Daikin, adopted from + * (https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/) + * Fujitsu A/C code added by jonnygraham + * Trotec AC code by stufisher + * Carrier & Haier AC code by crankyoldgit + * + * GPL license, all text above must be included in any redistribution + ****************************************************/ + +#ifndef IRREMOTEESP8266_H_ +#define IRREMOTEESP8266_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef UNIT_TEST +#include +#endif + +// Library Version +#define _IRREMOTEESP8266_VERSION_ "2.5.2" +// Supported IR protocols +// Each protocol you include costs memory and, during decode, costs time +// Disable (set to false) all the protocols you do not need/want! +// The Air Conditioner protocols are the most expensive memory-wise. +// +/* +#define DECODE_HASH true // Semi-unique code for unknown messages + +#define SEND_RAW true + +#define DECODE_NEC true +#define SEND_NEC true + +#define DECODE_SHERWOOD true // Doesn't exist. Actually is DECODE_NEC +#define SEND_SHERWOOD true + +#define DECODE_RC5 true +#define SEND_RC5 true + +#define DECODE_RC6 true +#define SEND_RC6 true + +#define DECODE_RCMM true +#define SEND_RCMM true + +#define DECODE_SONY true +#define SEND_SONY true + +#define DECODE_PANASONIC true +#define SEND_PANASONIC true + +#define DECODE_JVC true +#define SEND_JVC true + +#define DECODE_SAMSUNG true +#define SEND_SAMSUNG true + +#define DECODE_SAMSUNG_AC true +#define SEND_SAMSUNG_AC true + +#define DECODE_WHYNTER true +#define SEND_WHYNTER true + +#define DECODE_AIWA_RC_T501 true +#define SEND_AIWA_RC_T501 true + +#define DECODE_LG true +#define SEND_LG true + +#define DECODE_SANYO true +#define SEND_SANYO true + +#define DECODE_MITSUBISHI true +#define SEND_MITSUBISHI true + +#define DECODE_MITSUBISHI2 true +#define SEND_MITSUBISHI2 true + +#define DECODE_DISH true +#define SEND_DISH true + +#define DECODE_SHARP true +#define SEND_SHARP true + +#define DECODE_DENON true +#define SEND_DENON true + +#define DECODE_KELVINATOR true +#define SEND_KELVINATOR true + +#define DECODE_MITSUBISHI_AC true // Beta. +#define SEND_MITSUBISHI_AC true + +#define DECODE_FUJITSU_AC true +#define SEND_FUJITSU_AC true + +#define DECODE_DAIKIN true +#define SEND_DAIKIN true + +#define DECODE_COOLIX true +#define SEND_COOLIX true + +#define DECODE_GLOBALCACHE false // Not written. +#define SEND_GLOBALCACHE true + +#define DECODE_GREE true +#define SEND_GREE true + +#define DECODE_PRONTO false // Not written. +#define SEND_PRONTO true + +#define DECODE_ARGO false // Not written. +#define SEND_ARGO true + +#define DECODE_TROTEC false // Not implemented. +#define SEND_TROTEC true + +#define DECODE_NIKAI true +#define SEND_NIKAI true + +#define DECODE_TOSHIBA_AC true +#define SEND_TOSHIBA_AC true + +#define DECODE_MAGIQUEST true +#define SEND_MAGIQUEST true + +#define DECODE_MIDEA true +#define SEND_MIDEA true + +#define DECODE_LASERTAG true +#define SEND_LASERTAG true + +#define DECODE_CARRIER_AC true +#define SEND_CARRIER_AC true + +#define DECODE_HAIER_AC true +#define SEND_HAIER_AC true + +#define DECODE_HITACHI_AC true +#define SEND_HITACHI_AC true + +#define DECODE_HITACHI_AC1 true +#define SEND_HITACHI_AC1 true + +#define DECODE_HITACHI_AC2 true +#define SEND_HITACHI_AC2 true + +#define DECODE_GICABLE true +#define SEND_GICABLE true + +#define DECODE_HAIER_AC_YRW02 true +#define SEND_HAIER_AC_YRW02 true + +#define DECODE_WHIRLPOOL_AC true +#define SEND_WHIRLPOOL_AC true + +#define DECODE_LUTRON true +#define SEND_LUTRON true + +#define DECODE_ELECTRA_AC true +#define SEND_ELECTRA_AC true + +#define DECODE_PANASONIC_AC true +#define SEND_PANASONIC_AC true + +#define DECODE_MWM true +#define SEND_MWM true + +#define DECODE_PIONEER true +#define SEND_PIONEER true +*/ + +// Tasmota supported protocols (less protocols is less code size) +#define DECODE_HASH true // Semi-unique code for unknown messages + +#define SEND_RAW true + +#define DECODE_NEC true +#define SEND_NEC true + +#define DECODE_SHERWOOD false // Doesn't exist. Actually is DECODE_NEC +#define SEND_SHERWOOD false + +#define DECODE_RC5 true +#define SEND_RC5 true + +#define DECODE_RC6 true +#define SEND_RC6 true + +#define DECODE_RCMM false +#define SEND_RCMM false + +#define DECODE_SONY true +#define SEND_SONY true + +#define DECODE_PANASONIC true +#define SEND_PANASONIC true + +#define DECODE_JVC true +#define SEND_JVC true + +#define DECODE_SAMSUNG true +#define SEND_SAMSUNG true + +#define DECODE_SAMSUNG_AC false +#define SEND_SAMSUNG_AC false + +#define DECODE_WHYNTER false +#define SEND_WHYNTER false + +#define DECODE_AIWA_RC_T501 false +#define SEND_AIWA_RC_T501 false + +#define DECODE_LG true +#define SEND_LG true + +#define DECODE_SANYO false +#define SEND_SANYO false + +#define DECODE_MITSUBISHI false +#define SEND_MITSUBISHI false + +#define DECODE_MITSUBISHI2 false +#define SEND_MITSUBISHI2 false + +#define DECODE_DISH false +#define SEND_DISH true + +#define DECODE_SHARP false +#define SEND_SHARP false + +#define DECODE_DENON false +#define SEND_DENON false + +#define DECODE_KELVINATOR false +#define SEND_KELVINATOR false + +#define DECODE_MITSUBISHI_AC false // Beta. +#define SEND_MITSUBISHI_AC true + +#define DECODE_FUJITSU_AC false +#define SEND_FUJITSU_AC true + +#define DECODE_DAIKIN false +#define SEND_DAIKIN false + +#define DECODE_COOLIX false +#define SEND_COOLIX false + +#define DECODE_GLOBALCACHE false // Not written. +#define SEND_GLOBALCACHE false + +#define DECODE_GREE false +#define SEND_GREE false + +#define DECODE_PRONTO false // Not written. +#define SEND_PRONTO false + +#define DECODE_ARGO false // Not written. +#define SEND_ARGO false + +#define DECODE_TROTEC false // Not implemented. +#define SEND_TROTEC false + +#define DECODE_NIKAI false +#define SEND_NIKAI false + +#define DECODE_TOSHIBA_AC false +#define SEND_TOSHIBA_AC false + +#define DECODE_MAGIQUEST false +#define SEND_MAGIQUEST false + +#define DECODE_MIDEA false +#define SEND_MIDEA false + +#define DECODE_LASERTAG false +#define SEND_LASERTAG false + +#define DECODE_CARRIER_AC false +#define SEND_CARRIER_AC false + +#define DECODE_HAIER_AC false +#define SEND_HAIER_AC false + +#define DECODE_HITACHI_AC false +#define SEND_HITACHI_AC false + +#define DECODE_HITACHI_AC1 false +#define SEND_HITACHI_AC1 false + +#define DECODE_HITACHI_AC2 false +#define SEND_HITACHI_AC2 false + +#define DECODE_GICABLE false +#define SEND_GICABLE false + +#define DECODE_HAIER_AC_YRW02 false +#define SEND_HAIER_AC_YRW02 false + +#define DECODE_WHIRLPOOL_AC false +#define SEND_WHIRLPOOL_AC false + +#define DECODE_LUTRON false +#define SEND_LUTRON false + +#define DECODE_ELECTRA_AC false +#define SEND_ELECTRA_AC false + +#define DECODE_PANASONIC_AC false +#define SEND_PANASONIC_AC false + +#define DECODE_MWM false +#define SEND_MWM false + +#define DECODE_PIONEER false +#define SEND_PIONEER false + +#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 || \ + DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2 || DECODE_HAIER_AC_YRW02 || \ + DECODE_WHIRLPOOL_AC || DECODE_SAMSUNG_AC || DECODE_ELECTRA_AC || \ + DECODE_PANASONIC_AC || DECODE_MWM) +#define DECODE_AC true // We need some common infrastructure for decoding A/Cs. +#else +#define DECODE_AC false // We don't need that infrastructure. +#endif + +// Use millisecond 'delay()' calls where we can to avoid tripping the WDT. +// Note: If you plan to send IR messages in the callbacks of the AsyncWebserver +// library, you need to set ALLOW_DELAY_CALLS to false. +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/430 +#define ALLOW_DELAY_CALLS true + +/* + * Always add to the end of the list and should never remove entries + * or change order. Projects may save the type number for later usage + * so numbering should always stay the same. + */ +enum decode_type_t { + UNKNOWN = -1, + UNUSED = 0, + RC5, + RC6, + NEC, + SONY, + PANASONIC, + JVC, + SAMSUNG, + WHYNTER, + AIWA_RC_T501, + LG, + SANYO, + MITSUBISHI, + DISH, + SHARP, + COOLIX, + DAIKIN, + DENON, + KELVINATOR, + SHERWOOD, + MITSUBISHI_AC, + RCMM, + SANYO_LC7461, + RC5X, + GREE, + PRONTO, // Technically not a protocol, but an encoding. + NEC_LIKE, + ARGO, + TROTEC, + NIKAI, + RAW, // Technically not a protocol, but an encoding. + GLOBALCACHE, // Technically not a protocol, but an encoding. + TOSHIBA_AC, + FUJITSU_AC, + MIDEA, + MAGIQUEST, + LASERTAG, + CARRIER_AC, + HAIER_AC, + MITSUBISHI2, + HITACHI_AC, + HITACHI_AC1, + HITACHI_AC2, + GICABLE, + HAIER_AC_YRW02, + WHIRLPOOL_AC, + SAMSUNG_AC, + LUTRON, + ELECTRA_AC, + PANASONIC_AC, + PIONEER, + LG2, + MWM, +}; + +// Message lengths & required repeat values +const uint16_t kNoRepeat = 0; +const uint16_t kSingleRepeat = 1; + +const uint16_t kAiwaRcT501Bits = 15; +const uint16_t kAiwaRcT501MinRepeats = kSingleRepeat; +const uint16_t kArgoStateLength = 12; +const uint16_t kCoolixBits = 24; +const uint16_t kCarrierAcBits = 32; +const uint16_t kCarrierAcMinRepeat = kNoRepeat; +// Daikin has a lot of static stuff that is discarded +const uint16_t kDaikinRawBits = 583; +const uint16_t kDaikinStateLength = 27; +const uint16_t kDaikinBits = kDaikinStateLength * 8; +const uint16_t kDenonBits = 15; +const uint16_t kDenonLegacyBits = 14; +const uint16_t kDishBits = 16; +const uint16_t kDishMinRepeat = 3; +const uint16_t kElectraAcStateLength = 13; +const uint16_t kElectraAcBits = kElectraAcStateLength * 8; +const uint16_t kFujitsuAcMinRepeat = kNoRepeat; +const uint16_t kFujitsuAcStateLength = 16; +const uint16_t kFujitsuAcStateLengthShort = 7; +const uint16_t kFujitsuAcBits = kFujitsuAcStateLength * 8; +const uint16_t kFujitsuAcMinBits = (kFujitsuAcStateLengthShort - 1) * 8; +const uint16_t kGicableBits = 16; +const uint16_t kGicableMinRepeat = kSingleRepeat; +const uint16_t kGreeStateLength = 8; +const uint16_t kGreeBits = kGreeStateLength * 8; +const uint16_t kHaierACStateLength = 9; +const uint16_t kHaierACBits = kHaierACStateLength * 8; +const uint16_t kHaierACYRW02StateLength = 14; +const uint16_t kHaierACYRW02Bits = kHaierACYRW02StateLength * 8; +const uint16_t kHitachiAcStateLength = 28; +const uint16_t kHitachiAcBits = kHitachiAcStateLength * 8; +const uint16_t kHitachiAc1StateLength = 13; +const uint16_t kHitachiAc1Bits = kHitachiAc1StateLength * 8; +const uint16_t kHitachiAc2StateLength = 53; +const uint16_t kHitachiAc2Bits = kHitachiAc2StateLength * 8; +const uint16_t kJvcBits = 16; +const uint16_t kKelvinatorStateLength = 16; +const uint16_t kKelvinatorBits = kKelvinatorStateLength * 8; +const uint16_t kLasertagBits = 13; +const uint16_t kLasertagMinRepeat = kNoRepeat; +const uint16_t kLgBits = 28; +const uint16_t kLg32Bits = 32; +const uint16_t kLutronBits = 35; +const uint16_t kMagiquestBits = 56; +const uint16_t kMideaBits = 48; +const uint16_t kMideaMinRepeat = kNoRepeat; +const uint16_t kMitsubishiBits = 16; +// TODO(anyone): Verify that the Mitsubishi repeat is really needed. +// Based on marcosamarinho's code. +const uint16_t kMitsubishiMinRepeat = kSingleRepeat; +const uint16_t kMitsubishiACStateLength = 18; +const uint16_t kMitsubishiACBits = kMitsubishiACStateLength * 8; +const uint16_t kMitsubishiACMinRepeat = kSingleRepeat; +const uint16_t kNikaiBits = 24; +const uint16_t kNECBits = 32; +const uint16_t kPanasonicBits = 48; +const uint32_t kPanasonicManufacturer = 0x4004; +const uint16_t kPanasonicAcStateLength = 27; +const uint16_t kPanasonicAcStateShortLength = 16; +const uint16_t kPanasonicAcBits = kPanasonicAcStateLength * 8; +const uint16_t kPanasonicAcShortBits = kPanasonicAcStateShortLength * 8; +const uint16_t kPioneerBits = 64; +const uint16_t kProntoMinLength = 6; +const uint16_t kRC5RawBits = 14; +const uint16_t kRC5Bits = kRC5RawBits - 2; +const uint16_t kRC5XBits = kRC5RawBits - 1; +const uint16_t kRC6Mode0Bits = 20; // Excludes the 'start' bit. +const uint16_t kRC6_36Bits = 36; // Excludes the 'start' bit. +const uint16_t kRCMMBits = 24; +const uint16_t kSamsungBits = 32; +const uint16_t kSamsungAcStateLength = 14; +const uint16_t kSamsungAcBits = kSamsungAcStateLength * 8; +const uint16_t kSamsungAcExtendedStateLength = 21; +const uint16_t kSamsungAcExtendedBits = kSamsungAcExtendedStateLength * 8; +const uint16_t kSanyoSA8650BBits = 12; +const uint16_t kSanyoLC7461AddressBits = 13; +const uint16_t kSanyoLC7461CommandBits = 8; +const uint16_t kSanyoLC7461Bits = (kSanyoLC7461AddressBits + + kSanyoLC7461CommandBits) * 2; +const uint8_t kSharpAddressBits = 5; +const uint8_t kSharpCommandBits = 8; +const uint16_t kSharpBits = kSharpAddressBits + kSharpCommandBits + 2; // 15 +const uint8_t kSherwoodBits = kNECBits; +const uint16_t kSherwoodMinRepeat = kSingleRepeat; +const uint16_t kSony12Bits = 12; +const uint16_t kSony15Bits = 15; +const uint16_t kSony20Bits = 20; +const uint16_t kSonyMinBits = 12; +const uint16_t kSonyMinRepeat = 2; +const uint16_t kToshibaACStateLength = 9; +const uint16_t kToshibaACBits = kToshibaACStateLength * 8; +const uint16_t kToshibaACMinRepeat = kSingleRepeat; +const uint16_t kTrotecStateLength = 9; +const uint16_t kWhirlpoolAcStateLength = 21; +const uint16_t kWhirlpoolAcBits = kWhirlpoolAcStateLength * 8; +const uint16_t kWhynterBits = 32; + +// Legacy defines. (Deprecated) +#define AIWA_RC_T501_BITS kAiwaRcT501Bits +#define ARGO_COMMAND_LENGTH kArgoStateLength +#define COOLIX_BITS kCoolixBits +#define CARRIER_AC_BITS kCarrierAcBits +#define DAIKIN_COMMAND_LENGTH kDaikinStateLength +#define DENON_BITS kDenonBits +#define DENON_48_BITS kPanasonicBits +#define DENON_LEGACY_BITS kDenonLegacyBits +#define DISH_BITS kDishBits +#define FUJITSU_AC_MIN_REPEAT kFujitsuAcMinRepeat +#define FUJITSU_AC_STATE_LENGTH kFujitsuAcStateLength +#define FUJITSU_AC_STATE_LENGTH_SHORT kFujitsuAcStateLengthShort +#define FUJITSU_AC_BITS kFujitsuAcBits +#define FUJITSU_AC_MIN_BITS kFujitsuAcMinBits +#define GICABLE_BITS kGicableBits +#define GREE_STATE_LENGTH kGreeStateLength +#define HAIER_AC_STATE_LENGTH kHaierACStateLength +#define HAIER_AC_YRW02_STATE_LENGTH kHaierACYRW02StateLength +#define HITACHI_AC_STATE_LENGTH kHitachiAcStateLength +#define HITACHI_AC_BITS kHitachiAcBits +#define HITACHI_AC1_STATE_LENGTH kHitachiAc1StateLength +#define HITACHI_AC1_BITS kHitachiAc1Bits +#define HITACHI_AC2_STATE_LENGTH kHitachiAc2StateLength +#define HITACHI_AC2_BITS kHitachiAc2Bits +#define JVC_BITS kJvcBits +#define KELVINATOR_STATE_LENGTH kKelvinatorStateLength +#define LASERTAG_BITS kLasertagBits +#define LG_BITS kLgBits +#define LG32_BITS kLg32Bits +#define MAGIQUEST_BITS kMagiquestBits +#define MIDEA_BITS kMideaBits +#define MITSUBISHI_BITS kMitsubishiBits +#define MITSUBISHI_AC_STATE_LENGTH kMitsubishiACStateLength +#define NEC_BITS kNECBits +#define NIKAI_BITS kNikaiBits +#define PANASONIC_BITS kPanasonicBits +#define RC5_BITS kRC5Bits +#define RC5X_BITS kRC5XBits +#define RC6_MODE0_BITS kRC6Mode0Bits +#define RC6_36_BITS kRC6_36Bits +#define RCMM_BITS kRCMMBits +#define SANYO_LC7461_BITS kSanyoLC7461Bits +#define SAMSUNG_BITS kSamsungBits +#define SANYO_SA8650B_BITS kSanyoSA8650BBits +#define SHARP_BITS kSharpBits +#define SHERWOOD_BITS kSherwoodBits +#define SONY_12_BITS kSony12Bits +#define SONY_15_BITS kSony15Bits +#define SONY_20_BITS kSony20Bits +#define TOSHIBA_AC_STATE_LENGTH kToshibaACStateLength +#define TROTEC_COMMAND_LENGTH kTrotecStateLength +#define WHYNTER_BITS kWhynterBits + +// Turn on Debugging information by uncommenting the following line. +// #define DEBUG 1 + +#ifdef DEBUG +#ifdef UNIT_TEST +#define DPRINT(x) do { std::cout << x; } while (0) +#define DPRINTLN(x) do { std::cout << x << std::endl; } while (0) +#endif // UNIT_TEST +#ifdef ARDUINO +#define DPRINT(x) do { Serial.print(x); } while (0) +#define DPRINTLN(x) do { Serial.println(x); } while (0) +#endif // ARDUINO +#else // DEBUG +#define DPRINT(x) +#define DPRINTLN(x) +#endif // DEBUG + +#endif // IRREMOTEESP8266_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp b/lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp new file mode 100644 index 000000000..96f95172d --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp @@ -0,0 +1,601 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2015 Mark Szabo +// Copyright 2017 David Conran + +#include "IRsend.h" +#ifndef UNIT_TEST +#include +#else +#define __STDC_LIMIT_MACROS +#include +#endif +#include +#ifdef UNIT_TEST +#include +#endif +#include "IRtimer.h" + +// Originally from https://github.com/shirriff/Arduino-IRremote/ +// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for +// sending IR code on ESP8266 + +// IRsend ---------------------------------------------------------------------- +// Create an IRsend object. +// +// Args: +// IRsendPin: Which GPIO pin to use when sending an IR command. +// inverted: *DANGER* Optional flag to invert the output. (default = false) +// e.g. LED is illuminated when GPIO is LOW rather than HIGH. +// Setting this to something other than the default could +// easily destroy your IR LED if you are overdriving it. +// Unless you *REALLY* know what you are doing, don't change this. +// use_modulation: Do we do frequency modulation during transmission? +// i.e. If not, assume a 100% duty cycle. Ignore attempts +// to change the duty cycle etc. +// Returns: +// An IRsend object. +IRsend::IRsend(uint16_t IRsendPin, bool inverted, bool use_modulation) + : IRpin(IRsendPin), periodOffset(kPeriodOffset) { + if (inverted) { + outputOn = LOW; + outputOff = HIGH; + } else { + outputOn = HIGH; + outputOff = LOW; + } + modulation = use_modulation; + if (modulation) + _dutycycle = kDutyDefault; + else + _dutycycle = kDutyMax; +} + +// Enable the pin for output. +void IRsend::begin() { +#ifndef UNIT_TEST + pinMode(IRpin, OUTPUT); +#endif + ledOff(); // Ensure the LED is in a known safe state when we start. +} + +// Turn off the IR LED. +void IRsend::ledOff() { +#ifndef UNIT_TEST + digitalWrite(IRpin, outputOff); +#endif +} + +// Turn on the IR LED. +void IRsend::ledOn() { +#ifndef UNIT_TEST + digitalWrite(IRpin, outputOn); +#endif +} + +// Calculate the period for a given frequency. (T = 1/f) +// +// Args: +// freq: Frequency in Hz. +// use_offset: Should we use the calculated offset or not? +// Returns: +// nr. of uSeconds. +uint32_t IRsend::calcUSecPeriod(uint32_t hz, bool use_offset) { + if (hz == 0) hz = 1; // Avoid Zero hz. Divide by Zero is nasty. + uint32_t period = + (1000000UL + hz / 2) / hz; // The equiv of round(1000000/hz). + // Apply the offset and ensure we don't result in a <= 0 value. + if (use_offset) + return std::max((uint32_t)1, period + periodOffset); + else + return std::max((uint32_t)1, period); +} + +// Set the output frequency modulation and duty cycle. +// +// Args: +// freq: The freq we want to modulate at. Assumes < 1000 means kHz else Hz. +// duty: Percentage duty cycle of the LED. e.g. 25 = 25% = 1/4 on, 3/4 off. +// This is ignored if modulation is disabled at object instantiation. +// +// Note: +// Integer timing functions & math mean we can't do fractions of +// microseconds timing. Thus minor changes to the freq & duty values may have +// limited effect. You've been warned. +void IRsend::enableIROut(uint32_t freq, uint8_t duty) { + // Set the duty cycle to use if we want freq. modulation. + if (modulation) { + _dutycycle = std::min(duty, kDutyMax); + } else { + _dutycycle = kDutyMax; + } + if (freq < 1000) // Were we given kHz? Supports the old call usage. + freq *= 1000; + uint32_t period = calcUSecPeriod(freq); + // Nr. of uSeconds the LED will be on per pulse. + onTimePeriod = (period * _dutycycle) / kDutyMax; + // Nr. of uSeconds the LED will be off per pulse. + offTimePeriod = period - onTimePeriod; +} + +#if ALLOW_DELAY_CALLS +// An ESP8266 RTOS watch-dog timer friendly version of delayMicroseconds(). +// Args: +// usec: Nr. of uSeconds to delay for. +void IRsend::_delayMicroseconds(uint32_t usec) { + // delayMicroseconds() is only accurate to 16383us. + // Ref: https://www.arduino.cc/en/Reference/delayMicroseconds + if (usec <= kMaxAccurateUsecDelay) { +#ifndef UNIT_TEST + delayMicroseconds(usec); +#endif + } else { +#ifndef UNIT_TEST + // Invoke a delay(), where possible, to avoid triggering the WDT. + delay(usec / 1000UL); // Delay for as many whole milliseconds as we can. + // Delay the remaining sub-millisecond. + delayMicroseconds(static_cast(usec % 1000UL)); +#endif + } +} +#else // ALLOW_DELAY_CALLS +// A version of delayMicroseconds() that handles large values and does NOT use +// the watch-dog friendly delay() calls where appropriate. +// Args: +// usec: Nr. of uSeconds to delay for. +// +// NOTE: Use this only if you know what you are doing as it may cause the WDT +// to reset the ESP8266. +void IRsend::_delayMicroseconds(uint32_t usec) { + for (; usec > kMaxAccurateUsecDelay; usec -= kMaxAccurateUsecDelay) +#ifndef UNIT_TEST + delayMicroseconds(kMaxAccurateUsecDelay); + delayMicroseconds(static_cast(usec)); +#endif // UNIT_TEST +} +#endif // ALLOW_DELAY_CALLS + +// Modulate the IR LED for the given period (usec) and at the duty cycle set. +// +// Args: +// usec: The period of time to modulate the IR LED for, in microseconds. +// Returns: +// Nr. of pulses actually sent. +// +// Note: +// The ESP8266 has no good way to do hardware PWM, so we have to do it all +// in software. There is a horrible kludge/brilliant hack to use the second +// serial TX line to do fairly accurate hardware PWM, but it is only +// available on a single specific GPIO and only available on some modules. +// e.g. It's not available on the ESP-01 module. +// Hence, for greater compatibility & choice, we don't use that method. +// Ref: +// https://www.analysir.com/blog/2017/01/29/updated-esp8266-nodemcu-backdoor-upwm-hack-for-ir-signals/ +uint16_t IRsend::mark(uint16_t usec) { + // Handle the simple case of no required frequency modulation. + if (!modulation || _dutycycle >= 100) { + ledOn(); + _delayMicroseconds(usec); + ledOff(); + return 1; + } + + // Not simple, so do it assuming frequency modulation. + uint16_t counter = 0; + IRtimer usecTimer = IRtimer(); + // Cache the time taken so far. This saves us calling time, and we can be + // assured that we can't have odd math problems. i.e. unsigned under/overflow. + uint32_t elapsed = usecTimer.elapsed(); + + while (elapsed < usec) { // Loop until we've met/exceeded our required time. + ledOn(); + // Calculate how long we should pulse on for. + // e.g. Are we to close to the end of our requested mark time (usec)? + _delayMicroseconds(std::min((uint32_t)onTimePeriod, usec - elapsed)); + ledOff(); + counter++; + if (elapsed + onTimePeriod >= usec) + return counter; // LED is now off & we've passed our allotted time. + // Wait for the lesser of the rest of the duty cycle, or the time remaining. + _delayMicroseconds( + std::min(usec - elapsed - onTimePeriod, (uint32_t)offTimePeriod)); + elapsed = usecTimer.elapsed(); // Update & recache the actual elapsed time. + } + return counter; +} + +// Turn the pin (LED) off for a given time. +// Sends an IR space for the specified number of microseconds. +// A space is no output, so the PWM output is disabled. +// +// Args: +// time: Time in microseconds (us). +void IRsend::space(uint32_t time) { + ledOff(); + if (time == 0) return; + _delayMicroseconds(time); +} + +// Calculate & set any offsets to account for execution times. +// +// Args: +// hz: The frequency to calibrate at >= 1000Hz. Default is 38000Hz. +// +// Returns: +// The calculated period offset (in uSeconds) which is now in use. e.g. -5. +// +// Status: Stable / Working. +// +// NOTE: +// This will generate an 65535us mark() IR LED signal. +// This only needs to be called once, if at all. +int8_t IRsend::calibrate(uint16_t hz) { + if (hz < 1000) // Were we given kHz? Supports the old call usage. + hz *= 1000; + periodOffset = 0; // Turn off any existing offset while we calibrate. + enableIROut(hz); + IRtimer usecTimer = IRtimer(); // Start a timer *just* before we do the call. + uint16_t pulses = mark(UINT16_MAX); // Generate a PWM of 65,535 us. (Max.) + uint32_t timeTaken = usecTimer.elapsed(); // Record the time it took. + // While it shouldn't be necessary, assume at least 1 pulse, to avoid a + // divide by 0 situation. + pulses = std::max(pulses, (uint16_t)1U); + uint32_t calcPeriod = calcUSecPeriod(hz); // e.g. @38kHz it should be 26us. + // Assuming 38kHz for the example calculations: + // In a 65535us pulse, we should have 2520.5769 pulses @ 26us periods. + // e.g. 65535.0us / 26us = 2520.5769 + // This should have caused approx 2520 loops through the main loop in mark(). + // The average over that many interations should give us a reasonable + // approximation at what offset we need to use to account for instruction + // execution times. + // + // Calculate the actual period from the actual time & the actual pulses + // generated. + double_t actualPeriod = (double_t)timeTaken / (double_t)pulses; + // Store the difference between the actual time per period vs. calculated. + periodOffset = (int8_t)((double_t)calcPeriod - actualPeriod); + return periodOffset; +} + +// Generic method for sending data that is common to most protocols. +// Will send leading or trailing 0's if the nbits is larger than the number +// of bits in data. +// +// Args: +// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. +// onespace: Nr. of usecs for the led to be fully off for a '1' bit. +// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. +// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. +// data: The data to be transmitted. +// nbits: Nr. of bits of data to be sent. +// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. +void IRsend::sendData(uint16_t onemark, uint32_t onespace, uint16_t zeromark, + uint32_t zerospace, uint64_t data, uint16_t nbits, + bool MSBfirst) { + if (nbits == 0) // If we are asked to send nothing, just return. + return; + if (MSBfirst) { // Send the MSB first. + // Send 0's until we get down to a bit size we can actually manage. + while (nbits > sizeof(data) * 8) { + mark(zeromark); + space(zerospace); + nbits--; + } + // Send the supplied data. + for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) + if (data & mask) { // Send a 1 + mark(onemark); + space(onespace); + } else { // Send a 0 + mark(zeromark); + space(zerospace); + } + } else { // Send the Least Significant Bit (LSB) first / MSB last. + for (uint16_t bit = 0; bit < nbits; bit++, data >>= 1) + if (data & 1) { // Send a 1 + mark(onemark); + space(onespace); + } else { // Send a 0 + mark(zeromark); + space(zerospace); + } + } +} + +// Generic method for sending simple protocol messages. +// Will send leading or trailing 0's if the nbits is larger than the number +// of bits in data. +// +// Args: +// headermark: Nr. of usecs for the led to be pulsed for the header mark. +// A value of 0 means no header mark. +// headerspace: Nr. of usecs for the led to be off after the header mark. +// A value of 0 means no header space. +// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. +// onespace: Nr. of usecs for the led to be fully off for a '1' bit. +// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. +// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. +// footermark: Nr. of usecs for the led to be pulsed for the footer mark. +// A value of 0 means no footer mark. +// gap: Nr. of usecs for the led to be off after the footer mark. +// This is effectively the gap between messages. +// A value of 0 means no gap space. +// data: The data to be transmitted. +// nbits: Nr. of bits of data to be sent. +// frequency: The frequency we want to modulate at. +// Assumes < 1000 means kHz otherwise it is in Hz. +// Most common value is 38000 or 38, for 38kHz. +// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. +// repeat: Nr. of extra times the message will be sent. +// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages +// dutycycle: Percentage duty cycle of the LED. +// e.g. 25 = 25% = 1/4 on, 3/4 off. +// If you are not sure, try 50 percent. +void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint64_t data, const uint16_t nbits, + const uint16_t frequency, const bool MSBfirst, + const uint16_t repeat, const uint8_t dutycycle) { + sendGeneric(headermark, headerspace, onemark, onespace, zeromark, zerospace, + footermark, gap, 0U, data, nbits, frequency, MSBfirst, repeat, + dutycycle); +} + +// Generic method for sending simple protocol messages. +// Will send leading or trailing 0's if the nbits is larger than the number +// of bits in data. +// +// Args: +// headermark: Nr. of usecs for the led to be pulsed for the header mark. +// A value of 0 means no header mark. +// headerspace: Nr. of usecs for the led to be off after the header mark. +// A value of 0 means no header space. +// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. +// onespace: Nr. of usecs for the led to be fully off for a '1' bit. +// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. +// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. +// footermark: Nr. of usecs for the led to be pulsed for the footer mark. +// A value of 0 means no footer mark. +// gap: Min. nr. of usecs for the led to be off after the footer mark. +// This is effectively the absolute minimum gap between messages. +// mesgtime: Min. nr. of usecs a single message needs to be. +// This is effectively the min. total length of a single message. +// data: The data to be transmitted. +// nbits: Nr. of bits of data to be sent. +// frequency: The frequency we want to modulate at. +// Assumes < 1000 means kHz otherwise it is in Hz. +// Most common value is 38000 or 38, for 38kHz. +// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. +// repeat: Nr. of extra times the message will be sent. +// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages +// dutycycle: Percentage duty cycle of the LED. +// e.g. 25 = 25% = 1/4 on, 3/4 off. +// If you are not sure, try 50 percent. +void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint32_t mesgtime, const uint64_t data, + const uint16_t nbits, const uint16_t frequency, + const bool MSBfirst, const uint16_t repeat, + const uint8_t dutycycle) { + // Setup + enableIROut(frequency, dutycycle); + IRtimer usecs = IRtimer(); + + // We always send a message, even for repeat=0, hence '<= repeat'. + for (uint16_t r = 0; r <= repeat; r++) { + usecs.reset(); + + // Header + if (headermark) mark(headermark); + if (headerspace) space(headerspace); + + // Data + sendData(onemark, onespace, zeromark, zerospace, data, nbits, MSBfirst); + + // Footer + if (footermark) mark(footermark); + uint32_t elapsed = usecs.elapsed(); + // Avoid potential unsigned integer underflow. e.g. when mesgtime is 0. + if (elapsed >= mesgtime) + space(gap); + else + space(std::max(gap, mesgtime - elapsed)); + } +} + +// Generic method for sending simple protocol messages. +// +// Args: +// headermark: Nr. of usecs for the led to be pulsed for the header mark. +// A value of 0 means no header mark. +// headerspace: Nr. of usecs for the led to be off after the header mark. +// A value of 0 means no header space. +// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. +// onespace: Nr. of usecs for the led to be fully off for a '1' bit. +// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. +// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. +// footermark: Nr. of usecs for the led to be pulsed for the footer mark. +// A value of 0 means no footer mark. +// gap: Nr. of usecs for the led to be off after the footer mark. +// This is effectively the gap between messages. +// A value of 0 means no gap space. +// dataptr: Pointer to the data to be transmitted. +// nbytes: Nr. of bytes of data to be sent. +// frequency: The frequency we want to modulate at. +// Assumes < 1000 means kHz otherwise it is in Hz. +// Most common value is 38000 or 38, for 38kHz. +// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. +// repeat: Nr. of extra times the message will be sent. +// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages +// dutycycle: Percentage duty cycle of the LED. +// e.g. 25 = 25% = 1/4 on, 3/4 off. +// If you are not sure, try 50 percent. +void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint8_t *dataptr, const uint16_t nbytes, + const uint16_t frequency, const bool MSBfirst, + const uint16_t repeat, const uint8_t dutycycle) { + // Setup + enableIROut(frequency, dutycycle); + // We always send a message, even for repeat=0, hence '<= repeat'. + for (uint16_t r = 0; r <= repeat; r++) { + // Header + if (headermark) mark(headermark); + if (headerspace) space(headerspace); + + // Data + for (uint16_t i = 0; i < nbytes; i++) + sendData(onemark, onespace, zeromark, zerospace, *(dataptr + i), 8, + MSBfirst); + + // Footer + if (footermark) mark(footermark); + space(gap); + } +} + +#if SEND_RAW +// Send a raw IRremote message. +// +// Args: +// buf: An array of uint16_t's that has microseconds elements. +// len: Nr. of elements in the buf[] array. +// hz: Frequency to send the message at. (kHz < 1000; Hz >= 1000) +// +// Status: STABLE / Known working. +// +// Notes: +// Even elements are Mark times (On), Odd elements are Space times (Off). +// +// Ref: +// examples/IRrecvDumpV2/IRrecvDumpV2.ino +void IRsend::sendRaw(uint16_t buf[], uint16_t len, uint16_t hz) { + // Set IR carrier frequency + enableIROut(hz); + for (uint16_t i = 0; i < len; i++) { + if (i & 1) { // Odd bit. + space(buf[i]); + } else { // Even bit. + mark(buf[i]); + } + } + ledOff(); // We potentially have ended with a mark(), so turn of the LED. +} +#endif // SEND_RAW + +#ifndef UNIT_TEST +void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) { + switch (type) { +#if SEND_NEC + case NEC: + sendNEC(data, nbits); + break; +#endif +#if SEND_SONY + case SONY: + sendSony(data, nbits); + break; +#endif +#if SEND_RC5 + case RC5: + sendRC5(data, nbits); + break; +#endif +#if SEND_RC6 + case RC6: + sendRC6(data, nbits); + break; +#endif +#if SEND_DISH + case DISH: + sendDISH(data, nbits); + break; +#endif +#if SEND_JVC + case JVC: + sendJVC(data, nbits); + break; +#endif +#if SEND_SAMSUNG + case SAMSUNG: + sendSAMSUNG(data, nbits); + break; +#endif +#if SEND_LG + case LG: + sendLG(data, nbits); + break; +#endif +#if SEND_LG + case LG2: + sendLG2(data, nbits); + break; +#endif +#if SEND_WHYNTER + case WHYNTER: + sendWhynter(data, nbits); + break; +#endif +#if SEND_COOLIX + case COOLIX: + sendCOOLIX(data, nbits); + break; +#endif +#if SEND_DENON + case DENON: + sendDenon(data, nbits); + break; +#endif +#if SEND_SHERWOOD + case SHERWOOD: + sendSherwood(data, nbits); + break; +#endif +#if SEND_RCMM + case RCMM: + sendRCMM(data, nbits); + break; +#endif +#if SEND_MITSUBISHI + case MITSUBISHI: + sendMitsubishi(data, nbits); + break; +#endif +#if SEND_MITSUBISHI2 + case MITSUBISHI2: + sendMitsubishi2(data, nbits); + break; +#endif +#if SEND_SHARP + case SHARP: + sendSharpRaw(data, nbits); + break; +#endif +#if SEND_AIWA_RC_T501 + case AIWA_RC_T501: + sendAiwaRCT501(data, nbits); + break; +#endif +#if SEND_MIDEA + case MIDEA: + sendMidea(data, nbits); + break; +#endif +#if SEND_GICABLE + case GICABLE: + sendGICable(data, nbits); + break; +#endif +#if SEND_PIONEER + case PIONEER: + sendPioneer(data, nbits); + break; +#endif + } +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRsend.h b/lib/IRremoteESP8266-2.5.2.03/src/IRsend.h new file mode 100644 index 000000000..8e2dc248e --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRsend.h @@ -0,0 +1,333 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2015 Mark Szabo +// Copyright 2017 David Conran +#ifndef IRSEND_H_ +#define IRSEND_H_ + +#define __STDC_LIMIT_MACROS +#include +#include "IRremoteESP8266.h" + +// Originally from https://github.com/shirriff/Arduino-IRremote/ +// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for +// sending IR code on ESP8266 + +#if TEST || UNIT_TEST +#define VIRTUAL virtual +#else +#define VIRTUAL +#endif + +// Constants +// Offset (in microseconds) to use in Period time calculations to account for +// code excution time in producing the software PWM signal. +// Value was calculated on Wemos D1 mini using v2.4.1 with v2.4.0 ESP core +const int8_t kPeriodOffset = -5; +const uint8_t kDutyDefault = 50; // Percentage +const uint8_t kDutyMax = 100; // Percentage +// delayMicroseconds() is only accurate to 16383us. +// Ref: https://www.arduino.cc/en/Reference/delayMicroseconds +const uint16_t kMaxAccurateUsecDelay = 16383; + +// Classes +class IRsend { + public: + explicit IRsend(uint16_t IRsendPin, bool inverted = false, + bool use_modulation = true); + void begin(); + void enableIROut(uint32_t freq, uint8_t duty = kDutyDefault); + VIRTUAL void _delayMicroseconds(uint32_t usec); + VIRTUAL uint16_t mark(uint16_t usec); + VIRTUAL void space(uint32_t usec); + int8_t calibrate(uint16_t hz = 38000U); + void sendRaw(uint16_t buf[], uint16_t len, uint16_t hz); + void sendData(uint16_t onemark, uint32_t onespace, uint16_t zeromark, + uint32_t zerospace, uint64_t data, uint16_t nbits, + bool MSBfirst = true); + void sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint64_t data, const uint16_t nbits, + const uint16_t frequency, const bool MSBfirst, + const uint16_t repeat, const uint8_t dutycycle); + void sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint32_t mesgtime, const uint64_t data, + const uint16_t nbits, const uint16_t frequency, + const bool MSBfirst, const uint16_t repeat, + const uint8_t dutycycle); + void sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint8_t *dataptr, const uint16_t nbytes, + const uint16_t frequency, const bool MSBfirst, + const uint16_t repeat, const uint8_t dutycycle); + void send(uint16_t type, uint64_t data, uint16_t nbits); +#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO) + void sendNEC(uint64_t data, uint16_t nbits = kNECBits, + uint16_t repeat = kNoRepeat); + uint32_t encodeNEC(uint16_t address, uint16_t command); +#endif +#if SEND_SONY + // sendSony() should typically be called with repeat=2 as Sony devices + // expect the code to be sent at least 3 times. (code + 2 repeats = 3 codes) + // Legacy use of this procedure was to only send a single code so call it with + // repeat=0 for backward compatibility. As of v2.0 it defaults to sending + // a Sony command that will be accepted be a device. + void sendSony(uint64_t data, uint16_t nbits = kSony20Bits, + uint16_t repeat = kSonyMinRepeat); + uint32_t encodeSony(uint16_t nbits, uint16_t command, uint16_t address, + uint16_t extended = 0); +#endif +#if SEND_SHERWOOD + void sendSherwood(uint64_t data, uint16_t nbits = kSherwoodBits, + uint16_t repeat = kSherwoodMinRepeat); +#endif +#if SEND_SAMSUNG + void sendSAMSUNG(uint64_t data, uint16_t nbits = kSamsungBits, + uint16_t repeat = kNoRepeat); + uint32_t encodeSAMSUNG(uint8_t customer, uint8_t command); +#endif +#if SEND_SAMSUNG_AC + void sendSamsungAC(unsigned char data[], + uint16_t nbytes = kSamsungAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_LG + void sendLG(uint64_t data, uint16_t nbits = kLgBits, + uint16_t repeat = kNoRepeat); + void sendLG2(uint64_t data, uint16_t nbits = kLgBits, + uint16_t repeat = kNoRepeat); + uint32_t encodeLG(uint16_t address, uint16_t command); +#endif +#if (SEND_SHARP || SEND_DENON) + uint32_t encodeSharp(uint16_t address, uint16_t command, + uint16_t expansion = 1, uint16_t check = 0, + bool MSBfirst = false); + void sendSharp(uint16_t address, uint16_t command, + uint16_t nbits = kSharpBits, uint16_t repeat = kNoRepeat); + void sendSharpRaw(uint64_t data, uint16_t nbits = kSharpBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_JVC + void sendJVC(uint64_t data, uint16_t nbits = kJvcBits, + uint16_t repeat = kNoRepeat); + uint16_t encodeJVC(uint8_t address, uint8_t command); +#endif +#if SEND_DENON + void sendDenon(uint64_t data, uint16_t nbits = DENON_BITS, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_SANYO + uint64_t encodeSanyoLC7461(uint16_t address, uint8_t command); + void sendSanyoLC7461(uint64_t data, uint16_t nbits = kSanyoLC7461Bits, + uint16_t repeat = kNoRepeat); +#endif +#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) + // Legacy use of this procedure was only to send a single code + // so use repeat=0 for backward compatibility. + void sendDISH(uint64_t data, uint16_t nbits = kDishBits, + uint16_t repeat = kDishMinRepeat); +#endif +#if (SEND_PANASONIC || SEND_DENON) + void sendPanasonic64(uint64_t data, uint16_t nbits = kPanasonicBits, + uint16_t repeat = kNoRepeat); + void sendPanasonic(uint16_t address, uint32_t data, + uint16_t nbits = kPanasonicBits, + uint16_t repeat = kNoRepeat); + uint64_t encodePanasonic(uint16_t manufacturer, uint8_t device, + uint8_t subdevice, uint8_t function); +#endif +#if SEND_RC5 + void sendRC5(uint64_t data, uint16_t nbits = kRC5XBits, + uint16_t repeat = kNoRepeat); + uint16_t encodeRC5(uint8_t address, uint8_t command, + bool key_released = false); + uint16_t encodeRC5X(uint8_t address, uint8_t command, + bool key_released = false); + uint64_t toggleRC5(uint64_t data); +#endif +#if SEND_RC6 + void sendRC6(uint64_t data, uint16_t nbits = kRC6Mode0Bits, + uint16_t repeat = kNoRepeat); + uint64_t encodeRC6(uint32_t address, uint8_t command, + uint16_t mode = kRC6Mode0Bits); + uint64_t toggleRC6(uint64_t data, uint16_t nbits = kRC6Mode0Bits); +#endif +#if SEND_RCMM + void sendRCMM(uint64_t data, uint16_t nbits = kRCMMBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_COOLIX + void sendCOOLIX(uint64_t data, uint16_t nbits = kCoolixBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_WHYNTER + void sendWhynter(uint64_t data, uint16_t nbits = kWhynterBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_MITSUBISHI + void sendMitsubishi(uint64_t data, uint16_t nbits = kMitsubishiBits, + uint16_t repeat = kMitsubishiMinRepeat); +#endif +#if SEND_MITSUBISHI2 + void sendMitsubishi2(uint64_t data, uint16_t nbits = kMitsubishiBits, + uint16_t repeat = kMitsubishiMinRepeat); +#endif +#if SEND_MITSUBISHI_AC + void sendMitsubishiAC(unsigned char data[], + uint16_t nbytes = kMitsubishiACStateLength, + uint16_t repeat = kMitsubishiACMinRepeat); +#endif +#if SEND_FUJITSU_AC + void sendFujitsuAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat = kFujitsuAcMinRepeat); +#endif +#if SEND_GLOBALCACHE + void sendGC(uint16_t buf[], uint16_t len); +#endif +#if SEND_KELVINATOR + void sendKelvinator(unsigned char data[], + uint16_t nbytes = kKelvinatorStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_DAIKIN + void sendDaikin(unsigned char data[], uint16_t nbytes = kDaikinStateLength, + uint16_t repeat = kNoRepeat); + void sendDaikinGapHeader(); +#endif +#if SEND_AIWA_RC_T501 + void sendAiwaRCT501(uint64_t data, uint16_t nbits = kAiwaRcT501Bits, + uint16_t repeat = kAiwaRcT501MinRepeats); +#endif +#if SEND_GREE + void sendGree(uint64_t data, uint16_t nbits = kGreeBits, + uint16_t repeat = kNoRepeat); + void sendGree(uint8_t data[], uint16_t nbytes = kGreeStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_PRONTO + void sendPronto(uint16_t data[], uint16_t len, uint16_t repeat = kNoRepeat); +#endif +#if SEND_ARGO + void sendArgo(unsigned char data[], uint16_t nbytes = kArgoStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_TROTEC + void sendTrotec(unsigned char data[], uint16_t nbytes = kTrotecStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_NIKAI + void sendNikai(uint64_t data, uint16_t nbits = kNikaiBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_TOSHIBA_AC + void sendToshibaAC(unsigned char data[], + uint16_t nbytes = kToshibaACStateLength, + uint16_t repeat = kToshibaACMinRepeat); +#endif +#if SEND_MIDEA + void sendMidea(uint64_t data, uint16_t nbits = kMideaBits, + uint16_t repeat = kMideaMinRepeat); +#endif +#if SEND_MAGIQUEST + void sendMagiQuest(uint64_t data, uint16_t nbits = kMagiquestBits, + uint16_t repeat = kNoRepeat); + uint64_t encodeMagiQuest(uint32_t wand_id, uint16_t magnitude); +#endif +#if SEND_LASERTAG + void sendLasertag(uint64_t data, uint16_t nbits = kLasertagBits, + uint16_t repeat = kLasertagMinRepeat); +#endif +#if SEND_CARRIER_AC + void sendCarrierAC(uint64_t data, uint16_t nbits = kCarrierAcBits, + uint16_t repeat = kCarrierAcMinRepeat); +#endif +#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02) + void sendHaierAC(unsigned char data[], uint16_t nbytes = kHaierACStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_HAIER_AC_YRW02 + void sendHaierACYRW02(unsigned char data[], + uint16_t nbytes = kHaierACYRW02StateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_HITACHI_AC + void sendHitachiAC(unsigned char data[], + uint16_t nbytes = kHitachiAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_HITACHI_AC1 + void sendHitachiAC1(unsigned char data[], + uint16_t nbytes = kHitachiAc1StateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_HITACHI_AC2 + void sendHitachiAC2(unsigned char data[], + uint16_t nbytes = kHitachiAc2StateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_GICABLE + void sendGICable(uint64_t data, uint16_t nbits = kGicableBits, + uint16_t repeat = kGicableMinRepeat); +#endif +#if SEND_WHIRLPOOL_AC + void sendWhirlpoolAC(unsigned char data[], + uint16_t nbytes = kWhirlpoolAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_LUTRON + void sendLutron(uint64_t data, uint16_t nbits = kLutronBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_ELECTRA_AC + void sendElectraAC(unsigned char data[], + uint16_t nbytes = kElectraAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_PANASONIC_AC + void sendPanasonicAC(unsigned char data[], + uint16_t nbytes = kPanasonicAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_PIONEER + void sendPioneer(const uint64_t data, const uint16_t nbits = kPioneerBits, + const uint16_t repeat = kNoRepeat); + uint64_t encodePioneer(uint16_t address, uint16_t command); +#endif +#if SEND_MWM + void sendMWM(unsigned char data[], uint16_t nbytes, + uint16_t repeat = kNoRepeat); +#endif + + protected: +#ifdef UNIT_TEST +#ifndef HIGH +#define HIGH 0x1 +#endif +#ifndef LOW +#define LOW 0x0 +#endif +#endif // UNIT_TEST + uint8_t outputOn; + uint8_t outputOff; + VIRTUAL void ledOff(); + VIRTUAL void ledOn(); + + private: + uint16_t onTimePeriod; + uint16_t offTimePeriod; + uint16_t IRpin; + int8_t periodOffset; + uint8_t _dutycycle; + bool modulation; + uint32_t calcUSecPeriod(uint32_t hz, bool use_offset = true); +}; + +#endif // IRSEND_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.cpp b/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.cpp similarity index 52% rename from lib/IRremoteESP8266-2.2.1.02/src/IRtimer.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/IRtimer.cpp index cc5cdfaff..029637cbb 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.cpp @@ -5,18 +5,21 @@ #include #endif +#ifdef UNIT_TEST +// Used to help simulate elapsed time in unit tests. +extern uint32_t _IRtimer_unittest_now; +#endif // UNIT_TEST + // This class performs a simple time in useconds since instantiated. // Handles when the system timer wraps around (once). -IRtimer::IRtimer() { - reset(); -} +IRtimer::IRtimer() { reset(); } void IRtimer::reset() { #ifndef UNIT_TEST start = micros(); #else - start = 0; + start = _IRtimer_unittest_now; #endif } @@ -24,10 +27,15 @@ uint32_t IRtimer::elapsed() { #ifndef UNIT_TEST uint32_t now = micros(); #else - uint32_t now = 0; + uint32_t now = _IRtimer_unittest_now; #endif - if (start <= now) // Check if the system timer has wrapped. + if (start <= now) // Check if the system timer has wrapped. return now - start; // No wrap. else return UINT32_MAX - start + now; // Has wrapped. } + +// Only used in unit testing. +#ifdef UNIT_TEST +void IRtimer::add(uint32_t usecs) { _IRtimer_unittest_now += usecs; } +#endif // UNIT_TEST diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h b/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.h similarity index 78% rename from lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h rename to lib/IRremoteESP8266-2.5.2.03/src/IRtimer.h index 6cf7f7dc8..baca1cf74 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.h @@ -12,6 +12,9 @@ class IRtimer { IRtimer(); void reset(); uint32_t elapsed(); +#ifdef UNIT_TEST + static void add(uint32_t usecs); +#endif // UNIT_TEST private: uint32_t start; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp b/lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp new file mode 100644 index 000000000..7864625a5 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp @@ -0,0 +1,470 @@ +// Copyright 2017 David Conran + +#include "IRutils.h" +#ifndef UNIT_TEST +#include +#endif + +#define __STDC_LIMIT_MACROS +#include +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" + +// Reverse the order of the requested least significant nr. of bits. +// Args: +// input: Bit pattern/integer to reverse. +// nbits: Nr. of bits to reverse. +// Returns: +// The reversed bit pattern. +uint64_t reverseBits(uint64_t input, uint16_t nbits) { + if (nbits <= 1) return input; // Reversing <= 1 bits makes no change at all. + // Cap the nr. of bits to rotate to the max nr. of bits in the input. + nbits = std::min(nbits, (uint16_t)(sizeof(input) * 8)); + uint64_t output = 0; + for (uint16_t i = 0; i < nbits; i++) { + output <<= 1; + output |= (input & 1); + input >>= 1; + } + // Merge any remaining unreversed bits back to the top of the reversed bits. + return (input << nbits) | output; +} + +// Convert a uint64_t (unsigned long long) to a string. +// Arduino String/toInt/Serial.print() can't handle printing 64 bit values. +// +// Args: +// input: The value to print +// base: The output base. +// Returns: +// A string representation of the integer. +// Note: Based on Arduino's Print::printNumber() +#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. +String uint64ToString(uint64_t input, uint8_t base) { + String result = ""; +#else +std::string uint64ToString(uint64_t input, uint8_t base) { + std::string result = ""; +#endif + // prevent issues if called with base <= 1 + if (base < 2) base = 10; + // Check we have a base that we can actually print. + // i.e. [0-9A-Z] == 36 + if (base > 36) base = 10; + + do { + char c = input % base; + input /= base; + + if (c < 10) + c += '0'; + else + c += 'A' - 10; + result = c + result; + } while (input); + return result; +} + +#ifdef ARDUINO +// Print a uint64_t/unsigned long long to the Serial port +// Serial.print() can't handle printing long longs. (uint64_t) +// +// Args: +// input: The value to print +// base: The output base. +void serialPrintUint64(uint64_t input, uint8_t base) { + Serial.print(uint64ToString(input, base)); +} +#endif + +// Convert a protocol type (enum etc) to a human readable string. +// Args: +// protocol: Nr. (enum) of the protocol. +// isRepeat: A flag indicating if it is a repeat message of the protocol. +// Returns: +// A string containing the protocol name. +#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. +String typeToString(const decode_type_t protocol, const bool isRepeat) { + String result = ""; +#else +std::string typeToString(const decode_type_t protocol, const bool isRepeat) { + std::string result = ""; +#endif + switch (protocol) { + default: + case UNKNOWN: + result = "UNKNOWN"; + break; + case UNUSED: + result = "UNUSED"; + break; + case AIWA_RC_T501: + result = "AIWA_RC_T501"; + break; + case ARGO: + result = "ARGO"; + break; + case CARRIER_AC: + result = "CARRIER_AC"; + break; + case COOLIX: + result = "COOLIX"; + break; + case DAIKIN: + result = "DAIKIN"; + break; + case DENON: + result = "DENON"; + break; + case DISH: + result = "DISH"; + break; + case ELECTRA_AC: + result = "ELECTRA_AC"; + break; + case FUJITSU_AC: + result = "FUJITSU_AC"; + break; + case GICABLE: + result = "GICABLE"; + break; + case GLOBALCACHE: + result = "GLOBALCACHE"; + break; + case GREE: + result = "GREE"; + break; + case HAIER_AC: + result = "HAIER_AC"; + break; + case HAIER_AC_YRW02: + result = "HAIER_AC_YRW02"; + break; + case HITACHI_AC: + result = "HITACHI_AC"; + break; + case HITACHI_AC1: + result = "HITACHI_AC1"; + break; + case HITACHI_AC2: + result = "HITACHI_AC2"; + break; + case JVC: + result = "JVC"; + break; + case KELVINATOR: + result = "KELVINATOR"; + break; + case LG: + result = "LG"; + break; + case LG2: + result = "LG2"; + break; + case LASERTAG: + result = "LASERTAG"; + break; + case LUTRON: + result = "LUTRON"; + break; + case MAGIQUEST: + result = "MAGIQUEST"; + break; + case MIDEA: + result = "MIDEA"; + break; + case MITSUBISHI: + result = "MITSUBISHI"; + break; + case MITSUBISHI2: + result = "MITSUBISHI2"; + break; + case MITSUBISHI_AC: + result = "MITSUBISHI_AC"; + break; + case MWM: + result = "MWM"; + break; + case NEC: + result = "NEC"; + break; + case NEC_LIKE: + result = "NEC (non-strict)"; + break; + case NIKAI: + result = "NIKAI"; + break; + case PANASONIC: + result = "PANASONIC"; + break; + case PANASONIC_AC: + result = "PANASONIC_AC"; + break; + case PIONEER: + result = "PIONEER"; + break; + case PRONTO: + result = "PRONTO"; + break; + case RAW: + result = "RAW"; + break; + case RC5: + result = "RC5"; + break; + case RC5X: + result = "RC5X"; + break; + case RC6: + result = "RC6"; + break; + case RCMM: + result = "RCMM"; + break; + case SAMSUNG: + result = "SAMSUNG"; + break; + case SAMSUNG_AC: + result = "SAMSUNG_AC"; + break; + case SANYO: + result = "SANYO"; + break; + case SANYO_LC7461: + result = "SANYO_LC7461"; + break; + case SHARP: + result = "SHARP"; + break; + case SHERWOOD: + result = "SHERWOOD"; + break; + case SONY: + result = "SONY"; + break; + case TOSHIBA_AC: + result = "TOSHIBA_AC"; + break; + case TROTEC: + result = "TROTEC"; + break; + case WHIRLPOOL_AC: + result = "WHIRLPOOL_AC"; + break; + case WHYNTER: + result = "WHYNTER"; + break; + } + if (isRepeat) result += " (Repeat)"; + return result; +} + +// Does the given protocol use a complex state as part of the decode? +bool hasACState(const decode_type_t protocol) { + switch (protocol) { + case DAIKIN: + case ELECTRA_AC: + case FUJITSU_AC: + case GREE: + case HAIER_AC: + case HAIER_AC_YRW02: + case HITACHI_AC: + case HITACHI_AC1: + case HITACHI_AC2: + case KELVINATOR: + case MITSUBISHI_AC: + case MWM: + case PANASONIC_AC: + case SAMSUNG_AC: + case TOSHIBA_AC: + case WHIRLPOOL_AC: + return true; + default: + return false; + } +} + +// Return the corrected length of a 'raw' format array structure +// after over-large values are converted into multiple entries. +// Args: +// results: A ptr to a decode result. +// Returns: +// A uint16_t containing the length. +uint16_t getCorrectedRawLength(const decode_results *results) { + uint16_t extended_length = results->rawlen - 1; + for (uint16_t i = 0; i < results->rawlen - 1; i++) { + uint32_t usecs = results->rawbuf[i] * kRawTick; + // Add two extra entries for multiple larger than UINT16_MAX it is. + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + return extended_length; +} + +// Return a string containing the key values of a decode_results structure +// in a C/C++ code style format. +#ifdef ARDUINO +String resultToSourceCode(const decode_results *results) { + String output = ""; +#else +std::string resultToSourceCode(const decode_results *results) { + std::string output = ""; +#endif + // Start declaration + output += "uint16_t "; // variable type + output += "rawData["; // array name + output += uint64ToString(getCorrectedRawLength(results), 10); + // array size + output += "] = {"; // Start declaration + + // Dump data + for (uint16_t i = 1; i < results->rawlen; i++) { + uint32_t usecs; + for (usecs = results->rawbuf[i] * kRawTick; usecs > UINT16_MAX; + usecs -= UINT16_MAX) { + output += uint64ToString(UINT16_MAX); + if (i % 2) + output += ", 0, "; + else + output += ", 0, "; + } + output += uint64ToString(usecs, 10); + if (i < results->rawlen - 1) + output += ", "; // ',' not needed on the last one + if (i % 2 == 0) output += " "; // Extra if it was even. + } + + // End declaration + output += "};"; + + // Comment + output += " // " + typeToString(results->decode_type, results->repeat); + // Only display the value if the decode type doesn't have an A/C state. + if (!hasACState(results->decode_type)) + output += " " + uint64ToString(results->value, 16); + output += "\n"; + + // Now dump "known" codes + if (results->decode_type != UNKNOWN) { + if (hasACState(results->decode_type)) { +#if DECODE_AC + uint16_t nbytes = results->bits / 8; + output += "uint8_t state[" + uint64ToString(nbytes) + "] = {"; + for (uint16_t i = 0; i < nbytes; i++) { + output += "0x"; + if (results->state[i] < 0x10) output += "0"; + output += uint64ToString(results->state[i], 16); + if (i < nbytes - 1) output += ", "; + } + output += "};\n"; +#endif // DECODE_AC + } else { + // Simple protocols + // Some protocols have an address &/or command. + // NOTE: It will ignore the atypical case when a message has been + // decoded but the address & the command are both 0. + if (results->address > 0 || results->command > 0) { + output += "uint32_t address = 0x" + + uint64ToString(results->address, 16) + ";\n"; + output += "uint32_t command = 0x" + + uint64ToString(results->command, 16) + ";\n"; + } + // Most protocols have data + output += + "uint64_t data = 0x" + uint64ToString(results->value, 16) + ";\n"; + } + } + return output; +} + +// Dump out the decode_results structure. +// +#ifdef ARDUINO +String resultToTimingInfo(const decode_results *results) { + String output = ""; + String value = ""; +#else +std::string resultToTimingInfo(const decode_results *results) { + std::string output = ""; + std::string value = ""; +#endif + output += "Raw Timing[" + uint64ToString(results->rawlen - 1, 10) + "]:\n"; + + for (uint16_t i = 1; i < results->rawlen; i++) { + if (i % 2 == 0) + output += "-"; // even + else + output += " +"; // odd + value = uint64ToString(results->rawbuf[i] * kRawTick); + // Space pad the value till it is at least 6 chars long. + while (value.length() < 6) value = " " + value; + output += value; + if (i < results->rawlen - 1) output += ", "; // ',' not needed for last one + if (!(i % 8)) output += "\n"; // Newline every 8 entries. + } + output += "\n"; + return output; +} + +// Convert the decode_results structure's value/state to simple hexadecimal. +// +#ifdef ARDUINO +String resultToHexidecimal(const decode_results *result) { + String output = ""; +#else +std::string resultToHexidecimal(const decode_results *result) { + std::string output = ""; +#endif + if (hasACState(result->decode_type)) { +#if DECODE_AC + for (uint16_t i = 0; result->bits > i * 8; i++) { + if (result->state[i] < 0x10) output += "0"; // Zero pad + output += uint64ToString(result->state[i], 16); + } +#endif // DECODE_AC + } else { + output += uint64ToString(result->value, 16); + } + return output; +} + +// Dump out the decode_results structure. +// +#ifdef ARDUINO +String resultToHumanReadableBasic(const decode_results *results) { + String output = ""; +#else +std::string resultToHumanReadableBasic(const decode_results *results) { + std::string output = ""; +#endif + // Show Encoding standard + output += + "Encoding : " + typeToString(results->decode_type, results->repeat) + + "\n"; + + // Show Code & length + output += "Code : "; + output += resultToHexidecimal(results); + output += " (" + uint64ToString(results->bits) + " bits)\n"; + return output; +} + +uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init) { + uint8_t checksum = init; + uint8_t *ptr; + for (ptr = start; ptr - start < length; ptr++) checksum += *ptr; + return checksum; +} + +uint64_t invertBits(const uint64_t data, const uint16_t nbits) { + // No change if we are asked to invert no bits. + if (nbits == 0) return data; + uint64_t result = ~data; + // If we are asked to invert all the bits or more than we have, it's simple. + if (nbits >= sizeof(data) * 8) return result; + // Mask off any unwanted bits and return the result. + return (result & ((1ULL << nbits) - 1)); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRutils.h b/lib/IRremoteESP8266-2.5.2.03/src/IRutils.h new file mode 100644 index 000000000..c17375d98 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRutils.h @@ -0,0 +1,41 @@ +#ifndef IRUTILS_H_ +#define IRUTILS_H_ + +// Copyright 2017 David Conran + +#ifndef UNIT_TEST +#include +#endif +#define __STDC_LIMIT_MACROS +#include +#ifndef ARDUINO +#include +#endif +#include "IRremoteESP8266.h" +#include "IRrecv.h" + +uint64_t reverseBits(uint64_t input, uint16_t nbits); +#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. +String uint64ToString(uint64_t input, uint8_t base = 10); +String typeToString(const decode_type_t protocol, + const bool isRepeat = false); +void serialPrintUint64(uint64_t input, uint8_t base = 10); +String resultToSourceCode(const decode_results *results); +String resultToTimingInfo(const decode_results *results); +String resultToHumanReadableBasic(const decode_results *results); +String resultToHexidecimal(const decode_results *result); +#else +std::string uint64ToString(uint64_t input, uint8_t base = 10); +std::string typeToString(const decode_type_t protocol, + const bool isRepeat = false); +std::string resultToSourceCode(const decode_results *results); +std::string resultToTimingInfo(const decode_results *results); +std::string resultToHumanReadableBasic(const decode_results *results); +std::string resultToHexidecimal(const decode_results *result); +#endif +bool hasACState(const decode_type_t protocol); +uint16_t getCorrectedRawLength(const decode_results *results); +uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init = 0); +uint64_t invertBits(const uint64_t data, const uint16_t nbits); + +#endif // IRUTILS_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Aiwa.cpp similarity index 76% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Aiwa.cpp index 99a97e187..617711a99 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Aiwa.cpp @@ -2,7 +2,6 @@ #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" // AAA IIIII W W AAA // A A I W W A A @@ -14,20 +13,20 @@ // Added by David Conran. (Inspired by IRremoteESP8266's implementation: // https://github.com/z3t0/Arduino-IRremote) -#define AIWA_RC_T501_PRE_BITS 26U -#define AIWA_RC_T501_POST_BITS 1U +const uint16_t kAiwaRcT501PreBits = 26; +const uint16_t kAiwaRcT501PostBits = 1; // NOTE: These are the compliment (inverted) of lirc values as // lirc uses a '0' for a mark, and a '1' for a space. -#define AIWA_RC_T501_PRE_DATA 0x1D8113FULL // 26-bits -#define AIWA_RC_T501_POST_DATA 1ULL +const uint64_t kAiwaRcT501PreData = 0x1D8113FULL; // 26-bits +const uint64_t kAiwaRcT501PostData = 1ULL; #if SEND_AIWA_RC_T501 -// Send a Aiwa RC T501 formatted message. +// Send an Aiwa RC T501 formatted message. // // Args: // data: The message to be sent. // nbits: The number of bits of the message to be sent. -// Typically AIWA_RC_T501_BITS. Max is 37 = (64 - 27) +// Typically kAiwaRcT501Bits. Max is 37 = (64 - 27) // repeat: The number of times the command is to be repeated. // // Status: BETA / Should work. @@ -38,10 +37,9 @@ void IRsend::sendAiwaRCT501(uint64_t data, uint16_t nbits, uint16_t repeat) { // Appears to be an extended NEC1 protocol. i.e. 42 bits instead of 32 bits. // So use sendNEC instead, however the twist is it has a fixed 26 bit // prefix, and a fixed postfix bit. - uint64_t new_data = ( - (AIWA_RC_T501_PRE_DATA << (nbits + AIWA_RC_T501_POST_BITS)) | - (data << AIWA_RC_T501_POST_BITS) | AIWA_RC_T501_POST_DATA); - nbits += AIWA_RC_T501_PRE_BITS + AIWA_RC_T501_POST_BITS; + uint64_t new_data = ((kAiwaRcT501PreData << (nbits + kAiwaRcT501PostBits)) | + (data << kAiwaRcT501PostBits) | kAiwaRcT501PostData); + nbits += kAiwaRcT501PreBits + kAiwaRcT501PostBits; if (nbits > sizeof(new_data) * 8) return; // We are overflowing. Abort, and don't send. sendNEC(new_data, nbits, repeat); @@ -53,7 +51,7 @@ void IRsend::sendAiwaRCT501(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: The number of data bits to expect. Typically AIWA_RC_T501_BITS. +// nbits: The number of data bits to expect. Typically kAiwaRcT501Bits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. @@ -72,12 +70,11 @@ void IRsend::sendAiwaRCT501(uint64_t data, uint16_t nbits, uint16_t repeat) { bool IRrecv::decodeAiwaRCT501(decode_results *results, uint16_t nbits, bool strict) { // Compliance - if (strict && nbits != AIWA_RC_T501_BITS) + if (strict && nbits != kAiwaRcT501Bits) return false; // Doesn't match our protocol defn. // Add on the pre & post bits to our requested bit length. - uint16_t expected_nbits = nbits + AIWA_RC_T501_PRE_BITS + - AIWA_RC_T501_POST_BITS; + uint16_t expected_nbits = nbits + kAiwaRcT501PreBits + kAiwaRcT501PostBits; uint64_t new_data; if (expected_nbits > sizeof(new_data) * 8) return false; // We can't possibly match something that big. @@ -89,24 +86,23 @@ bool IRrecv::decodeAiwaRCT501(decode_results *results, uint16_t nbits, new_data = results->value; if (actual_bits < expected_nbits) return false; // The data we caught was undersized. Throw it back. - if ((new_data & 0x1ULL) != AIWA_RC_T501_POST_DATA) + if ((new_data & 0x1ULL) != kAiwaRcT501PostData) return false; // The post data doesn't match, so it can't be this protocol. // Trim off the post data bit. - new_data >>= AIWA_RC_T501_POST_BITS; - actual_bits -= AIWA_RC_T501_POST_BITS; + new_data >>= kAiwaRcT501PostBits; + actual_bits -= kAiwaRcT501PostBits; // Extract out our likely new value and put it back in the results. - actual_bits -= AIWA_RC_T501_PRE_BITS; + actual_bits -= kAiwaRcT501PreBits; results->value = new_data & ((1ULL << actual_bits) - 1); // Check the prefix data matches. new_data >>= actual_bits; // Trim off the new data to expose the prefix. - if (new_data != AIWA_RC_T501_PRE_DATA) // Check the prefix. + if (new_data != kAiwaRcT501PreData) // Check the prefix. return false; // Compliance - if (strict && results->bits != expected_nbits) - return false; + if (strict && results->bits != expected_nbits) return false; // Success results->decode_type = AIWA_RC_T501; diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.cpp similarity index 69% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.cpp index 0129c7231..8a3e69f72 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.cpp @@ -11,53 +11,40 @@ Copyright 2017 Schmolders // Constants // using SPACE modulation. MARK is always const 400u -#define ARGO_PREAMBLE_1 6400U // Mark -#define ARGO_PREAMBLE_2 3300U // Space -#define ARGO_MARK 400U -#define ARGO_ONE_SPACE 2200U -#define ARGO_ZERO_SPACE 900U +const uint16_t kArgoHdrMark = 6400; +const uint16_t kArgoHdrSpace = 3300; +const uint16_t kArgoBitMark = 400; +const uint16_t kArgoOneSpace = 2200; +const uint16_t kArgoZeroSpace = 900; #if SEND_ARGO -// Send a Argo A/C message. +// Send an Argo A/C message. // // Args: -// data: An array of ARGO_COMMAND_LENGTH bytes containing the IR command. +// data: An array of kArgoStateLength bytes containing the IR command. // // Status: ALPHA / Untested. -// -// Overloading the IRSend Function void IRsend::sendArgo(unsigned char data[], uint16_t nbytes, uint16_t repeat) { // Check if we have enough bytes to send a proper message. - if (nbytes < ARGO_COMMAND_LENGTH) return; - // Set IR carrier frequency - enableIROut(38); - for (uint16_t r = 0; r <= repeat; r++) { - // Header - // TODO(kaschmo): validate - mark(ARGO_PREAMBLE_1); - space(ARGO_PREAMBLE_2); - // send data, defined in IRSend.cpp - for (uint16_t i = 0; i < nbytes; i++) - sendData(ARGO_MARK, ARGO_ONE_SPACE, ARGO_MARK, - ARGO_ZERO_SPACE, data[i], 8, false); - // send LSB first reverses the bit order in array for sending. - } + if (nbytes < kArgoStateLength) return; + // TODO(kaschmo): validate + sendGeneric(kArgoHdrMark, kArgoHdrSpace, kArgoBitMark, kArgoOneSpace, + kArgoBitMark, kArgoZeroSpace, 0, 0, // No Footer. + data, nbytes, 38, false, repeat, kDutyDefault); } +#endif // SEND_ARGO -IRArgoAC::IRArgoAC(uint16_t pin) : _irsend(pin) { - stateReset(); -} +IRArgoAC::IRArgoAC(uint16_t pin) : _irsend(pin) { stateReset(); } -void IRArgoAC::begin() { - _irsend.begin(); -} +void IRArgoAC::begin() { _irsend.begin(); } +#if SEND_ARGO void IRArgoAC::send() { - // Serial.println("Sending IR code"); // Only for Debug checksum(); // Create valid checksum before sending _irsend.sendArgo(argo); } +#endif // SEND_ARGO void IRArgoAC::checksum() { uint8_t sum = 2; // Corresponds to byte 11 being constant 0b01 @@ -65,20 +52,18 @@ void IRArgoAC::checksum() { // Only add up bytes to 9. byte 10 is 0b01 constant anyway. // Assume that argo array is MSB first (left) - for (i = 0; i < 10; i++) - sum += argo[i]; + for (i = 0; i < 10; i++) sum += argo[i]; sum = sum % 256; // modulo 256 // Append sum to end of array // Set const part of checksum bit 10 argo[10] = 0b00000010; argo[10] += sum << 2; // Shift up 2 bits and append to byte 10 - argo[11] = sum >> 6; // Shift down 6 bits and add in two LSBs of bit 11 + argo[11] = sum >> 6; // Shift down 6 bits and add in two LSBs of bit 11 } void IRArgoAC::stateReset() { - for (uint8_t i = 0; i < ARGO_COMMAND_LENGTH; i++) - argo[i] = 0x0; + for (uint8_t i = 0; i < kArgoStateLength; i++) argo[i] = 0x0; // Argo Message. Store MSB left. // Default message: @@ -91,8 +76,8 @@ void IRArgoAC::stateReset() { this->off(); this->setTemp(20); this->setRoomTemp(25); - this->setCoolMode(ARGO_COOL_AUTO); - this->setFan(ARGO_FAN_AUTO); + this->setCoolMode(kArgoCoolAuto); + this->setFan(kArgoFanAuto); } uint8_t* IRArgoAC::getRaw() { @@ -123,9 +108,7 @@ void IRArgoAC::setPower(bool state) { off(); } -uint8_t IRArgoAC::getPower() { - return ac_state; -} +uint8_t IRArgoAC::getPower() { return ac_state; } void IRArgoAC::setMax(bool state) { max_mode = state; @@ -135,17 +118,15 @@ void IRArgoAC::setMax(bool state) { argo[9] &= 0b11110111; } -bool IRArgoAC::getMax() { - return max_mode; -} +bool IRArgoAC::getMax() { return max_mode; } // Set the temp in deg C // Sending 0 equals +4 void IRArgoAC::setTemp(uint8_t temp) { - if (temp < ARGO_MIN_TEMP) - temp = ARGO_MIN_TEMP; - else if (temp > ARGO_MAX_TEMP) - temp = ARGO_MAX_TEMP; + if (temp < kArgoMinTemp) + temp = kArgoMinTemp; + else if (temp > kArgoMaxTemp) + temp = kArgoMaxTemp; // Store in attributes set_temp = temp; @@ -161,9 +142,7 @@ void IRArgoAC::setTemp(uint8_t temp) { argo[3] += temp >> 2; // remove lowest to bits and append in 0-2 } -uint8_t IRArgoAC::getTemp() { - return set_temp; -} +uint8_t IRArgoAC::getTemp() { return set_temp; } // Set the speed of the fan void IRArgoAC::setFan(uint8_t fan) { @@ -175,18 +154,14 @@ void IRArgoAC::setFan(uint8_t fan) { argo[3] += fan << 3; } -uint8_t IRArgoAC::getFan() { - return fan_mode; -} +uint8_t IRArgoAC::getFan() { return fan_mode; } void IRArgoAC::setFlap(uint8_t flap) { flap_mode = flap; // TODO(kaschmo): set correct bits for flap mode } -uint8_t IRArgoAC::getFlap() { - return flap_mode; -} +uint8_t IRArgoAC::getFlap() { return flap_mode; } uint8_t IRArgoAC::getMode() { // return cooling 0, heating 1 @@ -203,9 +178,7 @@ void IRArgoAC::setCoolMode(uint8_t mode) { argo[2] += mode << 3; } -uint8_t IRArgoAC::getCoolMode() { - return cool_mode; -} +uint8_t IRArgoAC::getCoolMode() { return cool_mode; } void IRArgoAC::setHeatMode(uint8_t mode) { ac_mode = 1; // Set ac mode to heating @@ -218,9 +191,7 @@ void IRArgoAC::setHeatMode(uint8_t mode) { argo[2] += mode << 3; } -uint8_t IRArgoAC::getHeatMode() { - return heat_mode; -} +uint8_t IRArgoAC::getHeatMode() { return heat_mode; } void IRArgoAC::setNight(bool state) { night_mode = state; @@ -231,9 +202,7 @@ void IRArgoAC::setNight(bool state) { argo[9] &= 0b11111011; } -bool IRArgoAC::getNight() { - return night_mode; -} +bool IRArgoAC::getNight() { return night_mode; } void IRArgoAC::setiFeel(bool state) { ifeel_mode = state; @@ -244,9 +213,7 @@ void IRArgoAC::setiFeel(bool state) { argo[9] &= 0b01111111; } -bool IRArgoAC::getiFeel() { - return ifeel_mode; -} +bool IRArgoAC::getiFeel() { return ifeel_mode; } void IRArgoAC::setTime() { // TODO(kaschmo): use function call from checksum to set time first @@ -261,4 +228,3 @@ void IRArgoAC::setRoomTemp(uint8_t temp) { argo[3] += temp << 5; // Append to bit 5,6,7 argo[4] += temp >> 3; // Remove lowest 3 bits and append in 0,1 } -#endif // SEND_ARGO diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.h similarity index 51% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.h index a25199208..b49fc3517 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.h @@ -29,40 +29,59 @@ // Constants. Store MSB left. -#define ARGO_COOL_ON 0U // 0b000 -#define ARGO_COOL_OFF 3U // 0b110 -#define ARGO_COOL_AUTO 2U // 0b010 -#define ARGO_COOl_HUM 1U // 0b100 +const uint8_t kArgoCoolOn = 0; // 0b000 +const uint8_t kArgoCoolOff = 3; // 0b110 +const uint8_t kArgoCoolAuto = 2; // 0b010 +const uint8_t kArgoCoolHum = 1; // 0b100 +const uint8_t kArgoHeatOn = 0; // 0b001 +const uint8_t kArgoHeatAuto = 1; // 0b101 +const uint8_t kArgoHeatBlink = 2; // 0b011 // ??no idea what mode that is +const uint8_t kArgoMinTemp = 10; // Celsius offset +4 +const uint8_t kArgoMaxTemp = 32; // Celsius +const uint8_t kArgoFanAuto = 0; // 0b00 +const uint8_t kArgoFan3 = 3; // 0b11 +const uint8_t kArgoFan2 = 2; // 0b01 +const uint8_t kArgoFan1 = 1; // 0b10 +const uint8_t kArgoFlapAuto = 0; // 0b000 +const uint8_t kArgoFlap1 = 1; // 0b100 +const uint8_t kArgoFlap2 = 2; // 0b010 +const uint8_t kArgoFlap3 = 3; // 0b110 +const uint8_t kArgoFlap4 = 4; // 0b001 +const uint8_t kArgoFlap5 = 5; // 0b101 +const uint8_t kArgoFlap6 = 6; // 0b011 +const uint8_t kArgoFlapFull = 7; // 0b111 -#define ARGO_HEAT_ON 0U // 0b001 -#define ARGO_HEAT_AUTO 1U // 0b101 -#define ARGO_HEAT_BLINK 2U // 0b011 // ??no idea what mode that is +// Legacy defines. (Deperecated) +#define ARGO_COOL_ON kArgoCoolOn +#define ARGO_COOL_OFF kArgoCoolOff +#define ARGO_COOL_AUTO kArgoCoolAuto +#define ARGO_COOl_HUM kArgoCoolHum +#define ARGO_HEAT_ON kArgoHeatOn +#define ARGO_HEAT_AUTO kArgoHeatAuto +#define ARGO_HEAT_BLINK kArgoHeatBlink +#define ARGO_MIN_TEMP kArgoMinTemp +#define ARGO_MAX_TEMP kArgoMaxTemp +#define ARGO_FAN_AUTO kArgoFanAuto +#define ARGO_FAN_3 kArgoFan3 +#define ARGO_FAN_2 kArgoFan2 +#define ARGO_FAN_1 kArgoFan1 +#define ARGO_FLAP_AUTO kArgoFlapAuto +#define ARGO_FLAP_1 kArgoFlap1 +#define ARGO_FLAP_2 kArgoFlap2 +#define ARGO_FLAP_3 kArgoFlap3 +#define ARGO_FLAP_4 kArgoFlap4 +#define ARGO_FLAP_5 kArgoFlap5 +#define ARGO_FLAP_6 kArgoFlap6 +#define ARGO_FLAP_FULL kArgoFlapFull -#define ARGO_MIN_TEMP 10U // Celsius offset +4 -#define ARGO_MAX_TEMP 32U // Celsius - -#define ARGO_FAN_AUTO 0U // 0b00 -#define ARGO_FAN_3 3U // 0b11 -#define ARGO_FAN_2 2U // 0b01 -#define ARGO_FAN_1 1U // 0b10 - -#define ARGO_FLAP_AUTO 0U // 0b000 -#define ARGO_FLAP_1 1U // 0b100 -#define ARGO_FLAP_2 2U // 0b010 -#define ARGO_FLAP_3 3U // 0b110 -#define ARGO_FLAP_4 4U // 0b001 -#define ARGO_FLAP_5 5U // 0b101 -#define ARGO_FLAP_6 6U // 0b011 -#define ARGO_FLAP_FULL 7U // 0b111 - - -#if SEND_ARGO class IRArgoAC { public: explicit IRArgoAC(uint16_t pin); +#if SEND_ARGO void send(); +#endif // SEND_ARGO void begin(); void on(); void off(); @@ -102,7 +121,7 @@ class IRArgoAC { private: // # of bytes per command - uint8_t argo[ARGO_COMMAND_LENGTH]; // Defined in IRremoteESP8266.h + uint8_t argo[kArgoStateLength]; // Defined in IRremoteESP8266.h void stateReset(); void checksum(); IRsend _irsend; // instance of the IR send class @@ -119,6 +138,5 @@ class IRArgoAC { uint8_t max_mode; // on/off uint8_t ifeel_mode; // on/off }; -#endif // SEND_ARGO #endif // IR_ARGO_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp new file mode 100644 index 000000000..350d61cc1 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp @@ -0,0 +1,111 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// CCCCC AAA RRRRRR RRRRRR IIIII EEEEEEE RRRRRR +// CC C AAAAA RR RR RR RR III EE RR RR +// CC AA AA RRRRRR RRRRRR III EEEEE RRRRRR +// CC C AAAAAAA RR RR RR RR III EE RR RR +// CCCCC AA AA RR RR RR RR IIIII EEEEEEE RR RR + +// Suits Carrier/Surrey HVAC models: +// 42QG5A55970 (remote) +// 619EGX0090E0 / 619EGX0120E0 / 619EGX0180E0 / 619EGX0220E0 (indoor units) +// 53NGK009/012 (inverter) + +// Constants +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/385 +const uint16_t kCarrierAcHdrMark = 8532; +const uint16_t kCarrierAcHdrSpace = 4228; +const uint16_t kCarrierAcBitMark = 628; +const uint16_t kCarrierAcOneSpace = 1320; +const uint16_t kCarrierAcZeroSpace = 532; +const uint16_t kCarrierAcGap = 20000; + +#if SEND_CARRIER_AC +// Send a Carrier HVAC formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The bit size of the message being sent. typically kCarrierAcBits. +// repeat: The number of times the message is to be repeated. +// +// Status: BETA / Appears to work on real devices. +// +void IRsend::sendCarrierAC(uint64_t data, uint16_t nbits, uint16_t repeat) { + for (uint16_t r = 0; r <= repeat; r++) { + uint64_t temp_data = data; + // Carrier sends the data block three times. normal + inverted + normal. + for (uint16_t i = 0; i < 3; i++) { + sendGeneric(kCarrierAcHdrMark, kCarrierAcHdrSpace, kCarrierAcBitMark, + kCarrierAcOneSpace, kCarrierAcBitMark, kCarrierAcZeroSpace, + kCarrierAcBitMark, kCarrierAcGap, temp_data, nbits, 38, true, + 0, kDutyDefault); + temp_data = invertBits(temp_data, nbits); + } + } +} +#endif + +#if DECODE_CARRIER_AC +// Decode the supplied Carrier HVAC message. +// Carrier HVAC messages contain only 32 bits, but it is sent three(3) times. +// i.e. normal + inverted + normal +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. +// Typically kCarrierAcBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +bool IRrecv::decodeCarrierAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < ((2 * nbits + kHeader + kFooter) * 3) - 1) + return false; // Can't possibly be a valid Carrier message. + if (strict && nbits != kCarrierAcBits) + return false; // We expect Carrier to be 32 bits of message. + + uint64_t data = 0; + uint64_t prev_data = 0; + uint16_t offset = kStartOffset; + + for (uint8_t i = 0; i < 3; i++) { + prev_data = data; + // Header + if (!matchMark(results->rawbuf[offset++], kCarrierAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kCarrierAcHdrSpace)) + return false; + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kCarrierAcBitMark, + kCarrierAcOneSpace, kCarrierAcBitMark, kCarrierAcZeroSpace); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + // Footer + if (!matchMark(results->rawbuf[offset++], kCarrierAcBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kCarrierAcGap)) + return false; + // Compliance. + if (strict) { + // Check if the data is an inverted copy of the previous data. + if (i > 0 && prev_data != invertBits(data, nbits)) return false; + } + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = CARRIER_AC; + results->address = data >> 16; + results->command = data & 0xFFFF; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp new file mode 100644 index 000000000..ee539af25 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp @@ -0,0 +1,423 @@ +// Copyright bakrus +// Copyright 2017 David Conran + +#include "ir_Coolix.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// CCCCC OOOOO OOOOO LL IIIII XX XX +// CC C OO OO OO OO LL III XX XX +// CC OO OO OO OO LL III XXXX +// CC C OO OO OO OO LL III XX XX +// CCCCC OOOO0 OOOO0 LLLLLLL IIIII XX XX + +// Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit +// +// Supports: +// RG57K7(B)/BGEF remote control for Beko BINR 070/071 split-type aircon. +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/484 + +// Constants +// Pulse parms are *50-100 for the Mark and *50+100 for the space +// First MARK is the one after the long gap +// pulse parameters in usec +const uint16_t kCoolixTick = 560; // Approximately 21 cycles at 38kHz +const uint16_t kCoolixBitMarkTicks = 1; +const uint16_t kCoolixBitMark = kCoolixBitMarkTicks * kCoolixTick; +const uint16_t kCoolixOneSpaceTicks = 3; +const uint16_t kCoolixOneSpace = kCoolixOneSpaceTicks * kCoolixTick; +const uint16_t kCoolixZeroSpaceTicks = 1; +const uint16_t kCoolixZeroSpace = kCoolixZeroSpaceTicks * kCoolixTick; +const uint16_t kCoolixHdrMarkTicks = 8; +const uint16_t kCoolixHdrMark = kCoolixHdrMarkTicks * kCoolixTick; +const uint16_t kCoolixHdrSpaceTicks = 8; +const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick; +const uint16_t kCoolixMinGapTicks = kCoolixHdrMarkTicks + kCoolixZeroSpaceTicks; +const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick; + +#if SEND_COOLIX +// Send a Coolix message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kCoolixBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: BETA / Probably works. +// +// Ref: +// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_COOLIX.cpp +// TODO(anyone): Verify repeat functionality against a real unit. +void IRsend::sendCOOLIX(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits % 8 != 0) return; // nbits is required to be a multiple of 8. + + // Set IR carrier frequency + enableIROut(38); + + for (uint16_t r = 0; r <= repeat; r++) { + // Header + mark(kCoolixHdrMark); + space(kCoolixHdrSpace); + + // Data + // Break data into byte segments, starting at the Most Significant + // Byte. Each byte then being sent normal, then followed inverted. + for (uint16_t i = 8; i <= nbits; i += 8) { + // Grab a bytes worth of data. + uint8_t segment = (data >> (nbits - i)) & 0xFF; + // Normal + sendData(kCoolixBitMark, kCoolixOneSpace, kCoolixBitMark, + kCoolixZeroSpace, segment, 8, true); + // Inverted. + sendData(kCoolixBitMark, kCoolixOneSpace, kCoolixBitMark, + kCoolixZeroSpace, segment ^ 0xFF, 8, true); + } + + // Footer + mark(kCoolixBitMark); + space(kCoolixMinGap); // Pause before repeating + } +} +#endif + +// IRCoolixAC class +// Supports: +// RG57K7(B)/BGEF remote control for Beko BINR 070/071 split-type aircon. +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/484 +IRCoolixAC::IRCoolixAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRCoolixAC::stateReset() { remote_state = kCoolixDefaultState; } + +void IRCoolixAC::begin() { _irsend.begin(); } + +#if SEND_COOLIX +void IRCoolixAC::send() { _irsend.sendCOOLIX(remote_state); } +#endif // SEND_COOLIX + +uint32_t IRCoolixAC::getRaw() { return remote_state; } + +void IRCoolixAC::setRaw(const uint32_t new_code) { remote_state = new_code; } + +void IRCoolixAC::setTempRaw(const uint8_t code) { + remote_state &= ~kCoolixTempMask; // Clear the old temp. + remote_state |= (code << 4); +} + +uint8_t IRCoolixAC::getTempRaw() { + return (remote_state & kCoolixTempMask) >> 4; +} + +void IRCoolixAC::setTemp(const uint8_t desired) { + // Range check. + uint8_t temp = std::min(desired, kCoolixTempMax); + temp = std::max(temp, kCoolixTempMin); + setTempRaw(kCoolixTempMap[temp - kCoolixTempMin]); +} + +uint8_t IRCoolixAC::getTemp() { + uint8_t code = getTempRaw(); + uint8_t i; + for (i = 0; i < kCoolixTempRange; i++) + if (kCoolixTempMap[i] == code) return kCoolixTempMin + i; + return kCoolixUnknown; // Not a temp we expected. +} + +void IRCoolixAC::setSensorTempRaw(const uint8_t code) { + remote_state &= ~kCoolixSensorTempMask; // Clear previous sensor temp. + remote_state |= ((code & 0xF) << 8); +} + +void IRCoolixAC::setSensorTemp(const uint8_t desired) { + uint8_t temp = desired; + temp = std::min(temp, kCoolixSensorTempMax); + temp = std::max(temp, kCoolixSensorTempMin); + setSensorTempRaw(temp - kCoolixSensorTempMin); + setZoneFollow(true); // Setting a Sensor temp means you want to Zone Follow. +} + +uint8_t IRCoolixAC::getSensorTemp() { + return ((remote_state & kCoolixSensorTempMask) >> 8) + kCoolixSensorTempMin; +} + +bool IRCoolixAC::getPower() { + // There is only an off state. Everything else is "on". + return remote_state != kCoolixOff; +} + +void IRCoolixAC::setPower(const bool power) { + if (!power) remote_state = kCoolixOff; + // There really is no distinct "on" setting, so do nothing. +} + +bool IRCoolixAC::getSwing() { return remote_state == kCoolixSwing; } + +void IRCoolixAC::setSwing() { + // Assumes that repeated sending "swing" toggles the action on the device. + remote_state = kCoolixSwing; +} + +bool IRCoolixAC::getSleep() { return remote_state == kCoolixSleep; } + +void IRCoolixAC::setSleep() { remote_state = kCoolixSleep; } + +bool IRCoolixAC::getTurbo() { return remote_state == kCoolixTurbo; } + +void IRCoolixAC::setTurbo() { + // Assumes that repeated sending "turbo" toggles the action on the device. + remote_state = kCoolixTurbo; +} + +bool IRCoolixAC::getLed() { return remote_state == kCoolixLed; } + +void IRCoolixAC::setLed() { + // Assumes that repeated sending "Led" toggles the action on the device. + remote_state = kCoolixLed; +} + +bool IRCoolixAC::getClean() { return remote_state == kCoolixClean; } + +void IRCoolixAC::setClean() { remote_state = kCoolixClean; } + +bool IRCoolixAC::getZoneFollow() { + return remote_state & kCoolixZoneFollowMask; +} + +// Internal use only. +void IRCoolixAC::setZoneFollow(bool state) { + if (state) { + remote_state |= kCoolixZoneFollowMask; + } else { + remote_state &= ~kCoolixZoneFollowMask; + } +} + +void IRCoolixAC::clearSensorTemp() { + setZoneFollow(false); + setSensorTempRaw(kCoolixSensorTempIgnoreCode); +} + +void IRCoolixAC::setMode(const uint8_t mode) { + uint32_t actualmode = mode; + // Fan mode is a special case of Dry. + if (mode == kCoolixFan) actualmode = kCoolixDry; + switch (actualmode) { + case kCoolixCool: + case kCoolixAuto: + case kCoolixHeat: + case kCoolixDry: + remote_state = (remote_state & ~kCoolixModeMask) | (actualmode << 2); + // Force the temp into a known-good state. + setTemp(getTemp()); + } + if (mode == kCoolixFan) setTempRaw(kCoolixFanTempCode); +} + +uint8_t IRCoolixAC::getMode() { + uint8_t mode = (remote_state & kCoolixModeMask) >> 2; + if (mode == kCoolixDry) + if (getTempRaw() == kCoolixFanTempCode) return kCoolixFan; + return mode; +} + +uint8_t IRCoolixAC::getFan() { return (remote_state & kCoolixFanMask) >> 13; } + +void IRCoolixAC::setFan(const uint8_t speed) { + uint8_t newspeed = speed; + switch (speed) { + case kCoolixFanMin: + case kCoolixFanMed: + case kCoolixFanMax: + case kCoolixFanAuto: + case kCoolixFanZoneFollow: + case kCoolixFanFixed: + break; + default: // Unknown speed requested. + newspeed = kCoolixFanAuto; + } + remote_state &= ~kCoolixFanMask; + remote_state |= ((newspeed << 13) & kCoolixFanMask); +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRCoolixAC::toString() { + String result = ""; +#else +std::string IRCoolixAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) { + result += "On"; + } else { + result += "Off"; + return result; // If it's off, there is no other info. + } + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kCoolixFanAuto: + result += " (AUTO)"; + break; + case kCoolixFanMax: + result += " (MAX)"; + break; + case kCoolixFanMin: + result += " (MIN)"; + break; + case kCoolixFanMed: + result += " (MED)"; + break; + case kCoolixFanZoneFollow: + result += " (ZONEFOLLOW)"; + break; + case kCoolixFanFixed: + result += " (FIXED)"; + break; + default: + result += " (UNKNOWN)"; + } + // Special modes. + if (getSwing()) { + result += ", Swing: Toggle"; + return result; + } + if (getSleep()) { + result += ", Sleep: Toggle"; + return result; + } + if (getTurbo()) { + result += ", Turbo: Toggle"; + return result; + } + if (getLed()) { + result += ", Led: Toggle"; + return result; + } + if (getClean()) { + result += ", Mode: Self clean"; + return result; + } + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kCoolixAuto: + result += " (AUTO)"; + break; + case kCoolixCool: + result += " (COOL)"; + break; + case kCoolixHeat: + result += " (HEAT)"; + break; + case kCoolixDry: + result += " (DRY)"; + break; + case kCoolixFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + if (getMode() != kCoolixFan) // Fan mode doesn't have a temperature. + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Zone Follow: "; + if (getZoneFollow()) + result += "On"; + else + result += "Off"; + result += ", Sensor Temp: "; + if (getSensorTemp() > kCoolixSensorTempMax) + result += "Ignored"; + else + result += uint64ToString(getSensorTemp()) + "C"; + return result; +} + +#if DECODE_COOLIX +// Decode the supplied Coolix message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kCoolixBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Probably working. +bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t nbits, + bool strict) { + // The protocol sends the data normal + inverted, alternating on + // each byte. Hence twice the number of expected data bits. + if (results->rawlen < 2 * 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid COOLIX message. + if (strict && nbits != kCoolixBits) + return false; // Not strictly a COOLIX message. + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + uint64_t data = 0; + uint64_t inverted = 0; + uint16_t offset = kStartOffset; + + if (nbits > sizeof(data) * 8) + return false; // We can't possibly capture a Coolix packet that big. + + // Header + if (!matchMark(results->rawbuf[offset], kCoolixHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kCoolixHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kCoolixHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kCoolixHdrSpaceTicks; + + // Data + // Twice as many bits as there are normal plus inverted bits. + for (uint16_t i = 0; i < nbits * 2; i++, offset++) { + bool flip = (i / 8) % 2; + if (!matchMark(results->rawbuf[offset++], kCoolixBitMarkTicks * m_tick)) + return false; + if (matchSpace(results->rawbuf[offset], kCoolixOneSpaceTicks * s_tick)) { + if (flip) + inverted = (inverted << 1) | 1; + else + data = (data << 1) | 1; + } else if (matchSpace(results->rawbuf[offset], + kCoolixZeroSpaceTicks * s_tick)) { + if (flip) + inverted <<= 1; + else + data <<= 1; + } else { + return false; + } + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kCoolixBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kCoolixMinGapTicks * s_tick)) + return false; + + // Compliance + uint64_t orig = data; // Save a copy of the data. + if (strict) { + for (uint16_t i = 0; i < nbits; i += 8, data >>= 8, inverted >>= 8) + if ((data & 0xFF) != ((inverted & 0xFF) ^ 0xFF)) return false; + } + + // Success + results->decode_type = COOLIX; + results->bits = nbits; + results->value = orig; + results->address = 0; + results->command = 0; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h new file mode 100644 index 000000000..ee4552074 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h @@ -0,0 +1,139 @@ +// Coolix A/C +// +// Copyright 2018 David Conran + +#ifndef IR_COOLIX_H_ +#define IR_COOLIX_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// CCCCC OOOOO OOOOO LL IIIII XX XX +// CC C OO OO OO OO LL III XX XX +// CC OO OO OO OO LL III XXXX +// CC C OO OO OO OO LL III XX XX +// CCCCC OOOO0 OOOO0 LLLLLLL IIIII XX XX + +// Supports: +// RG57K7(B)/BGEF remote control for Beko BINR 070/071 split-type aircon. +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/484 +// Kudos: +// Hamper: For the breakdown and mapping of the bit values. + +// Constants +// Modes +const uint8_t kCoolixCool = 0b00; +const uint8_t kCoolixDry = 0b01; +const uint8_t kCoolixAuto = 0b10; +const uint8_t kCoolixHeat = 0b11; +const uint8_t kCoolixFan = 4; // Synthetic. +const uint32_t kCoolixModeMask = 0b000000000000000000001100; // 0xC +const uint32_t kCoolixZoneFollowMask = 0b000010000000000000000000; // 0x80000 +// Fan Control +const uint8_t kCoolixFanMin = 0b100; +const uint8_t kCoolixFanMed = 0b010; +const uint8_t kCoolixFanMax = 0b001; +const uint8_t kCoolixFanAuto = 0b101; +const uint8_t kCoolixFanZoneFollow = 0b110; +const uint8_t kCoolixFanFixed = 0b111; +const uint32_t kCoolixFanMask = 0b000000001110000000000000; // 0x00E000 +// Temperature +const uint8_t kCoolixTempMin = 17; // Celsius +const uint8_t kCoolixTempMax = 30; // Celsius +const uint8_t kCoolixTempRange = kCoolixTempMax - kCoolixTempMin + 1; +const uint8_t kCoolixFanTempCode = 0b1110; // Part of Fan Mode. +const uint32_t kCoolixTempMask = 0b11110000; +const uint8_t kCoolixTempMap[kCoolixTempRange] = { + 0b0000, // 17C + 0b0001, // 18c + 0b0011, // 19C + 0b0010, // 20C + 0b0110, // 21C + 0b0111, // 22C + 0b0101, // 23C + 0b0100, // 24C + 0b1100, // 25C + 0b1101, // 26C + 0b1001, // 27C + 0b1000, // 28C + 0b1010, // 29C + 0b1011 // 30C +}; +const uint8_t kCoolixSensorTempMin = 16; // Celsius +const uint8_t kCoolixSensorTempMax = 30; // Celsius +const uint8_t kCoolixSensorTempIgnoreCode = 0b1111; +const uint32_t kCoolixSensorTempMask = 0b000000000000111100000000; // 0xF00 +// Fixed states/messages. +const uint8_t kCoolixPrefix = 0b1011; // 0xB +const uint8_t kCoolixUnknown = 0xFF; +const uint32_t kCoolixOff = 0b101100100111101111100000; // 0xB27BE0 +const uint32_t kCoolixSwing = 0b101100100110101111100000; // 0xB26BE0 +const uint32_t kCoolixSleep = 0b101100101110000000000011; // 0xB2E003 +const uint32_t kCoolixTurbo = 0b101101011111010110100010; // 0xB5F5A2 +const uint32_t kCoolixLed = 0b101101011111010110100101; // 0xB5F5A5 +const uint32_t kCoolixClean = 0b101101011111010110101010; // 0xB5F5AA +// On, 25C, Mode: Auto, Fan: Auto, Zone Follow: Off, Sensor Temp: Ignore. +const uint32_t kCoolixDefaultState = 0b101100101011111111001000; // 0xB2BFC8 + +// Classes +class IRCoolixAC { + public: + explicit IRCoolixAC(uint16_t pin); + + void stateReset(); +#if SEND_COOLIX + void send(); +#endif // SEND_COOLIX + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setSensorTemp(const uint8_t desired); + uint8_t getSensorTemp(); + void clearSensorTemp(); + void setFan(const uint8_t fan); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setSwing(); + bool getSwing(); + void setSleep(); + bool getSleep(); + void setTurbo(); + bool getTurbo(); + void setLed(); + bool getLed(); + void setClean(); + bool getClean(); + bool getZoneFollow(); + uint32_t getRaw(); + void setRaw(const uint32_t new_code); + +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + // The state of the IR remote in IR code form. + uint32_t remote_state; + IRsend _irsend; + void setTempRaw(const uint8_t code); + uint8_t getTempRaw(); + void setSensorTempRaw(const uint8_t code); + void setZoneFollow(const bool state); +}; + +#endif // IR_COOLIX_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp new file mode 100644 index 000000000..b94b4a63a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp @@ -0,0 +1,750 @@ +/* +An Arduino sketch to emulate IR Daikin ARC433** remote control unit +Read more at: +http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/ + +Copyright 2016 sillyfrog +Copyright 2017 sillyfrog, crankyoldgit +*/ + +#include "ir_Daikin.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" + +// DDDDD AAA IIIII KK KK IIIII NN NN +// DD DD AAAAA III KK KK III NNN NN +// DD DD AA AA III KKKK III NN N NN +// DD DD AAAAAAA III KK KK III NN NNN +// DDDDDD AA AA IIIII KK KK IIIII NN NN + +// Constants +// Ref: +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +// http://rdlab.cdmt.vn/project-2013/daikin-ir-protocol + +#if SEND_DAIKIN +// Original header +// static uint8_t header1[DAIKIN_HEADER1_LENGTH]; +// header1[0] = 0b00010001; +// header1[1] = 0b11011010; +// header1[2] = 0b00100111; +// header1[3] = 0b00000000; +// header1[4] = 0b11000101; +// header1[5] = 0b00000000; +// header1[6] = 0b00000000; +// header1[7] = 0b11010111; + +// Send a Daikin A/C message. +// +// Args: +// data: An array of kDaikinStateLength bytes containing the IR command. +// +// Status: STABLE +// +// Ref: +// IRDaikinESP.cpp +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +void IRsend::sendDaikin(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kDaikinStateLength) + return; // Not enough bytes to send a proper message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Send the header, 0b00000 + sendGeneric(0, 0, // No header for the header + kDaikinBitMark, kDaikinOneSpace, kDaikinBitMark, + kDaikinZeroSpace, kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, + (uint64_t)0b00000, 5, 38, false, 0, 50); + // Leading header + // Do this as a constant to save RAM and keep in flash memory + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, + kDaikinFirstHeader64, 64, 38, false, 0, 50); + // Data #1 + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, data, 8, 38, + false, 0, 50); + // Data #2 + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, data + 8, + nbytes - 8, 38, false, 0, 50); + } +} +#endif // SEND_DAIKIN + +IRDaikinESP::IRDaikinESP(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRDaikinESP::begin() { _irsend.begin(); } + +#if SEND_DAIKIN +void IRDaikinESP::send() { + checksum(); + _irsend.sendDaikin(daikin); +} +#endif // SEND_DAIKIN + +// Calculate the checksum for a given data block. +// Args: +// block: Ptr to the start of the data block. +// length: Nr. of bytes to checksum. +// Returns: +// A byte containing the calculated checksum. +uint8_t IRDaikinESP::calcBlockChecksum(const uint8_t *block, + const uint16_t length) { + uint8_t sum = 0; + // Daikin checksum is just the addition of all the data bytes + // in the block but capped to 8 bits. + for (uint16_t i = 0; i < length; i++, block++) sum += *block; + return sum & 0xFFU; +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRDaikinESP::validChecksum(const uint8_t state[], const uint16_t length) { + if (length < 8 || state[7] != calcBlockChecksum(state, 7)) return false; + if (length < 10 || + state[length - 1] != calcBlockChecksum(state + 8, length - 9)) + return false; + return true; +} + +// Calculate and set the checksum values for the internal state. +void IRDaikinESP::checksum() { + daikin[7] = calcBlockChecksum(daikin, 7); + daikin[26] = calcBlockChecksum(daikin + 8, 17); +} + +void IRDaikinESP::stateReset() { + for (uint8_t i = 0; i < kDaikinStateLength; i++) daikin[i] = 0x0; + + daikin[0] = 0x11; + daikin[1] = 0xDA; + daikin[2] = 0x27; + daikin[4] = 0x42; + // daikin[7] is a checksum byte, it will be set by checksum(). + daikin[8] = 0x11; + daikin[9] = 0xDA; + daikin[10] = 0x27; + daikin[13] = 0x49; + daikin[14] = 0x1E; + daikin[16] = 0xB0; + daikin[19] = 0x06; + daikin[20] = 0x60; + daikin[23] = 0xC0; + // daikin[26] is a checksum byte, it will be set by checksum(). + checksum(); +} + +uint8_t *IRDaikinESP::getRaw() { + checksum(); // Ensure correct settings before sending. + return daikin; +} + +void IRDaikinESP::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kDaikinStateLength; i++) daikin[i] = new_code[i]; +} + +void IRDaikinESP::on() { + // state = ON; + setBit(kDaikinBytePower, kDaikinBitPower); +} + +void IRDaikinESP::off() { + // state = OFF; + clearBit(kDaikinBytePower, kDaikinBitPower); +} + +void IRDaikinESP::setPower(bool state) { + if (state) + on(); + else + off(); +} + +bool IRDaikinESP::getPower() { + return (getBit(kDaikinBytePower, kDaikinBitPower) > 0); +} + +// Set the temp in deg C +void IRDaikinESP::setTemp(uint8_t temp) { + if (temp < kDaikinMinTemp) + temp = kDaikinMinTemp; + else if (temp > kDaikinMaxTemp) + temp = kDaikinMaxTemp; + daikin[14] = temp * 2; +} + +uint8_t IRDaikinESP::getTemp() { return daikin[14] / 2; } + +// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet +void IRDaikinESP::setFan(uint8_t fan) { + // Set the fan speed bits, leave low 4 bits alone + uint8_t fanset; + if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto) + fanset = fan; + else if (fan < kDaikinFanMin || fan > kDaikinFanMax) + fanset = kDaikinFanAuto; + else + fanset = 2 + fan; + daikin[16] &= 0x0F; + daikin[16] |= (fanset << 4); +} + +uint8_t IRDaikinESP::getFan() { + uint8_t fan = daikin[16] >> 4; + if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; + return fan; +} + +uint8_t IRDaikinESP::getMode() { + /* + kDaikinCool + kDaikinHeat + kDaikinFan + kDaikinAuto + kDaikinDry + */ + return daikin[13] >> 4; +} + +void IRDaikinESP::setMode(uint8_t mode) { + switch (mode) { + case kDaikinCool: + case kDaikinHeat: + case kDaikinFan: + case kDaikinDry: + break; + default: + mode = kDaikinAuto; + } + mode <<= 4; + daikin[13] &= 0b10001111; + daikin[13] |= mode; +} + +void IRDaikinESP::setSwingVertical(bool state) { + if (state) + daikin[16] |= 0x0F; + else + daikin[16] &= 0xF0; +} + +bool IRDaikinESP::getSwingVertical() { return daikin[16] & 0x01; } + +void IRDaikinESP::setSwingHorizontal(bool state) { + if (state) + daikin[17] |= 0x0F; + else + daikin[17] &= 0xF0; +} + +bool IRDaikinESP::getSwingHorizontal() { return daikin[17] & 0x01; } + +void IRDaikinESP::setQuiet(bool state) { + if (state) { + setBit(kDaikinByteSilent, kDaikinBitSilent); + // Powerful & Quiet mode being on are mutually exclusive. + setPowerful(false); + } else { + clearBit(kDaikinByteSilent, kDaikinBitSilent); + } +} + +bool IRDaikinESP::getQuiet() { + return (getBit(kDaikinByteSilent, kDaikinBitSilent) > 0); +} + +void IRDaikinESP::setPowerful(bool state) { + if (state) { + setBit(kDaikinBytePowerful, kDaikinBitPowerful); + // Powerful, Quiet, & Econo mode being on are mutually exclusive. + setQuiet(false); + setEcono(false); + } else { + clearBit(kDaikinBytePowerful, kDaikinBitPowerful); + } +} + +bool IRDaikinESP::getPowerful() { + return (getBit(kDaikinBytePowerful, kDaikinBitPowerful) > 0); +} + +void IRDaikinESP::setSensor(bool state) { + if (state) + setBit(kDaikinByteSensor, kDaikinBitSensor); + else + clearBit(kDaikinByteSensor, kDaikinBitSensor); +} + +bool IRDaikinESP::getSensor() { + return (getBit(kDaikinByteSensor, kDaikinBitSensor) > 0); +} + +void IRDaikinESP::setEcono(bool state) { + if (state) { + setBit(kDaikinByteEcono, kDaikinBitEcono); + // Powerful & Econo mode being on are mutually exclusive. + setPowerful(false); + } else { + clearBit(kDaikinByteEcono, kDaikinBitEcono); + } +} + +bool IRDaikinESP::getEcono() { + return (getBit(kDaikinByteEcono, kDaikinBitEcono) > 0); +} + +void IRDaikinESP::setEye(bool state) { + if (state) + setBit(kDaikinByteEye, kDaikinBitEye); + else + clearBit(kDaikinByteEye, kDaikinBitEye); +} + +bool IRDaikinESP::getEye() { + return (getBit(kDaikinByteEye, kDaikinBitEye) > 0); +} + +void IRDaikinESP::setMold(bool state) { + if (state) + setBit(kDaikinByteMold, kDaikinBitMold); + else + clearBit(kDaikinByteMold, kDaikinBitMold); +} + +bool IRDaikinESP::getMold() { + return (getBit(kDaikinByteMold, kDaikinBitMold) > 0); +} + +void IRDaikinESP::setBit(uint8_t byte, uint8_t bitmask) { + daikin[byte] |= bitmask; +} + +void IRDaikinESP::clearBit(uint8_t byte, uint8_t bitmask) { + bitmask = ~bitmask; + daikin[byte] &= bitmask; +} + +uint8_t IRDaikinESP::getBit(uint8_t byte, uint8_t bitmask) { + return daikin[byte] & bitmask; +} + +// starttime: Number of minutes after midnight, in 10 minutes increments +void IRDaikinESP::enableOnTimer(uint16_t starttime) { + setBit(kDaikinByteOnTimer, kDaikinBitOnTimer); + daikin[18] = (uint8_t)(starttime & 0x00FF); + // only keep 4 bits + daikin[19] &= 0xF0; + daikin[19] |= (uint8_t)((starttime >> 8) & 0x0F); +} + +void IRDaikinESP::disableOnTimer() { + enableOnTimer(0x600); + clearBit(kDaikinByteOnTimer, kDaikinBitOnTimer); +} + +uint16_t IRDaikinESP::getOnTime() { + uint16_t ret; + ret = daikin[19] & 0x0F; + ret = ret << 8; + ret += daikin[18]; + return ret; +} + +bool IRDaikinESP::getOnTimerEnabled() { + return getBit(kDaikinByteOnTimer, kDaikinBitOnTimer); +} + +// endtime: Number of minutes after midnight, in 10 minutes increments +void IRDaikinESP::enableOffTimer(uint16_t endtime) { + setBit(kDaikinByteOffTimer, kDaikinBitOffTimer); + daikin[20] = (uint8_t)((endtime >> 4) & 0xFF); + daikin[19] &= 0x0F; + daikin[19] |= (uint8_t)((endtime & 0x000F) << 4); +} + +void IRDaikinESP::disableOffTimer() { + enableOffTimer(0x600); + clearBit(kDaikinByteOffTimer, kDaikinBitOffTimer); +} + +uint16_t IRDaikinESP::getOffTime() { + uint16_t ret, tmp; + ret = daikin[20]; + ret <<= 4; + tmp = daikin[19] & 0xF0; + tmp >>= 4; + ret += tmp; + return ret; +} + +bool IRDaikinESP::getOffTimerEnabled() { + return getBit(kDaikinByteOffTimer, kDaikinBitOffTimer); +} + +void IRDaikinESP::setCurrentTime(uint16_t numMins) { + if (numMins > 24 * 60) numMins = 0; // If > 23:59, set to 00:00 + daikin[5] = (uint8_t)(numMins & 0x00FF); + // only keep 4 bits + daikin[6] &= 0xF0; + daikin[6] |= (uint8_t)((numMins >> 8) & 0x0F); +} + +uint16_t IRDaikinESP::getCurrentTime() { + uint16_t ret; + ret = daikin[6] & 0x0F; + ret <<= 8; + ret += daikin[5]; + return ret; +} + +#ifdef ARDUINO +String IRDaikinESP::renderTime(uint16_t timemins) { + String ret; +#else // ARDUINO +std::string IRDaikinESP::renderTime(uint16_t timemins) { + std::string ret; +#endif // ARDUINO + uint16_t hours, mins; + hours = timemins / 60; + ret = uint64ToString(hours) + ":"; + mins = timemins - (hours * 60); + if (mins < 10) ret += "0"; + ret += uint64ToString(mins); + return ret; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRDaikinESP::toString() { + String result = ""; +#else // ARDUINO +std::string IRDaikinESP::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kDaikinAuto: + result += " (AUTO)"; + break; + case kDaikinCool: + result += " (COOL)"; + break; + case kDaikinHeat: + result += " (HEAT)"; + break; + case kDaikinDry: + result += " (DRY)"; + break; + case kDaikinFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kDaikinFanAuto: + result += " (AUTO)"; + break; + case kDaikinFanQuiet: + result += " (QUIET)"; + break; + case kDaikinFanMin: + result += " (MIN)"; + break; + case kDaikinFanMax: + result += " (MAX)"; + break; + } + result += ", Powerful: "; + if (getPowerful()) + result += "On"; + else + result += "Off"; + result += ", Quiet: "; + if (getQuiet()) + result += "On"; + else + result += "Off"; + result += ", Sensor: "; + if (getSensor()) + result += "On"; + else + result += "Off"; + result += ", Eye: "; + if (getEye()) + result += "On"; + else + result += "Off"; + result += ", Mold: "; + if (getMold()) + result += "On"; + else + result += "Off"; + result += ", Swing (Horizontal): "; + if (getSwingHorizontal()) + result += "On"; + else + result += "Off"; + result += ", Swing (Vertical): "; + if (getSwingVertical()) + result += "On"; + else + result += "Off"; + result += ", Current Time: " + renderTime(getCurrentTime()); + result += ", On Time: "; + if (getOnTimerEnabled()) + result += renderTime(getOnTime()); + else + result += "Off"; + result += ", Off Time: "; + if (getOffTimerEnabled()) + result += renderTime(getOffTime()); + else + result += "Off"; + + return result; +} + +#if DAIKIN_DEBUG +// Print what we have +void IRDaikinESP::printState() { +#ifdef ARDUINO + String strbits; +#else // ARDUINO + std::string strbits; +#endif // ARDUINO + DPRINTLN("Raw Bits:"); + for (uint8_t i = 0; i < kDaikinStateLength; i++) { + strbits = uint64ToString(daikin[i], BIN); + while (strbits.length() < 8) strbits = "0" + strbits; + DPRINT(strbits); + DPRINT(" "); + } + DPRINTLN(""); + DPRINTLN(toString()); +} +#endif // DAIKIN_DEBUG + +/* + * Return most important bits to allow replay + * layout is: + * 0: Power + * 1-3: Mode + * 4-7: Fan speed/mode + * 8-14: Target Temperature + * 15: Econo + * 16: Powerful + * 17: Quiet + * 18: Sensor + * 19: Swing Vertical + * 20-31: Current time (mins since midnight) + * */ +uint32_t IRDaikinESP::getCommand() { + uint32_t ret = 0; + uint32_t tmp = 0; + if (getPower()) ret |= 0b00000000000000000000000000000001; + tmp = getMode(); + tmp = tmp << 1; + ret |= tmp; + + tmp = getFan(); + tmp <<= 4; + ret |= tmp; + + tmp = getTemp(); + tmp <<= 8; + ret |= tmp; + + if (getEcono()) ret |= 0b00000000000000001000000000000000; + if (getPowerful()) ret |= 0b00000000000000010000000000000000; + if (getQuiet()) ret |= 0b00000000000000100000000000000000; + if (getSensor()) ret |= 0b00000000000001000000000000000000; + if (getSwingVertical()) ret |= 0b00000000000010000000000000000000; + ret |= (getCurrentTime() << 20); + return ret; +} + +void IRDaikinESP::setCommand(uint32_t value) { + uint32_t tmp = 0; + if (value & 0b00000000000000000000000000000001) setPower(true); + tmp = value & 0b00000000000000000000000000001110; + tmp >>= 1; + setMode(tmp); + + tmp = value & 0b00000000000000000000000011110000; + tmp >>= 4; + setFan(tmp); + + tmp = value & 0b00000000000000000111111100000000; + tmp >>= 8; + setTemp(tmp); + + if (value & 0b00000000000000001000000000000000) setEcono(true); + if (value & 0b00000000000000010000000000000000) setPowerful(true); + if (value & 0b00000000000000100000000000000000) setQuiet(true); + if (value & 0b00000000000001000000000000000000) setSensor(true); + if (value & 0b00000000000010000000000000000000) setSwingVertical(true); + + value >>= 20; + setCurrentTime(value); +} + +#if DECODE_DAIKIN + +void addbit(bool val, unsigned char data[]) { + uint8_t curbit = data[kDaikinCurBit]; + uint8_t curindex = data[kDaikinCurIndex]; + if (val) { + unsigned char bit = 1; + bit = bit << curbit; + data[curindex] |= bit; + } + curbit++; + if (curbit == 8) { + curbit = 0; + curindex++; + } + data[kDaikinCurBit] = curbit; + data[kDaikinCurIndex] = curindex; +} + +bool checkheader(decode_results *results, uint16_t *offset) { + if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinBitMark, + kDaikinTolerance, kDaikinMarkExcess)) + return false; + if (!IRrecv::matchSpace(results->rawbuf[(*offset)++], + kDaikinZeroSpace + kDaikinGap, kDaikinTolerance, + kDaikinMarkExcess)) + return false; + if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinHdrMark, + kDaikinTolerance, kDaikinMarkExcess)) + return false; + if (!IRrecv::matchSpace(results->rawbuf[(*offset)++], kDaikinHdrSpace, + kDaikinTolerance, kDaikinMarkExcess)) + return false; + + return true; +} + +bool readbits(decode_results *results, uint16_t *offset, + unsigned char daikin_code[], uint16_t countbits) { + for (uint16_t i = 0; i < countbits && *offset < results->rawlen - 1; + i++, (*offset)++) { + if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinBitMark, + kDaikinTolerance, kDaikinMarkExcess)) + return false; + if (IRrecv::matchSpace(results->rawbuf[*offset], kDaikinOneSpace, + kDaikinTolerance, kDaikinMarkExcess)) + addbit(1, daikin_code); + else if (IRrecv::matchSpace(results->rawbuf[*offset], kDaikinZeroSpace, + kDaikinTolerance, kDaikinMarkExcess)) + addbit(0, daikin_code); + else + return false; + } + return true; +} + +// Decode the supplied Daikin A/C message. +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. (kDaikinRawBits) +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should be working. +// +// Notes: +// If DAIKIN_DEBUG enabled, will print all the set options and values. +// +// Ref: +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +bool IRrecv::decodeDaikin(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < kDaikinRawBits) return false; + + // Compliance + if (strict && nbits != kDaikinRawBits) return false; + + uint16_t offset = kStartOffset; + unsigned char daikin_code[kDaikinStateLength + 2]; + for (uint8_t i = 0; i < kDaikinStateLength + 2; i++) daikin_code[i] = 0; + + // Header (#1) + for (uint8_t i = 0; i < 10; i++) { + if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false; + } + if (!checkheader(results, &offset)) return false; + + // Data (#1) + if (!readbits(results, &offset, daikin_code, 8 * 8)) return false; + + // Ignore everything that has just been captured as it is not needed. + // Some remotes may not send this portion, my remote did, but it's not + // required. + for (uint8_t i = 0; i < kDaikinStateLength + 2; i++) daikin_code[i] = 0; + + // Header (#2) + if (!checkheader(results, &offset)) return false; + + // Data (#2) + if (!readbits(results, &offset, daikin_code, 8 * 8)) return false; + + // Header (#3) + if (!checkheader(results, &offset)) return false; + + // Data (#3), read up everything else + if (!readbits(results, &offset, daikin_code, kDaikinBits - (8 * 8))) + return false; + + // Footer + if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kDaikinGap)) + return false; + + // Compliance + if (strict) { + if (!IRDaikinESP::validChecksum(daikin_code)) return false; + } + + // Success +#if DAIKIN_DEBUG + IRDaikinESP dako = IRDaikinESP(0); + dako.setRaw(daikin_code); +#ifdef ARDUINO + yield(); +#endif // ARDUINO + dako.printState(); +#endif // DAIKIN_DEBUG + + // Copy across the bits to state + for (uint8_t i = 0; i < kDaikinStateLength; i++) + results->state[i] = daikin_code[i]; + results->bits = kDaikinStateLength * 8; + results->decode_type = DAIKIN; + return true; +} +#endif // DECODE_DAIKIN diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h new file mode 100644 index 000000000..7094990d8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h @@ -0,0 +1,208 @@ +// Copyright 2016 sillyfrog +// Copyright 2017 sillyfrog, crankyoldgit +#ifndef IR_DAIKIN_H_ +#define IR_DAIKIN_H_ + +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// Option to disable the additional Daikin debug info to conserve memory +#define DAIKIN_DEBUG false + +// DDDDD AAA IIIII KK KK IIIII NN NN +// DD DD AAAAA III KK KK III NNN NN +// DD DD AA AA III KKKK III NN N NN +// DD DD AAAAAAA III KK KK III NN NNN +// DDDDDD AA AA IIIII KK KK IIIII NN NN + +/* + Daikin AC map + byte 5=Current time, mins past midnight, low bits + byte 6 + b0-b3=Current time, mins past midnight, high bits + byte 7= checksum of the first part (and last byte before a 29ms pause) + byte 13=mode + b7 = 0 + b6+b5+b4 = Mode + Modes: b6+b5+b4 + 011 = Cool + 100 = Heat (temp 23) + 110 = FAN (temp not shown, but 25) + 000 = Fully Automatic (temp 25) + 010 = DRY (temp 0xc0 = 96 degrees c) + b3 = 1 + b2 = OFF timer set + b1 = ON timer set + b0 = Air Conditioner ON + byte 14=temp*2 (Temp should be between 10 - 32) + byte 16=Fan + FAN control + b7+b6+b5+b4 = Fan speed + Fan: b7+b6+b5+b4 + 0×3 = 1 bar + 0×4 = 2 bar + 0×5 = 3 bar + 0×6 = 4 bar + 0×7 = 5 bar + 0xa = Auto + 0xb = Quite + b3+b2+b1+b0 = Swing control up/down + Swing control up/down: + 0000 = Swing up/down off + 1111 = Swing up/down on + byte 17 + Swing control left/right: + 0000 = Swing left/right off + 1111 = Swing left/right on + byte 18=On timer mins past midnight, low bits + byte 19 + b0-b3=On timer mins past midnight, high bits + b4-b7=Off timer mins past midnight, low bits + byte 20=Off timer mins past midnight, high bits + byte 21=Aux -> Powerful (bit 1), Silent (bit 5) + byte 24=Aux2 + b1: Sensor + b2: Econo mode + b7: Intelligent eye on + byte 25=Aux3 + b1: Mold Proof + byte 26= checksum of the second part +*/ + +// Constants +const uint8_t kDaikinAuto = 0b000; +const uint8_t kDaikinDry = 0b010; +const uint8_t kDaikinCool = 0b011; +const uint8_t kDaikinHeat = 0b100; +const uint8_t kDaikinFan = 0b110; +const uint8_t kDaikinMinTemp = 10; // Celsius +const uint8_t kDaikinMaxTemp = 32; // Celsius +const uint8_t kDaikinFanMin = 1; +const uint8_t kDaikinFanMax = 5; +const uint8_t kDaikinFanAuto = 0b1010; +const uint8_t kDaikinFanQuiet = 0b1011; +const uint8_t kDaikinBytePower = 13; +const uint8_t kDaikinBitPower = 0b00000001; +const uint8_t kDaikinBytePowerful = 21; +const uint8_t kDaikinBitPowerful = 0b00000001; +const uint8_t kDaikinByteSilent = 21; +const uint8_t kDaikinBitSilent = 0b00100000; +const uint8_t kDaikinByteSensor = 24; +const uint8_t kDaikinBitSensor = 0b00000010; +const uint8_t kDaikinByteEcono = 24; +const uint8_t kDaikinBitEcono = 0b00000100; +const uint8_t kDaikinByteEye = 24; +const uint8_t kDaikinBitEye = 0b10000000; +const uint8_t kDaikinByteMold = 25; +const uint8_t kDaikinBitMold = 0b00000010; +const uint8_t kDaikinByteOffTimer = 13; +const uint8_t kDaikinBitOffTimer = 0b00000100; +const uint8_t kDaikinByteOnTimer = 13; +const uint8_t kDaikinBitOnTimer = 0b00000010; +const uint8_t kDaikinCurBit = kDaikinStateLength; +const uint8_t kDaikinCurIndex = kDaikinStateLength + 1; +const uint8_t kDaikinTolerance = 35; +const uint16_t kDaikinMarkExcess = kMarkExcess; +const uint16_t kDaikinHdrMark = 3650; // kDaikinBitMark * 8 +const uint16_t kDaikinHdrSpace = 1623; // kDaikinBitMark * 4 +const uint16_t kDaikinBitMark = 428; +const uint16_t kDaikinZeroSpace = 428; +const uint16_t kDaikinOneSpace = 1280; +const uint16_t kDaikinGap = 29000; +// Note bits in each octet swapped so can be sent as a single value +const uint64_t kDaikinFirstHeader64 = + 0b1101011100000000000000001100010100000000001001111101101000010001; + +// Legacy defines. +#define DAIKIN_COOL kDaikinCool +#define DAIKIN_HEAT kDaikinHeat +#define DAIKIN_FAN kDaikinFan +#define DAIKIN_AUTO kDaikinAuto +#define DAIKIN_DRY kDaikinDry +#define DAIKIN_MIN_TEMP kDaikinMinTemp +#define DAIKIN_MAX_TEMP kDaikinMaxTemp +#define DAIKIN_FAN_MIN kDaikinFanMin +#define DAIKIN_FAN_MAX kDaikinFanMax +#define DAIKIN_FAN_AUTO kDaikinFanAuto +#define DAIKIN_FAN_QUIET kDaikinFanQuiet + +class IRDaikinESP { + public: + explicit IRDaikinESP(uint16_t pin); + +#if SEND_DAIKIN + void send(); +#endif + void begin(); + void on(); + void off(); + void setPower(bool state); + bool getPower(); + void setTemp(uint8_t temp); + uint8_t getTemp(); + void setFan(uint8_t fan); + uint8_t getFan(); + uint8_t getMode(); + void setMode(uint8_t mode); + void setSwingVertical(bool state); + bool getSwingVertical(); + void setSwingHorizontal(bool state); + bool getSwingHorizontal(); + bool getQuiet(); + void setQuiet(bool state); + bool getPowerful(); + void setPowerful(bool state); + void setSensor(bool state); + bool getSensor(); + void setEcono(bool state); + bool getEcono(); + void setEye(bool state); + bool getEye(); + void setMold(bool state); + bool getMold(); + void enableOnTimer(uint16_t starttime); + void disableOnTimer(); + uint16_t getOnTime(); + bool getOnTimerEnabled(); + void enableOffTimer(uint16_t endtime); + void disableOffTimer(); + uint16_t getOffTime(); + bool getOffTimerEnabled(); + void setCurrentTime(uint16_t time); + uint16_t getCurrentTime(); + uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); +#if DAIKIN_DEBUG + void printState(); +#endif // DAIKIN_DEBUG + uint32_t getCommand(); + void setCommand(uint32_t value); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kDaikinStateLength); +#ifdef ARDUINO + String toString(); + static String renderTime(uint16_t timemins); +#else + std::string toString(); + static std::string renderTime(uint16_t timemins); +#endif + + private: + // # of bytes per command + uint8_t daikin[kDaikinStateLength]; + void stateReset(); + static uint8_t calcBlockChecksum(const uint8_t* block, const uint16_t length); + void checksum(); + void setBit(uint8_t byte, uint8_t bitmask); + void clearBit(uint8_t byte, uint8_t bitmask); + uint8_t getBit(uint8_t byte, uint8_t bitmask); + IRsend _irsend; +}; + +#endif // IR_DAIKIN_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Denon.cpp similarity index 59% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Denon.cpp index 538e5af10..6798e022e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Denon.cpp @@ -4,7 +4,6 @@ #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // DDDD EEEEE N N OOO N N @@ -19,25 +18,25 @@ // Constants // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp -#define DENON_TICK 263U -#define DENON_HDR_MARK_TICKS 1U -#define DENON_HDR_MARK (DENON_HDR_MARK_TICKS * DENON_TICK) -#define DENON_HDR_SPACE_TICKS 3U -#define DENON_HDR_SPACE (DENON_HDR_SPACE_TICKS * DENON_TICK) -#define DENON_BIT_MARK_TICKS 1U -#define DENON_BIT_MARK (DENON_BIT_MARK_TICKS * DENON_TICK) -#define DENON_ONE_SPACE_TICKS 7U -#define DENON_ONE_SPACE (DENON_ONE_SPACE_TICKS * DENON_TICK) -#define DENON_ZERO_SPACE_TICKS 3U -#define DENON_ZERO_SPACE (DENON_ZERO_SPACE_TICKS * DENON_TICK) -#define DENON_MIN_COMMAND_LENGTH_TICKS 510U -#define DENON_MIN_COMMAND_LENGTH (DENON_MIN_COMMAND_LENGTH_TICKS * DENON_TICK) -#define DENON_MIN_GAP_TICKS (DENON_MIN_COMMAND_LENGTH_TICKS - \ - (DENON_HDR_MARK_TICKS + DENON_HDR_SPACE_TICKS + \ - DENON_BITS * (DENON_BIT_MARK_TICKS + DENON_ONE_SPACE_TICKS) + \ - DENON_BIT_MARK_TICKS)) -#define DENON_MIN_GAP (DENON_MIN_GAP_TICKS * DENON_TICK) -#define DENON_MANUFACTURER 0x2A4CULL +const uint16_t kDenonTick = 263; +const uint16_t kDenonHdrMarkTicks = 1; +const uint16_t kDenonHdrMark = kDenonHdrMarkTicks * kDenonTick; +const uint16_t kDenonHdrSpaceTicks = 3; +const uint16_t kDenonHdrSpace = kDenonHdrSpaceTicks * kDenonTick; +const uint16_t kDenonBitMarkTicks = 1; +const uint16_t kDenonBitMark = kDenonBitMarkTicks * kDenonTick; +const uint16_t kDenonOneSpaceTicks = 7; +const uint16_t kDenonOneSpace = kDenonOneSpaceTicks * kDenonTick; +const uint16_t kDenonZeroSpaceTicks = 3; +const uint16_t kDenonZeroSpace = kDenonZeroSpaceTicks * kDenonTick; +const uint16_t kDenonMinCommandLengthTicks = 510; +const uint16_t kDenonMinGapTicks = + kDenonMinCommandLengthTicks - + (kDenonHdrMarkTicks + kDenonHdrSpaceTicks + + kDenonBits * (kDenonBitMarkTicks + kDenonOneSpaceTicks) + + kDenonBitMarkTicks); +const uint32_t kDenonMinGap = kDenonMinGapTicks * kDenonTick; +const uint64_t kDenonManufacturer = 0x2A4CULL; #if SEND_DENON // Send a Denon message @@ -56,9 +55,9 @@ // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp // http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls void IRsend::sendDenon(uint64_t data, uint16_t nbits, uint16_t repeat) { - if (nbits >= PANASONIC_BITS) // Is this really Panasonic? + if (nbits >= kPanasonicBits) // Is this really Panasonic? sendPanasonic64(data, nbits, repeat); - else if (nbits == DENON_LEGACY_BITS) + else if (nbits == kDenonLegacyBits) // Support legacy (broken) calls of sendDenon(). sendSharpRaw(data & (~0x2000ULL), nbits + 1, repeat); else @@ -85,7 +84,7 @@ bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) { switch (nbits) { case DENON_BITS: case DENON_48_BITS: - case DENON_LEGACY_BITS: + case kDenonLegacyBits: break; default: return false; @@ -100,40 +99,36 @@ bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) { // manufacturer code. if (!decodeSharp(results, nbits, true, false) && - !decodePanasonic(results, nbits, true, DENON_MANUFACTURER)) { + !decodePanasonic(results, nbits, true, kDenonManufacturer)) { // We couldn't decode it as expected, so try the old legacy method. // NOTE: I don't think this following protocol actually exists. // Looks like a partial version of the Sharp protocol. // Check we have enough data - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) - return false; - if (strict && nbits != DENON_LEGACY_BITS) - return false; + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; + if (strict && nbits != kDenonLegacyBits) return false; uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // Header - if (!matchMark(results->rawbuf[offset], DENON_HDR_MARK)) return false; + if (!matchMark(results->rawbuf[offset], kDenonHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - DENON_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], DENON_HDR_SPACE)) return false; - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - DENON_HDR_SPACE_TICKS; + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kDenonHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kDenonHdrSpace)) return false; + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kDenonHdrSpaceTicks; // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - DENON_BIT_MARK_TICKS * m_tick, - DENON_ONE_SPACE_TICKS * s_tick, - DENON_BIT_MARK_TICKS * m_tick, - DENON_ZERO_SPACE_TICKS * s_tick); + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, + kDenonBitMarkTicks * m_tick, kDenonOneSpaceTicks * s_tick, + kDenonBitMarkTicks * m_tick, kDenonZeroSpaceTicks * s_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer - if (!matchMark(results->rawbuf[offset++], DENON_BIT_MARK_TICKS * m_tick)) + if (!matchMark(results->rawbuf[offset++], kDenonBitMarkTicks * m_tick)) return false; // Success diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Dish.cpp similarity index 59% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Dish.cpp index 4555db92f..040aa3bf7 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Dish.cpp @@ -3,7 +3,6 @@ #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // DDDD IIIII SSSS H H @@ -19,19 +18,19 @@ // Ref: // https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Dish.cpp // http://www.hifi-remote.com/wiki/index.php?title=Dish -#define DISH_TICK 100U -#define DISH_HDR_MARK_TICKS 4U -#define DISH_HDR_MARK (DISH_HDR_MARK_TICKS * DISH_TICK) -#define DISH_HDR_SPACE_TICKS 61U -#define DISH_HDR_SPACE (DISH_HDR_SPACE_TICKS * DISH_TICK) -#define DISH_BIT_MARK_TICKS 4U -#define DISH_BIT_MARK (DISH_BIT_MARK_TICKS * DISH_TICK) -#define DISH_ONE_SPACE_TICKS 17U -#define DISH_ONE_SPACE (DISH_ONE_SPACE_TICKS * DISH_TICK) -#define DISH_ZERO_SPACE_TICKS 28U -#define DISH_ZERO_SPACE (DISH_ZERO_SPACE_TICKS * DISH_TICK) -#define DISH_RPT_SPACE_TICKS DISH_HDR_SPACE_TICKS -#define DISH_RPT_SPACE (DISH_RPT_SPACE_TICKS * DISH_TICK) +const uint16_t kDishTick = 100; +const uint16_t kDishHdrMarkTicks = 4; +const uint16_t kDishHdrMark = kDishHdrMarkTicks * kDishTick; +const uint16_t kDishHdrSpaceTicks = 61; +const uint16_t kDishHdrSpace = kDishHdrSpaceTicks * kDishTick; +const uint16_t kDishBitMarkTicks = 4; +const uint16_t kDishBitMark = kDishBitMarkTicks * kDishTick; +const uint16_t kDishOneSpaceTicks = 17; +const uint16_t kDishOneSpace = kDishOneSpaceTicks * kDishTick; +const uint16_t kDishZeroSpaceTicks = 28; +const uint16_t kDishZeroSpace = kDishZeroSpaceTicks * kDishTick; +const uint16_t kDishRptSpaceTicks = kDishHdrSpaceTicks; +const uint16_t kDishRptSpace = kDishRptSpaceTicks * kDishTick; #if SEND_DISH // Send an IR command to a DISH NETWORK device. @@ -56,20 +55,15 @@ // Ref: // http://www.hifi-remote.com/wiki/index.php?title=Dish void IRsend::sendDISH(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 57.6kHz IR carrier frequency, duty cycle is unknown. - enableIROut(57600); - // Header - mark(DISH_HDR_MARK); - space(DISH_HDR_SPACE); - // We always send a command, even for repeat=0, hence '<= repeat'. - for (uint16_t i = 0; i <= repeat; i++) { - // Data - sendData(DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, - data, nbits, true); - // Footer - mark(DISH_BIT_MARK); - space(DISH_RPT_SPACE); - } + enableIROut(57600); // Set modulation freq. to 57.6kHz. + // Header is only ever sent once. + mark(kDishHdrMark); + space(kDishHdrSpace); + + sendGeneric(0, 0, // No headers from here on in. + kDishBitMark, kDishOneSpace, kDishBitMark, kDishZeroSpace, + kDishBitMark, kDishRptSpace, data, nbits, 57600, true, repeat, + 50); } #endif @@ -78,7 +72,7 @@ void IRsend::sendDISH(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. Typically DISH_BITS. +// nbits: Nr. of bits to expect in the data portion. Typically kDishBits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: // boolean: True if it can decode it, false if it can't. @@ -94,34 +88,32 @@ void IRsend::sendDISH(uint64_t data, uint16_t nbits, uint16_t repeat) { // http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx // https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Dish.cpp bool IRrecv::decodeDISH(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; // Not enough entries to be valid. - if (strict && nbits != DISH_BITS) - return false; // Not strictly compliant. + if (strict && nbits != kDishBits) return false; // Not strictly compliant. uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // Header - if (!match(results->rawbuf[offset], DISH_HDR_MARK)) return false; + if (!match(results->rawbuf[offset], kDishHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / DISH_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], DISH_HDR_SPACE)) return false; + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kDishHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kDishHdrSpace)) return false; // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / DISH_HDR_SPACE_TICKS; + uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kDishHdrSpaceTicks; // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - DISH_BIT_MARK_TICKS * m_tick, - DISH_ONE_SPACE_TICKS * s_tick, - DISH_BIT_MARK_TICKS * m_tick, - DISH_ZERO_SPACE_TICKS * s_tick); + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kDishBitMarkTicks * m_tick, + kDishOneSpaceTicks * s_tick, kDishBitMarkTicks * m_tick, + kDishZeroSpaceTicks * s_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer - if (!matchMark(results->rawbuf[offset++], DISH_BIT_MARK_TICKS * m_tick)) + if (!matchMark(results->rawbuf[offset++], kDishBitMarkTicks * m_tick)) return false; // Compliance @@ -129,7 +121,7 @@ bool IRrecv::decodeDISH(decode_results *results, uint16_t nbits, bool strict) { // The DISH protocol calls for a repeated message, so strictly speaking // there should be a code following this. Only require it if we are set to // strict matching. - if (!matchSpace(results->rawbuf[offset], DISH_RPT_SPACE_TICKS * s_tick)) + if (!matchSpace(results->rawbuf[offset], kDishRptSpaceTicks * s_tick)) return false; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp new file mode 100644 index 000000000..df69be748 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp @@ -0,0 +1,112 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// EEEEEEE LL EEEEEEE CCCCC TTTTTTT RRRRRR AAA +// EE LL EE CC C TTT RR RR AAAAA +// EEEEE LL EEEEE CC TTT RRRRRR AA AA +// EE LL EE CC C TTT RR RR AAAAAAA +// EEEEEEE LLLLLLL EEEEEEE CCCCC TTT RR RR AA AA + +// Electra A/C added by crankyoldgit +// +// Equipment it seems compatible with: +// * + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/527 + +// Constants +const uint16_t kElectraAcHdrMark = 9166; +const uint16_t kElectraAcBitMark = 646; +const uint16_t kElectraAcHdrSpace = 4470; +const uint16_t kElectraAcOneSpace = 1647; +const uint16_t kElectraAcZeroSpace = 547; +const uint32_t kElectraAcMessageGap = 100000; // Completely made-up guess. + +#if SEND_ELECTRA_AC +// Send a Electra message +// +// Args: +// data: Contents of the message to be sent. (Guessing MSBF order) +// nbits: Nr. of bits of data to be sent. Typically kElectraAcBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: Alpha / Needs testing against a real device. +// +void IRsend::sendElectraAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) { + for (uint16_t r = 0; r <= repeat; r++) + sendGeneric(kElectraAcHdrMark, kElectraAcHdrSpace, kElectraAcBitMark, + kElectraAcOneSpace, kElectraAcBitMark, kElectraAcZeroSpace, + kElectraAcBitMark, kElectraAcMessageGap, data, nbytes, + 38000, // Complete guess of the modulation frequency. + true, 0, 50); +} +#endif + +#if DECODE_ELECTRA_AC +// Decode the supplied Electra A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kElectraAcBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Needs testing against a real device. +// +bool IRrecv::decodeElectraAC(decode_results *results, uint16_t nbits, + bool strict) { + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + if (strict) { + if (nbits != kElectraAcBits) + return false; // Not strictly a ELECTRA_AC message. + } + + // The protocol sends the data normal + inverted, alternating on + // each byte. Hence twice the number of expected data bits. + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid ELECTRA_AC message. + + uint16_t offset = kStartOffset; + + // Message Header + if (!matchMark(results->rawbuf[offset++], kElectraAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kElectraAcHdrSpace)) return false; + + // Data Section + match_result_t data_result; + uint16_t dataBitsSoFar = 0; + // Keep reading bytes until we either run out of section or state to fill. + for (uint16_t i = 0; offset <= results->rawlen - 16 && i < nbits / 8; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData(&(results->rawbuf[offset]), 8, kElectraAcBitMark, + kElectraAcOneSpace, kElectraAcBitMark, + kElectraAcZeroSpace, kTolerance, 0, true); + if (data_result.success == false) return false; // Fail + results->state[i] = data_result.data; + } + + // Message Footer + if (!matchMark(results->rawbuf[offset++], kElectraAcBitMark)) return false; + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kElectraAcMessageGap)) + return false; + + // Compliance + if (strict && dataBitsSoFar != nbits) return false; + + // Success + results->decode_type = ELECTRA_AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_ELECTRA_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp new file mode 100644 index 000000000..7c1b99834 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp @@ -0,0 +1,519 @@ +// Copyright 2017 Jonny Graham, David Conran +#include "ir_Fujitsu.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRsend.h" +#include "IRutils.h" + +// Fujitsu A/C support added by Jonny Graham & David Conran + +// Equipment it seems compatible with: +// * Fujitsu ASYG30LFCA with remote AR-RAH2E +// * Fujitsu AST9RSGCW with remote AR-DB1 +// * + +// Ref: +// These values are based on averages of measurements +const uint16_t kFujitsuAcHdrMark = 3324; +const uint16_t kFujitsuAcHdrSpace = 1574; +const uint16_t kFujitsuAcBitMark = 448; +const uint16_t kFujitsuAcOneSpace = 1182; +const uint16_t kFujitsuAcZeroSpace = 390; +const uint16_t kFujitsuAcMinGap = 8100; + +#if SEND_FUJITSU_AC +// Send a Fujitsu A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. Typically one of: +// kFujitsuAcStateLength +// kFujitsuAcStateLength - 1 +// kFujitsuAcStateLengthShort +// kFujitsuAcStateLengthShort - 1 +// repeat: Nr. of times the message is to be repeated. +// (Default = kFujitsuAcMinRepeat). +// +// Status: BETA / Appears to be working. +// +void IRsend::sendFujitsuAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + sendGeneric(kFujitsuAcHdrMark, kFujitsuAcHdrSpace, kFujitsuAcBitMark, + kFujitsuAcOneSpace, kFujitsuAcBitMark, kFujitsuAcZeroSpace, + kFujitsuAcBitMark, kFujitsuAcMinGap, data, nbytes, 38, false, + repeat, 50); +} +#endif // SEND_FUJITSU_AC + +// Code to emulate Fujitsu A/C IR remote control unit. + +// Initialise the object. +IRFujitsuAC::IRFujitsuAC(uint16_t pin, fujitsu_ac_remote_model_t model) + : _irsend(pin) { + setModel(model); + stateReset(); +} + +void IRFujitsuAC::setModel(fujitsu_ac_remote_model_t model) { + _model = model; + switch (model) { + case ARDB1: + _state_length = kFujitsuAcStateLength - 1; + _state_length_short = kFujitsuAcStateLengthShort - 1; + break; + default: + _state_length = kFujitsuAcStateLength; + _state_length_short = kFujitsuAcStateLengthShort; + } +} + +// Reset the state of the remote to a known good state/sequence. +void IRFujitsuAC::stateReset() { + _temp = 24; + _fanSpeed = kFujitsuAcFanHigh; + _mode = kFujitsuAcModeCool; + _swingMode = kFujitsuAcSwingBoth; + _cmd = kFujitsuAcCmdTurnOn; + buildState(); +} + +// Configure the pin for output. +void IRFujitsuAC::begin() { _irsend.begin(); } + +#if SEND_FUJITSU_AC +// Send the current desired state to the IR LED. +void IRFujitsuAC::send() { + getRaw(); + _irsend.sendFujitsuAC(remote_state, getStateLength()); +} +#endif // SEND_FUJITSU_AC + +void IRFujitsuAC::buildState() { + remote_state[0] = 0x14; + remote_state[1] = 0x63; + remote_state[2] = 0x00; + remote_state[3] = 0x10; + remote_state[4] = 0x10; + bool fullCmd = false; + switch (_cmd) { + case kFujitsuAcCmdTurnOff: + remote_state[5] = 0x02; + break; + case kFujitsuAcCmdStepHoriz: + remote_state[5] = 0x79; + break; + case kFujitsuAcCmdStepVert: + remote_state[5] = 0x6C; + break; + default: + switch (_model) { + case ARRAH2E: + remote_state[5] = 0xFE; + break; + case ARDB1: + remote_state[5] = 0xFC; + break; + } + fullCmd = true; + break; + } + if (fullCmd) { // long codes + uint8_t tempByte = _temp - kFujitsuAcMinTemp; + // Nr. of bytes in the message after this byte. + remote_state[6] = _state_length - 7; + + remote_state[7] = 0x30; + remote_state[8] = (_cmd == kFujitsuAcCmdTurnOn) | (tempByte << 4); + remote_state[9] = _mode | 0 << 4; // timer off + remote_state[10] = _fanSpeed | _swingMode << 4; + remote_state[11] = 0; // timerOff values + remote_state[12] = 0; // timerOff/On values + remote_state[13] = 0; // timerOn values + if (_model == ARRAH2E) + remote_state[14] = 0x20; + else + remote_state[14] = 0x00; + + uint8_t checksum = 0; + uint8_t checksum_complement = 0; + if (_model == ARRAH2E) { + checksum = sumBytes(remote_state + _state_length_short, + _state_length - _state_length_short - 1); + } else if (_model == ARDB1) { + checksum = sumBytes(remote_state, _state_length - 1); + checksum_complement = 0x9B; + } + // and negate the checksum and store it in the last byte. + remote_state[_state_length - 1] = checksum_complement - checksum; + } else { // short codes + if (_model == ARRAH2E) + // The last byte is the inverse of penultimate byte + remote_state[_state_length_short - 1] = + ~remote_state[_state_length_short - 2]; + // Zero the rest of the state. + for (uint8_t i = _state_length_short; i < kFujitsuAcStateLength; i++) + remote_state[i] = 0; + } +} + +uint8_t IRFujitsuAC::getStateLength() { + buildState(); // Force an update of the internal state. + if ((_model == ARRAH2E && remote_state[5] != 0xFE) || + (_model == ARDB1 && remote_state[5] != 0xFC)) + return _state_length_short; + else + return _state_length; +} + +// Return a pointer to the internal state date of the remote. +uint8_t* IRFujitsuAC::getRaw() { + buildState(); + return remote_state; +} + +void IRFujitsuAC::buildFromState(const uint16_t length) { + switch (length) { + case kFujitsuAcStateLength - 1: + case kFujitsuAcStateLengthShort - 1: + setModel(ARDB1); + break; + default: + setModel(ARRAH2E); + } + switch (remote_state[6]) { + case 8: + setModel(ARDB1); + break; + case 9: + setModel(ARRAH2E); + break; + } + setTemp((remote_state[8] >> 4) + kFujitsuAcMinTemp); + if (remote_state[8] & 0x1) + setCmd(kFujitsuAcCmdTurnOn); + else + setCmd(kFujitsuAcCmdStayOn); + setMode(remote_state[9] & 0b111); + setFanSpeed(remote_state[10] & 0b111); + setSwing(remote_state[10] >> 4); + switch (remote_state[5]) { + case kFujitsuAcCmdTurnOff: + case kFujitsuAcCmdStepHoriz: + case kFujitsuAcCmdStepVert: + setCmd(remote_state[5]); + break; + } +} + +bool IRFujitsuAC::setRaw(const uint8_t newState[], const uint16_t length) { + if (length > kFujitsuAcStateLength) return false; + for (uint16_t i = 0; i < kFujitsuAcStateLength; i++) { + if (i < length) + remote_state[i] = newState[i]; + else + remote_state[i] = 0; + } + buildFromState(length); + return true; +} + +// Set the requested power state of the A/C to off. +void IRFujitsuAC::off() { _cmd = kFujitsuAcCmdTurnOff; } + +void IRFujitsuAC::stepHoriz() { + switch (_model) { + case ARDB1: + break; // This remote doesn't have a horizontal option. + default: + _cmd = kFujitsuAcCmdStepHoriz; + } +} + +void IRFujitsuAC::stepVert() { _cmd = kFujitsuAcCmdStepVert; } + +// Set the requested command of the A/C. +void IRFujitsuAC::setCmd(uint8_t cmd) { + switch (cmd) { + case kFujitsuAcCmdTurnOff: + case kFujitsuAcCmdTurnOn: + case kFujitsuAcCmdStayOn: + case kFujitsuAcCmdStepVert: + _cmd = cmd; + break; + case kFujitsuAcCmdStepHoriz: + if (_model != ARDB1) // AR-DB1 remote doesn't have step horizontal. + _cmd = cmd; + // FALLTHRU + default: + _cmd = kFujitsuAcCmdStayOn; + break; + } +} + +uint8_t IRFujitsuAC::getCmd() { return _cmd; } + +bool IRFujitsuAC::getPower() { return _cmd != kFujitsuAcCmdTurnOff; } + +// Set the temp. in deg C +void IRFujitsuAC::setTemp(uint8_t temp) { + temp = std::max((uint8_t)kFujitsuAcMinTemp, temp); + temp = std::min((uint8_t)kFujitsuAcMaxTemp, temp); + _temp = temp; +} + +uint8_t IRFujitsuAC::getTemp() { return _temp; } + +// Set the speed of the fan +void IRFujitsuAC::setFanSpeed(uint8_t fanSpeed) { + if (fanSpeed > kFujitsuAcFanQuiet) + fanSpeed = kFujitsuAcFanHigh; // Set the fan to maximum if out of range. + _fanSpeed = fanSpeed; +} +uint8_t IRFujitsuAC::getFanSpeed() { return _fanSpeed; } + +// Set the requested climate operation mode of the a/c unit. +void IRFujitsuAC::setMode(uint8_t mode) { + if (mode > kFujitsuAcModeHeat) + mode = kFujitsuAcModeHeat; // Set the mode to maximum if out of range. + _mode = mode; +} + +uint8_t IRFujitsuAC::getMode() { return _mode; } +// Set the requested swing operation mode of the a/c unit. +void IRFujitsuAC::setSwing(uint8_t swingMode) { + switch (_model) { + case ARDB1: + // Set the mode to max if out of range + if (swingMode > kFujitsuAcSwingVert) swingMode = kFujitsuAcSwingVert; + break; + case ARRAH2E: + default: + // Set the mode to max if out of range + if (swingMode > kFujitsuAcSwingBoth) swingMode = kFujitsuAcSwingBoth; + } + _swingMode = swingMode; +} + +uint8_t IRFujitsuAC::getSwing() { return _swingMode; } + +bool IRFujitsuAC::validChecksum(uint8_t state[], uint16_t length) { + uint8_t sum = 0; + uint8_t sum_complement = 0; + uint8_t checksum = state[length - 1]; + switch (length) { + case kFujitsuAcStateLengthShort: // ARRAH2E + return state[length - 1] == (uint8_t)~state[length - 2]; + case kFujitsuAcStateLength - 1: // ARDB1 + sum = sumBytes(state, length - 1); + sum_complement = 0x9B; + break; + case kFujitsuAcStateLength: // ARRAH2E + sum = sumBytes(state + kFujitsuAcStateLengthShort, + length - 1 - kFujitsuAcStateLengthShort); + break; + default: // Includes ARDB1 short. + return true; // Assume the checksum is valid for other lengths. + } + return checksum == (uint8_t)(sum_complement - sum); // Does it match? +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRFujitsuAC::toString() { + String result = ""; +#else +std::string IRFujitsuAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kFujitsuAcModeAuto: + result += " (AUTO)"; + break; + case kFujitsuAcModeCool: + result += " (COOL)"; + break; + case kFujitsuAcModeHeat: + result += " (HEAT)"; + break; + case kFujitsuAcModeDry: + result += " (DRY)"; + break; + case kFujitsuAcModeFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFanSpeed()); + switch (getFanSpeed()) { + case kFujitsuAcFanAuto: + result += " (AUTO)"; + break; + case kFujitsuAcFanHigh: + result += " (HIGH)"; + break; + case kFujitsuAcFanMed: + result += " (MED)"; + break; + case kFujitsuAcFanLow: + result += " (LOW)"; + break; + case kFujitsuAcFanQuiet: + result += " (QUIET)"; + break; + } + result += ", Swing: "; + switch (getSwing()) { + case kFujitsuAcSwingOff: + result += "Off"; + break; + case kFujitsuAcSwingVert: + result += "Vert"; + break; + case kFujitsuAcSwingHoriz: + result += "Horiz"; + break; + case kFujitsuAcSwingBoth: + result += "Vert + Horiz"; + break; + default: + result += "UNKNOWN"; + } + result += ", Command: "; + switch (getCmd()) { + case kFujitsuAcCmdStepHoriz: + result += "Step vane horizontally"; + break; + case kFujitsuAcCmdStepVert: + result += "Step vane vertically"; + break; + default: + result += "N/A"; + } + return result; +} + +#if DECODE_FUJITSU_AC +// Decode a Fujitsu AC IR message if possible. +// Places successful decode information in the results pointer. +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kFujitsuAcBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +// Ref: +// +bool IRrecv::decodeFujitsuAC(decode_results* results, uint16_t nbits, + bool strict) { + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + + // Have we got enough data to successfully decode? + if (results->rawlen < (2 * kFujitsuAcMinBits) + kHeader + kFooter - 1) + return false; // Can't possibly be a valid message. + + // Compliance + if (strict) { + switch (nbits) { + case kFujitsuAcBits: + case kFujitsuAcBits - 8: + case kFujitsuAcMinBits: + case kFujitsuAcMinBits + 8: + break; + default: + return false; // Must be called with the correct nr. of bits. + } + } + + // Header + if (!matchMark(results->rawbuf[offset++], kFujitsuAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kFujitsuAcHdrSpace)) return false; + + // Data (Fixed signature) + match_result_t data_result = + matchData(&(results->rawbuf[offset]), kFujitsuAcMinBits - 8, + kFujitsuAcBitMark, kFujitsuAcOneSpace, kFujitsuAcBitMark, + kFujitsuAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; // Fail + if (data_result.data != 0x1010006314) return false; // Signature failed. + dataBitsSoFar += kFujitsuAcMinBits - 8; + offset += data_result.used; + results->state[0] = 0x14; + results->state[1] = 0x63; + results->state[2] = 0x00; + results->state[3] = 0x10; + results->state[4] = 0x10; + + // Keep reading bytes until we either run out of message or state to fill. + for (uint16_t i = 5; + offset <= results->rawlen - 16 && i < kFujitsuAcStateLength; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData( + &(results->rawbuf[offset]), 8, kFujitsuAcBitMark, kFujitsuAcOneSpace, + kFujitsuAcBitMark, kFujitsuAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) break; // Fail + results->state[i] = data_result.data; + } + + // Footer + if (offset > results->rawlen || + !matchMark(results->rawbuf[offset++], kFujitsuAcBitMark)) + return false; + // The space is optional if we are out of capture. + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kFujitsuAcMinGap)) + return false; + + // Compliance + if (strict) { + if (dataBitsSoFar != nbits) return false; + } + + results->decode_type = FUJITSU_AC; + results->bits = dataBitsSoFar; + + // Compliance + switch (dataBitsSoFar) { + case kFujitsuAcMinBits: + // Check if this values indicate that this should have been a long state + // message. + if (results->state[5] == 0xFC) return false; + return true; // Success + case kFujitsuAcMinBits + 8: + // Check if this values indicate that this should have been a long state + // message. + if (results->state[5] == 0xFE) return false; + // The last byte needs to be the inverse of the penultimate byte. + if (results->state[5] != (uint8_t)~results->state[6]) return false; + return true; // Success + case kFujitsuAcBits - 8: + // Long messages of this size require this byte be correct. + if (results->state[5] != 0xFC) return false; + break; + case kFujitsuAcBits: + // Long messages of this size require this byte be correct. + if (results->state[5] != 0xFE) return false; + break; + default: + return false; // Unexpected size. + } + if (!IRFujitsuAC::validChecksum(results->state, dataBitsSoFar / 8)) + return false; + + // Success + return true; // All good. +} +#endif // DECODE_FUJITSU_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h new file mode 100644 index 000000000..bba634be6 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h @@ -0,0 +1,123 @@ +// Copyright 2017 Jonny Graham +// Copyright 2018 David Conran +#ifndef IR_FUJITSU_H_ +#define IR_FUJITSU_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef ARDUINO +#include +#else +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// FUJITSU A/C support added by Jonny Graham + +// Constants +const uint8_t kFujitsuAcModeAuto = 0x00; +const uint8_t kFujitsuAcModeCool = 0x01; +const uint8_t kFujitsuAcModeDry = 0x02; +const uint8_t kFujitsuAcModeFan = 0x03; +const uint8_t kFujitsuAcModeHeat = 0x04; + +const uint8_t kFujitsuAcCmdStayOn = 0x00; +const uint8_t kFujitsuAcCmdTurnOn = 0x01; +const uint8_t kFujitsuAcCmdTurnOff = 0x02; +const uint8_t kFujitsuAcCmdStepHoriz = 0x79; +const uint8_t kFujitsuAcCmdStepVert = 0x6C; + +const uint8_t kFujitsuAcFanAuto = 0x00; +const uint8_t kFujitsuAcFanHigh = 0x01; +const uint8_t kFujitsuAcFanMed = 0x02; +const uint8_t kFujitsuAcFanLow = 0x03; +const uint8_t kFujitsuAcFanQuiet = 0x04; + +const uint8_t kFujitsuAcMinTemp = 16; // 16C +const uint8_t kFujitsuAcMaxTemp = 30; // 30C + +const uint8_t kFujitsuAcSwingOff = 0x00; +const uint8_t kFujitsuAcSwingVert = 0x01; +const uint8_t kFujitsuAcSwingHoriz = 0x02; +const uint8_t kFujitsuAcSwingBoth = 0x03; + +// Legacy defines. +#define FUJITSU_AC_MODE_AUTO kFujitsuAcModeAuto +#define FUJITSU_AC_MODE_COOL kFujitsuAcModeCool +#define FUJITSU_AC_MODE_DRY kFujitsuAcModeDry +#define FUJITSU_AC_MODE_FAN kFujitsuAcModeFan +#define FUJITSU_AC_MODE_HEAT kFujitsuAcModeHeat +#define FUJITSU_AC_CMD_STAY_ON kFujitsuAcCmdStayOn +#define FUJITSU_AC_CMD_TURN_ON kFujitsuAcCmdTurnOn +#define FUJITSU_AC_CMD_TURN_OFF kFujitsuAcCmdTurnOff +#define FUJITSU_AC_CMD_STEP_HORIZ kFujitsuAcCmdStepHoriz +#define FUJITSU_AC_CMD_STEP_VERT kFujitsuAcCmdStepVert +#define FUJITSU_AC_FAN_AUTO kFujitsuAcFanAuto +#define FUJITSU_AC_FAN_HIGH kFujitsuAcFanHigh +#define FUJITSU_AC_FAN_MED kFujitsuAcFanMed +#define FUJITSU_AC_FAN_LOW kFujitsuAcFanLow +#define FUJITSU_AC_FAN_QUIET kFujitsuAcFanQuiet +#define FUJITSU_AC_MIN_TEMP kFujitsuAcMinTemp +#define FUJITSU_AC_MAX_TEMP kFujitsuAcMaxTemp +#define FUJITSU_AC_SWING_OFF kFujitsuAcSwingOff +#define FUJITSU_AC_SWING_VERT kFujitsuAcSwingVert +#define FUJITSU_AC_SWING_HORIZ kFujitsuAcSwingHoriz +#define FUJITSU_AC_SWING_BOTH kFujitsuAcSwingBoth + +enum fujitsu_ac_remote_model_t { + ARRAH2E = 1, + ARDB1, +}; + +class IRFujitsuAC { + public: + explicit IRFujitsuAC(uint16_t pin, fujitsu_ac_remote_model_t model = ARRAH2E); + + void setModel(fujitsu_ac_remote_model_t model); + void stateReset(); +#if SEND_FUJITSU_AC + void send(); +#endif // SEND_FUJITSU_AC + void begin(); + void off(); + void stepHoriz(); + void stepVert(); + void setCmd(uint8_t cmd); + uint8_t getCmd(); + void setTemp(uint8_t temp); + uint8_t getTemp(); + void setFanSpeed(uint8_t fan); + uint8_t getFanSpeed(); + void setMode(uint8_t mode); + uint8_t getMode(); + void setSwing(uint8_t mode); + uint8_t getSwing(); + uint8_t* getRaw(); + bool setRaw(const uint8_t newState[], const uint16_t length); + uint8_t getStateLength(); + static bool validChecksum(uint8_t* state, uint16_t length); + bool getPower(); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + uint8_t remote_state[kFujitsuAcStateLength]; + IRsend _irsend; + uint8_t _temp; + uint8_t _fanSpeed; + uint8_t _mode; + uint8_t _swingMode; + uint8_t _cmd; + fujitsu_ac_remote_model_t _model; + uint8_t _state_length; + uint8_t _state_length_short; + void buildState(); + void buildFromState(const uint16_t length); +}; + +#endif // IR_FUJITSU_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp new file mode 100644 index 000000000..229e4e5bb --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp @@ -0,0 +1,116 @@ +// Copyright 2018 David Conran + +#define __STDC_LIMIT_MACROS +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// GGGG IIIII CCCCC AAA BBBBB LL EEEEEEE +// GG GG III CC C AAAAA BB B LL EE +// GG III CC AA AA BBBBBB LL EEEEE +// GG GG ... III ... CC C AAAAAAA BB BB LL EE +// GGGGGG ... IIIII ... CCCCC AA AA BBBBBB LLLLLLL EEEEEEE +// +// Ref: +// https://github.com/cyborg5/IRLib2/blob/master/IRLibProtocols/IRLib_P09_GICable.h +// https://github.com/markszabo/IRremoteESP8266/issues/447 + +// Constants +const uint16_t kGicableHdrMark = 9000; +const uint16_t kGicableHdrSpace = 4400; +const uint16_t kGicableBitMark = 550; +const uint16_t kGicableOneSpace = 4400; +const uint16_t kGicableZeroSpace = 2200; +const uint16_t kGicableRptSpace = 2200; +const uint32_t kGicableMinCommandLength = 99600; +const uint32_t kGicableMinGap = + kGicableMinCommandLength - + (kGicableHdrMark + kGicableHdrSpace + + kGicableBits * (kGicableBitMark + kGicableOneSpace) + kGicableBitMark); + +#if SEND_GICABLE +// Send a raw G.I. Cable formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The number of bits of the message to be sent. +// Typically kGicableBits. +// repeat: The number of times the command is to be repeated. +// +// Status: Alpha / Untested. +// +// Ref: +void IRsend::sendGICable(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kGicableHdrMark, kGicableHdrSpace, kGicableBitMark, + kGicableOneSpace, kGicableBitMark, kGicableZeroSpace, + kGicableBitMark, kGicableMinGap, kGicableMinCommandLength, data, + nbits, 39, true, 0, // Repeats are handled later. + 50); + // Message repeat sequence. + if (repeat) + sendGeneric(kGicableHdrMark, kGicableRptSpace, 0, 0, 0, + 0, // No actual data sent. + kGicableBitMark, kGicableMinGap, kGicableMinCommandLength, 0, + 0, // No data to be sent. + 39, true, repeat - 1, 50); +} +#endif // SEND_GICABLE + +#if DECODE_GICABLE +// Decode the supplied G.I. Cable message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kGicableBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Not tested against a real device. +bool IRrecv::decodeGICable(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1) + return false; // Can't possibly be a valid GICABLE message. + if (strict && nbits != kGicableBits) + return false; // Not strictly an GICABLE message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset++], kGicableHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kGicableHdrSpace)) return false; + + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kGicableBitMark, + kGicableOneSpace, kGicableBitMark, kGicableZeroSpace); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Footer + if (!matchMark(results->rawbuf[offset++], kGicableBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kGicableMinGap)) + return false; + + // Compliance + if (strict) { + // We expect a repeat frame. + if (!matchMark(results->rawbuf[offset++], kGicableHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kGicableRptSpace)) return false; + if (!matchMark(results->rawbuf[offset++], kGicableBitMark)) return false; + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = GICABLE; + results->command = 0; + results->address = 0; + return true; +} +#endif // DECODE_GICABLE diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_GlobalCache.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_GlobalCache.cpp similarity index 66% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_GlobalCache.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_GlobalCache.cpp index 019413b96..daa9dd22c 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_GlobalCache.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_GlobalCache.cpp @@ -3,7 +3,6 @@ #include #include "IRsend.h" -#include "IRtimer.h" // GGG L OOOO BBBB AA L CCCC AA CCCC H H EEEEEE // G G L O O B B AAAA L C C AAAA C C H H E @@ -15,12 +14,12 @@ // (http://www.hishamkhalifa.com) // Constants -#define GLOBALCACHE_MAX_REPEAT 50U -#define GLOBALCACHE_MIN_USEC 80U -#define GLOBALCACHE_FREQ_INDEX 0U -#define GLOBALCACHE_RPT_INDEX GLOBALCACHE_FREQ_INDEX + 1U -#define GLOBALCACHE_RPT_START_INDEX GLOBALCACHE_RPT_INDEX + 1U -#define GLOBALCACHE_START_INDEX GLOBALCACHE_RPT_START_INDEX + 1U +const uint16_t kGlobalCacheMaxRepeat = 50; +const uint32_t kGlobalCacheMinUsec = 80; +const uint8_t kGlobalCacheFreqIndex = 0; +const uint8_t kGlobalCacheRptIndex = kGlobalCacheFreqIndex + 1; +const uint8_t kGlobalCacheRptStartIndex = kGlobalCacheRptIndex + 1; +const uint8_t kGlobalCacheStartIndex = kGlobalCacheRptStartIndex + 1; #if SEND_GLOBALCACHE // Send a shortened GlobalCache (GC) IRdb/control tower formatted message. @@ -41,24 +40,23 @@ // Ref: // https://irdb.globalcache.com/Home/Database void IRsend::sendGC(uint16_t buf[], uint16_t len) { - uint16_t hz = buf[GLOBALCACHE_FREQ_INDEX]; // GC frequency is in Hz. + uint16_t hz = buf[kGlobalCacheFreqIndex]; // GC frequency is in Hz. enableIROut(hz); uint32_t periodic_time = calcUSecPeriod(hz, false); - uint8_t emits = std::min(buf[GLOBALCACHE_RPT_INDEX], - (uint16_t) GLOBALCACHE_MAX_REPEAT); + uint8_t emits = + std::min(buf[kGlobalCacheRptIndex], (uint16_t)kGlobalCacheMaxRepeat); // Repeat for (uint8_t repeat = 0; repeat < emits; repeat++) { - // First time through, start at the beginning (GLOBALCACHE_START_INDEX), + // First time through, start at the beginning (kGlobalCacheStartIndex), // otherwise for repeats, we start a specified offset from that. - uint16_t offset = GLOBALCACHE_START_INDEX; - if (repeat) - offset += buf[GLOBALCACHE_RPT_START_INDEX] - 1; + uint16_t offset = kGlobalCacheStartIndex; + if (repeat) offset += buf[kGlobalCacheRptStartIndex] - 1; // Data for (; offset < len; offset++) { // Convert periodic units to microseconds. - // Minimum is GLOBALCACHE_MIN_USEC for actual GC units. - uint32_t microseconds = std::max(buf[offset] * periodic_time, - GLOBALCACHE_MIN_USEC); + // Minimum is kGlobalCacheMinUsec for actual GC units. + uint32_t microseconds = + std::max(buf[offset] * periodic_time, kGlobalCacheMinUsec); // These codes start at an odd index (not even as with sendRaw). if (offset & 1) // Odd bit. mark(microseconds); diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp new file mode 100644 index 000000000..df8afada6 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp @@ -0,0 +1,478 @@ +// Copyright 2017 Ville Skyttä (scop) +// Copyright 2017, 2018 David Conran +// +// Code to emulate Gree protocol compatible HVAC devices. +// Should be compatible with: +// * Heat pumps carrying the "Ultimate" brand name. +// * EKOKAI air conditioners. +// + +#include "ir_Gree.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" +#include "ir_Kelvinator.h" + +// GGGG RRRRRR EEEEEEE EEEEEEE +// GG GG RR RR EE EE +// GG RRRRRR EEEEE EEEEE +// GG GG RR RR EE EE +// GGGGGG RR RR EEEEEEE EEEEEEE + +// Constants +// Ref: https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.h +const uint16_t kGreeHdrMark = 9000; +const uint16_t kGreeHdrSpace = 4000; +const uint16_t kGreeBitMark = 620; +const uint16_t kGreeOneSpace = 1600; +const uint16_t kGreeZeroSpace = 540; +const uint16_t kGreeMsgSpace = 19000; +const uint8_t kGreeBlockFooter = 0b010; +const uint8_t kGreeBlockFooterBits = 3; + +#if SEND_GREE +// Send a Gree Heat Pump message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kGreeStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp +void IRsend::sendGree(unsigned char data[], uint16_t nbytes, uint16_t repeat) { + if (nbytes < kGreeStateLength) + return; // Not enough bytes to send a proper message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Block #1 + sendGeneric(kGreeHdrMark, kGreeHdrSpace, kGreeBitMark, kGreeOneSpace, + kGreeBitMark, kGreeZeroSpace, 0, 0, // No Footer. + data, 4, 38, false, 0, 50); + // Footer #1 + sendGeneric(0, 0, // No Header + kGreeBitMark, kGreeOneSpace, kGreeBitMark, kGreeZeroSpace, + kGreeBitMark, kGreeMsgSpace, 0b010, 3, 38, true, 0, false); + + // Block #2 + sendGeneric(0, 0, // No Header for Block #2 + kGreeBitMark, kGreeOneSpace, kGreeBitMark, kGreeZeroSpace, + kGreeBitMark, kGreeMsgSpace, data + 4, nbytes - 4, 38, false, 0, + 50); + } +} + +// Send a Gree Heat Pump message. +// +// Args: +// data: The raw message to be sent. +// nbits: Nr. of bits of data in the message. (Default is kGreeBits) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp +void IRsend::sendGree(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits != kGreeBits) + return; // Wrong nr. of bits to send a proper message. + // Set IR carrier frequency + enableIROut(38); + + for (uint16_t r = 0; r <= repeat; r++) { + // Header + mark(kGreeHdrMark); + space(kGreeHdrSpace); + + // Data + for (int16_t i = 8; i <= nbits; i += 8) { + sendData(kGreeBitMark, kGreeOneSpace, kGreeBitMark, kGreeZeroSpace, + (data >> (nbits - i)) & 0xFF, 8, false); + if (i == nbits / 2) { + // Send the mid-message Footer. + sendData(kGreeBitMark, kGreeOneSpace, kGreeBitMark, kGreeZeroSpace, + 0b010, 3); + mark(kGreeBitMark); + space(kGreeMsgSpace); + } + } + // Footer + mark(kGreeBitMark); + space(kGreeMsgSpace); + } +} +#endif // SEND_GREE + +IRGreeAC::IRGreeAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRGreeAC::stateReset() { + // This resets to a known-good state to Power Off, Fan Auto, Mode Auto, 25C. + for (uint8_t i = 0; i < kGreeStateLength; i++) remote_state[i] = 0x0; + remote_state[1] = 0x09; + remote_state[2] = 0x20; + remote_state[3] = 0x50; + remote_state[5] = 0x20; + remote_state[7] = 0x50; +} + +void IRGreeAC::fixup() { + checksum(); // Calculate the checksums +} + +void IRGreeAC::begin() { _irsend.begin(); } + +#if SEND_GREE +void IRGreeAC::send() { + fixup(); // Ensure correct settings before sending. + _irsend.sendGree(remote_state); +} +#endif // SEND_GREE + +uint8_t* IRGreeAC::getRaw() { + fixup(); // Ensure correct settings before sending. + return remote_state; +} + +void IRGreeAC::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kGreeStateLength; i++) { + remote_state[i] = new_code[i]; + } +} + +void IRGreeAC::checksum(const uint16_t length) { + // Gree uses the same checksum alg. as Kelvinator's block checksum. + uint8_t sum = IRKelvinatorAC::calcBlockChecksum(remote_state, length); + remote_state[length - 1] = (sum << 4) | (remote_state[length - 1] & 0xFU); +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRGreeAC::validChecksum(const uint8_t state[], const uint16_t length) { + // Top 4 bits of the last byte in the state is the state's checksum. + if (state[length - 1] >> 4 == + IRKelvinatorAC::calcBlockChecksum(state, length)) + return true; + else + return false; +} + +void IRGreeAC::on() { + remote_state[0] |= kGreePower1Mask; + remote_state[2] |= kGreePower2Mask; +} + +void IRGreeAC::off() { + remote_state[0] &= ~kGreePower1Mask; + remote_state[2] &= ~kGreePower2Mask; +} + +void IRGreeAC::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +bool IRGreeAC::getPower() { + return (remote_state[0] & kGreePower1Mask) && + (remote_state[2] & kGreePower2Mask); +} + +// Set the temp. in deg C +void IRGreeAC::setTemp(const uint8_t temp) { + uint8_t new_temp = std::max((uint8_t)kGreeMinTemp, temp); + new_temp = std::min((uint8_t)kGreeMaxTemp, new_temp); + if (getMode() == kGreeAuto) new_temp = 25; + remote_state[1] = (remote_state[1] & 0xF0U) | (new_temp - kGreeMinTemp); +} + +// Return the set temp. in deg C +uint8_t IRGreeAC::getTemp() { + return ((remote_state[1] & 0xFU) + kGreeMinTemp); +} + +// Set the speed of the fan, 0-3, 0 is auto, 1-3 is the speed +void IRGreeAC::setFan(const uint8_t speed) { + uint8_t fan = std::min((uint8_t)kGreeFanMax, speed); // Bounds check + + if (getMode() == kGreeDry) fan = 1; // DRY mode is always locked to fan 1. + // Set the basic fan values. + remote_state[0] &= ~kGreeFanMask; + remote_state[0] |= (fan << 4); +} + +uint8_t IRGreeAC::getFan() { return ((remote_state[0] & kGreeFanMask) >> 4); } + +void IRGreeAC::setMode(const uint8_t new_mode) { + uint8_t mode = new_mode; + switch (mode) { + case kGreeAuto: + // AUTO is locked to 25C + setTemp(25); + break; + case kGreeDry: + // DRY always sets the fan to 1. + setFan(1); + break; + case kGreeCool: + case kGreeFan: + case kGreeHeat: + break; + default: + // If we get an unexpected mode, default to AUTO. + mode = kGreeAuto; + } + remote_state[0] &= ~kGreeModeMask; + remote_state[0] |= mode; +} + +uint8_t IRGreeAC::getMode() { return (remote_state[0] & kGreeModeMask); } + +void IRGreeAC::setLight(const bool state) { + remote_state[2] &= ~kGreeLightMask; + remote_state[2] |= (state << 5); +} + +bool IRGreeAC::getLight() { return remote_state[2] & kGreeLightMask; } + +void IRGreeAC::setXFan(const bool state) { + remote_state[2] &= ~kGreeXfanMask; + remote_state[2] |= (state << 7); +} + +bool IRGreeAC::getXFan() { return remote_state[2] & kGreeXfanMask; } + +void IRGreeAC::setSleep(const bool state) { + remote_state[0] &= ~kGreeSleepMask; + remote_state[0] |= (state << 7); +} + +bool IRGreeAC::getSleep() { return remote_state[0] & kGreeSleepMask; } + +void IRGreeAC::setTurbo(const bool state) { + remote_state[2] &= ~kGreeTurboMask; + remote_state[2] |= (state << 4); +} + +bool IRGreeAC::getTurbo() { return remote_state[2] & kGreeTurboMask; } + +void IRGreeAC::setSwingVertical(const bool automatic, const uint8_t position) { + remote_state[0] &= ~kGreeSwingAutoMask; + remote_state[0] |= (automatic << 6); + uint8_t new_position = position; + if (!automatic) { + switch (position) { + case kGreeSwingUp: + case kGreeSwingMiddleUp: + case kGreeSwingMiddle: + case kGreeSwingMiddleDown: + case kGreeSwingDown: + break; + default: + new_position = kGreeSwingLastPos; + } + } else { + switch (position) { + case kGreeSwingAuto: + case kGreeSwingDownAuto: + case kGreeSwingMiddleAuto: + case kGreeSwingUpAuto: + break; + default: + new_position = kGreeSwingAuto; + } + } + remote_state[4] &= ~kGreeSwingPosMask; + remote_state[4] |= new_position; +} + +bool IRGreeAC::getSwingVerticalAuto() { + return remote_state[0] & kGreeSwingAutoMask; +} + +uint8_t IRGreeAC::getSwingVerticalPosition() { + return remote_state[4] & kGreeSwingPosMask; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRGreeAC::toString() { + String result = ""; +#else +std::string IRGreeAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kGreeAuto: + result += " (AUTO)"; + break; + case kGreeCool: + result += " (COOL)"; + break; + case kGreeHeat: + result += " (HEAT)"; + break; + case kGreeDry: + result += " (DRY)"; + break; + case kGreeFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case 0: + result += " (AUTO)"; + break; + case kGreeFanMax: + result += " (MAX)"; + break; + } + result += ", Turbo: "; + if (getTurbo()) + result += "On"; + else + result += "Off"; + result += ", XFan: "; + if (getXFan()) + result += "On"; + else + result += "Off"; + result += ", Light: "; + if (getLight()) + result += "On"; + else + result += "Off"; + result += ", Sleep: "; + if (getSleep()) + result += "On"; + else + result += "Off"; + result += ", Swing Vertical Mode: "; + if (getSwingVerticalAuto()) + result += "Auto"; + else + result += "Manual"; + result += + ", Swing Vertical Pos: " + uint64ToString(getSwingVerticalPosition()); + switch (getSwingVerticalPosition()) { + case kGreeSwingLastPos: + result += " (Last Pos)"; + break; + case kGreeSwingAuto: + result += " (Auto)"; + break; + } + return result; +} + +#if DECODE_GREE +// Decode the supplied Gree message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kGreeBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +bool IRrecv::decodeGree(decode_results* results, uint16_t nbits, bool strict) { + if (results->rawlen < + 2 * (nbits + kGreeBlockFooterBits) + (kHeader + kFooter + 1)) + return false; // Can't possibly be a valid Gree message. + if (strict && nbits != kGreeBits) + return false; // Not strictly a Gree message. + + uint32_t data; + uint16_t offset = kStartOffset; + + // There are two blocks back-to-back in a full Gree IR message + // sequence. + int8_t state_pos = 0; + match_result_t data_result; + + // Header + if (!matchMark(results->rawbuf[offset++], kGreeHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kGreeHdrSpace)) return false; + // Data Block #1 (32 bits) + data_result = + matchData(&(results->rawbuf[offset]), 32, kGreeBitMark, kGreeOneSpace, + kGreeBitMark, kGreeZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Record Data Block #1 in the state. + for (uint16_t i = 0; i < 4; i++, data >>= 8) + results->state[state_pos + i] = data & 0xFF; + state_pos += 4; + + // Block #1 footer (3 bits, B010) + data_result = matchData(&(results->rawbuf[offset]), kGreeBlockFooterBits, + kGreeBitMark, kGreeOneSpace, kGreeBitMark, + kGreeZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + if (data_result.data != kGreeBlockFooter) return false; + offset += data_result.used; + + // Inter-block gap. + if (!matchMark(results->rawbuf[offset++], kGreeBitMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kGreeMsgSpace)) return false; + + // Data Block #2 (32 bits) + data_result = + matchData(&(results->rawbuf[offset]), 32, kGreeBitMark, kGreeOneSpace, + kGreeBitMark, kGreeZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Record Data Block #2 in the state. + for (uint16_t i = 0; i < 4; i++, data >>= 8) + results->state[state_pos + i] = data & 0xFF; + state_pos += 4; + + // Footer. + if (!matchMark(results->rawbuf[offset++], kGreeBitMark)) return false; + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset], kGreeMsgSpace)) + return false; + + // Compliance + if (strict) { + // Correct size/length) + if (state_pos != kGreeStateLength) return false; + // Verify the message's checksum is correct. + if (!IRGreeAC::validChecksum(results->state)) return false; + } + + // Success + results->decode_type = GREE; + results->bits = state_pos * 8; + // 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_GREE diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h new file mode 100644 index 000000000..73f69eb31 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h @@ -0,0 +1,130 @@ +// Kelvinator A/C +// +// Copyright 2016 David Conran + +#ifndef IR_GREE_H_ +#define IR_GREE_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// GGGG RRRRRR EEEEEEE EEEEEEE +// GG GG RR RR EE EE +// GG RRRRRR EEEEE EEEEE +// GG GG RR RR EE EE +// GGGGGG RR RR EEEEEEE EEEEEEE + +// Constants +const uint8_t kGreeAuto = 0; +const uint8_t kGreeCool = 1; +const uint8_t kGreeDry = 2; +const uint8_t kGreeFan = 3; +const uint8_t kGreeHeat = 4; + +// Byte 0 +const uint8_t kGreeModeMask = 0b00000111; +const uint8_t kGreePower1Mask = 0b00001000; +const uint8_t kGreeFanMask = 0b00110000; +const uint8_t kGreeSwingAutoMask = 0b01000000; +const uint8_t kGreeSleepMask = 0b10000000; +// Byte 2 +const uint8_t kGreeTurboMask = 0b00010000; +const uint8_t kGreeLightMask = 0b00100000; +const uint8_t kGreePower2Mask = 0b01000000; +const uint8_t kGreeXfanMask = 0b10000000; +// Byte 4 +const uint8_t kGreeSwingPosMask = 0b00001111; + +const uint8_t kGreeMinTemp = 16; // Celsius +const uint8_t kGreeMaxTemp = 30; // Celsius +const uint8_t kGreeFanMax = 3; + +const uint8_t kGreeSwingLastPos = 0b00000000; +const uint8_t kGreeSwingAuto = 0b00000001; +const uint8_t kGreeSwingUp = 0b00000010; +const uint8_t kGreeSwingMiddleUp = 0b00000011; +const uint8_t kGreeSwingMiddle = 0b00000100; +const uint8_t kGreeSwingMiddleDown = 0b00000101; +const uint8_t kGreeSwingDown = 0b00000110; +const uint8_t kGreeSwingDownAuto = 0b00000111; +const uint8_t kGreeSwingMiddleAuto = 0b00001001; +const uint8_t kGreeSwingUpAuto = 0b00001011; + +// Legacy defines. +#define GREE_AUTO kGreeAuto +#define GREE_COOL kGreeCool +#define GREE_DRY kGreeDry +#define GREE_FAN kGreeFan +#define GREE_HEAT kGreeHeat +#define GREE_MIN_TEMP kGreeMinTemp +#define GREE_MAX_TEMP kGreeMaxTemp +#define GREE_FAN_MAX kGreeFanMax +#define GREE_SWING_LAST_POS kGreeSwingLastPos +#define GREE_SWING_AUTO kGreeSwingAuto +#define GREE_SWING_UP kGreeSwingUp +#define GREE_SWING_MIDDLE_UP kGreeSwingMiddleUp +#define GREE_SWING_MIDDLE kGreeSwingMiddle +#define GREE_SWING_MIDDLE_DOWN kGreeSwingMiddleDown +#define GREE_SWING_DOWN kGreeSwingDown +#define GREE_SWING_DOWN_AUTO kGreeSwingDownAuto +#define GREE_SWING_MIDDLE_AUTO kGreeSwingMiddleAuto +#define GREE_SWING_UP_AUTO kGreeSwingUpAuto + +// Classes +class IRGreeAC { + public: + explicit IRGreeAC(uint16_t pin); + + void stateReset(); +#if SEND_GREE + void send(); +#endif // SEND_GREE + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t speed); + uint8_t getFan(); + void setMode(const uint8_t new_mode); + uint8_t getMode(); + void setLight(const bool state); + bool getLight(); + void setXFan(const bool state); + bool getXFan(); + void setSleep(const bool state); + bool getSleep(); + void setTurbo(const bool state); + bool getTurbo(); + void setSwingVertical(const bool automatic, const uint8_t position); + bool getSwingVerticalAuto(); + uint8_t getSwingVerticalPosition(); + + uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kGreeStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + // The state of the IR remote in IR code form. + uint8_t remote_state[kGreeStateLength]; + void checksum(const uint16_t length = kGreeStateLength); + void fixup(); + IRsend _irsend; +}; + +#endif // IR_GREE_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp new file mode 100644 index 000000000..2c47e4eac --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp @@ -0,0 +1,865 @@ +// Copyright 2018 crankyoldgit +// The specifics of reverse engineering the protocols details: +// * HSU07-HEA03 by kuzin2006. +// * YR-W02/HSU-09HMC203 by non7top. + +#include "ir_Haier.h" +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRutils.h" + +// HH HH AAA IIIII EEEEEEE RRRRRR +// HH HH AAAAA III EE RR RR +// HHHHHHH AA AA III EEEEE RRRRRR +// HH HH AAAAAAA III EE RR RR +// HH HH AA AA IIIII EEEEEEE RR RR + +// Supported devices: +// * Haier HSU07-HEA03 Remote control. +// * Haier YR-W02 Remote control +// * Haier HSU-09HMC203 A/C unit. + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/404 +// https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0 +// https://github.com/markszabo/IRremoteESP8266/issues/485 +// https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods + +// Constants +const uint16_t kHaierAcHdr = 3000; +const uint16_t kHaierAcHdrGap = 4300; +const uint16_t kHaierAcBitMark = 520; +const uint16_t kHaierAcOneSpace = 1650; +const uint16_t kHaierAcZeroSpace = 650; +const uint32_t kHaierAcMinGap = 150000; // Completely made up value. + +#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02) +// Send a Haier A/C message. (HSU07-HEA03 remote) +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHaierACStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: Beta / Probably working. +// +void IRsend::sendHaierAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kHaierACStateLength) return; + + for (uint16_t r = 0; r <= repeat; r++) { + enableIROut(38000); + mark(kHaierAcHdr); + space(kHaierAcHdr); + sendGeneric(kHaierAcHdr, kHaierAcHdrGap, kHaierAcBitMark, kHaierAcOneSpace, + kHaierAcBitMark, kHaierAcZeroSpace, kHaierAcBitMark, + kHaierAcMinGap, data, nbytes, 38, true, + 0, // Repeats handled elsewhere + 50); + } +} +#endif // (SEND_HAIER_AC || SEND_HAIER_AC_YRW02) + +#if SEND_HAIER_AC_YRW02 +// Send a Haier YR-W02 remote A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHaierACYRW02StateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: Alpha / Untested on a real device. +// +void IRsend::sendHaierACYRW02(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes >= kHaierACYRW02StateLength) sendHaierAC(data, nbytes, repeat); +} +#endif // SEND_HAIER_AC_YRW02 + +// Class for emulating a Haier HSU07-HEA03 remote +IRHaierAC::IRHaierAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRHaierAC::begin() { _irsend.begin(); } + +#if SEND_HAIER_AC +void IRHaierAC::send() { + checksum(); + _irsend.sendHaierAC(remote_state); +} +#endif // SEND_HAIER_AC + +void IRHaierAC::checksum() { + remote_state[8] = sumBytes(remote_state, kHaierACStateLength - 1); +} + +bool IRHaierAC::validChecksum(uint8_t state[], const uint16_t length) { + if (length < 2) return false; // 1 byte of data can't have a checksum. + return (state[length - 1] == sumBytes(state, length - 1)); +} + +void IRHaierAC::stateReset() { + for (uint8_t i = 1; i < kHaierACStateLength; i++) remote_state[i] = 0x0; + remote_state[0] = kHaierAcPrefix; + remote_state[2] = 0b00100000; + + setTemp(kHaierAcDefTemp); + setFan(kHaierAcFanAuto); + setMode(kHaierAcAuto); + setCommand(kHaierAcCmdOn); +} + +uint8_t* IRHaierAC::getRaw() { + checksum(); + return remote_state; +} + +void IRHaierAC::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kHaierACStateLength; i++) { + remote_state[i] = new_code[i]; + } +} + +void IRHaierAC::setCommand(uint8_t state) { + remote_state[1] &= 0b11110000; + switch (state) { + case kHaierAcCmdOff: + case kHaierAcCmdOn: + case kHaierAcCmdMode: + case kHaierAcCmdFan: + case kHaierAcCmdTempUp: + case kHaierAcCmdTempDown: + case kHaierAcCmdSleep: + case kHaierAcCmdTimerSet: + case kHaierAcCmdTimerCancel: + case kHaierAcCmdHealth: + case kHaierAcCmdSwing: + remote_state[1] |= (state & 0b00001111); + } +} + +uint8_t IRHaierAC::getCommand() { return remote_state[1] & (0b00001111); } + +void IRHaierAC::setFan(uint8_t speed) { + uint8_t new_speed = kHaierAcFanAuto; + switch (speed) { + case kHaierAcFanLow: + new_speed = 3; + break; + case kHaierAcFanMed: + new_speed = 1; + break; + case kHaierAcFanHigh: + new_speed = 2; + break; + default: + new_speed = kHaierAcFanAuto; // Default to auto for anything else. + } + + if (speed != getFan()) setCommand(kHaierAcCmdFan); + remote_state[5] &= 0b11111100; + remote_state[5] |= new_speed; +} + +uint8_t IRHaierAC::getFan() { + switch (remote_state[5] & 0b00000011) { + case 1: + return kHaierAcFanMed; + case 2: + return kHaierAcFanHigh; + case 3: + return kHaierAcFanLow; + default: + return kHaierAcFanAuto; + } +} + +void IRHaierAC::setMode(uint8_t mode) { + uint8_t new_mode = mode; + setCommand(kHaierAcCmdMode); + if (mode > kHaierAcFan) // If out of range, default to auto mode. + new_mode = kHaierAcAuto; + remote_state[7] &= 0b00011111; + remote_state[7] |= (new_mode << 5); +} + +uint8_t IRHaierAC::getMode() { return (remote_state[7] & 0b11100000) >> 5; } + +void IRHaierAC::setTemp(const uint8_t celsius) { + uint8_t temp = celsius; + if (temp < kHaierAcMinTemp) + temp = kHaierAcMinTemp; + else if (temp > kHaierAcMaxTemp) + temp = kHaierAcMaxTemp; + + uint8_t old_temp = getTemp(); + if (old_temp == temp) return; + if (old_temp > temp) + setCommand(kHaierAcCmdTempDown); + else + setCommand(kHaierAcCmdTempUp); + + remote_state[1] &= 0b00001111; // Clear the previous temp. + remote_state[1] |= ((temp - kHaierAcMinTemp) << 4); +} + +uint8_t IRHaierAC::getTemp() { + return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp; +} + +void IRHaierAC::setHealth(bool state) { + setCommand(kHaierAcCmdHealth); + remote_state[4] &= 0b11011111; + remote_state[4] |= (state << 5); +} + +bool IRHaierAC::getHealth(void) { return remote_state[4] & (1 << 5); } + +void IRHaierAC::setSleep(bool state) { + setCommand(kHaierAcCmdSleep); + remote_state[7] &= 0b10111111; + remote_state[7] |= (state << 6); +} + +bool IRHaierAC::getSleep(void) { return remote_state[7] & 0b01000000; } + +uint16_t IRHaierAC::getTime(const uint8_t ptr[]) { + return (ptr[0] & 0b00011111) * 60 + (ptr[1] & 0b00111111); +} + +int16_t IRHaierAC::getOnTimer() { + if (remote_state[3] & 0b10000000) // Check if the timer is turned on. + return getTime(remote_state + 6); + else + return -1; +} + +int16_t IRHaierAC::getOffTimer() { + if (remote_state[3] & 0b01000000) // Check if the timer is turned on. + return getTime(remote_state + 4); + else + return -1; +} + +uint16_t IRHaierAC::getCurrTime() { return getTime(remote_state + 2); } + +void IRHaierAC::setTime(uint8_t ptr[], const uint16_t nr_mins) { + uint16_t mins = nr_mins; + if (nr_mins > kHaierAcMaxTime) mins = kHaierAcMaxTime; + + // Hours + ptr[0] &= 0b11100000; + ptr[0] |= (mins / 60); + // Minutes + ptr[1] &= 0b11000000; + ptr[1] |= (mins % 60); +} + +void IRHaierAC::setOnTimer(const uint16_t nr_mins) { + setCommand(kHaierAcCmdTimerSet); + remote_state[3] |= 0b10000000; + setTime(remote_state + 6, nr_mins); +} + +void IRHaierAC::setOffTimer(const uint16_t nr_mins) { + setCommand(kHaierAcCmdTimerSet); + remote_state[3] |= 0b01000000; + setTime(remote_state + 4, nr_mins); +} + +void IRHaierAC::cancelTimers() { + setCommand(kHaierAcCmdTimerCancel); + remote_state[3] &= 0b00111111; +} + +void IRHaierAC::setCurrTime(const uint16_t nr_mins) { + setTime(remote_state + 2, nr_mins); +} + +uint8_t IRHaierAC::getSwing() { return (remote_state[2] & 0b11000000) >> 6; } + +void IRHaierAC::setSwing(const uint8_t state) { + if (state == getSwing()) return; // Nothing to do. + setCommand(kHaierAcCmdSwing); + switch (state) { + case kHaierAcSwingOff: + case kHaierAcSwingUp: + case kHaierAcSwingDown: + case kHaierAcSwingChg: + remote_state[2] &= 0b00111111; + remote_state[2] |= (state << 6); + break; + } +} + +// Convert a Haier time into a human readable string. +#ifdef ARDUINO +String IRHaierAC::timeToString(const uint16_t nr_mins) { + String result = ""; +#else +std::string IRHaierAC::timeToString(const uint16_t nr_mins) { + std::string result = ""; +#endif // ARDUINO + + if (nr_mins / 24 < 10) result += "0"; // Zero pad. + result += uint64ToString(nr_mins / 60); + result += ":"; + if (nr_mins % 60 < 10) result += "0"; // Zero pad. + result += uint64ToString(nr_mins % 60); + return result; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRHaierAC::toString() { + String result = ""; +#else +std::string IRHaierAC::toString() { + std::string result = ""; +#endif // ARDUINO + uint8_t cmd = getCommand(); + result += "Command: " + uint64ToString(cmd) + " ("; + switch (cmd) { + case kHaierAcCmdOff: + result += "Off"; + break; + case kHaierAcCmdOn: + result += "On"; + break; + case kHaierAcCmdMode: + result += "Mode"; + break; + case kHaierAcCmdFan: + result += "Fan"; + break; + case kHaierAcCmdTempUp: + result += "Temp Up"; + break; + case kHaierAcCmdTempDown: + result += "Temp Down"; + break; + case kHaierAcCmdSleep: + result += "Sleep"; + break; + case kHaierAcCmdTimerSet: + result += "Timer Set"; + break; + case kHaierAcCmdTimerCancel: + result += "Timer Cancel"; + break; + case kHaierAcCmdHealth: + result += "Health"; + break; + case kHaierAcCmdSwing: + result += "Swing"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kHaierAcAuto: + result += " (AUTO)"; + break; + case kHaierAcCool: + result += " (COOL)"; + break; + case kHaierAcHeat: + result += " (HEAT)"; + break; + case kHaierAcDry: + result += " (DRY)"; + break; + case kHaierAcFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kHaierAcFanAuto: + result += " (AUTO)"; + break; + case kHaierAcFanHigh: + result += " (MAX)"; + break; + } + result += ", Swing: " + uint64ToString(getSwing()) + " ("; + switch (getSwing()) { + case kHaierAcSwingOff: + result += "Off"; + break; + case kHaierAcSwingUp: + result += "Up"; + break; + case kHaierAcSwingDown: + result += "Down"; + break; + case kHaierAcSwingChg: + result += "Chg"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Sleep: "; + if (getSleep()) + result += "On"; + else + result += "Off"; + result += ", Health: "; + if (getHealth()) + result += "On"; + else + result += "Off"; + result += ", Current Time: " + timeToString(getCurrTime()); + result += ", On Timer: "; + if (getOnTimer() >= 0) + result += timeToString(getOnTimer()); + else + result += "Off"; + result += ", Off Timer: "; + if (getOffTimer() >= 0) + result += timeToString(getOffTimer()); + else + result += "Off"; + + return result; +} +// End of IRHaierAC class. + +// Class for emulating a Haier YRW02 remote +IRHaierACYRW02::IRHaierACYRW02(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRHaierACYRW02::begin() { _irsend.begin(); } + +#if SEND_HAIER_AC_YRW02 +void IRHaierACYRW02::send() { + checksum(); + _irsend.sendHaierACYRW02(remote_state); +} +#endif // SEND_HAIER_AC_YRW02 + +void IRHaierACYRW02::checksum() { + remote_state[kHaierACYRW02StateLength - 1] = + sumBytes(remote_state, kHaierACYRW02StateLength - 1); +} + +bool IRHaierACYRW02::validChecksum(uint8_t state[], const uint16_t length) { + if (length < 2) return false; // 1 byte of data can't have a checksum. + return (state[length - 1] == sumBytes(state, length - 1)); +} + +void IRHaierACYRW02::stateReset() { + for (uint8_t i = 1; i < kHaierACYRW02StateLength; i++) remote_state[i] = 0x0; + remote_state[0] = kHaierAcYrw02Prefix; + + setTemp(kHaierAcDefTemp); + setHealth(true); + setTurbo(kHaierAcYrw02TurboOff); + setSleep(false); + setFan(kHaierAcYrw02FanAuto); + setSwing(kHaierAcYrw02SwingOff); + setMode(kHaierAcYrw02Auto); + setPower(true); +} + +uint8_t* IRHaierACYRW02::getRaw() { + checksum(); + return remote_state; +} + +void IRHaierACYRW02::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kHaierACYRW02StateLength; i++) { + remote_state[i] = new_code[i]; + } +} + +void IRHaierACYRW02::setButton(uint8_t button) { + switch (button) { + case kHaierAcYrw02ButtonTempUp: + case kHaierAcYrw02ButtonTempDown: + case kHaierAcYrw02ButtonSwing: + case kHaierAcYrw02ButtonFan: + case kHaierAcYrw02ButtonPower: + case kHaierAcYrw02ButtonMode: + case kHaierAcYrw02ButtonHealth: + case kHaierAcYrw02ButtonTurbo: + case kHaierAcYrw02ButtonSleep: + remote_state[12] &= 0b11110000; + remote_state[12] |= (button & 0b00001111); + } +} + +uint8_t IRHaierACYRW02::getButton() { return remote_state[12] & (0b00001111); } + +void IRHaierACYRW02::setMode(uint8_t mode) { + uint8_t new_mode = mode; + setButton(kHaierAcYrw02ButtonMode); + switch (mode) { + case kHaierAcYrw02Auto: + case kHaierAcYrw02Cool: + case kHaierAcYrw02Dry: + case kHaierAcYrw02Heat: + case kHaierAcYrw02Fan: + break; + default: // If unexpected, default to auto mode. + new_mode = kHaierAcYrw02Auto; + } + remote_state[7] &= 0b0001111; + remote_state[7] |= (new_mode << 4); +} + +uint8_t IRHaierACYRW02::getMode() { return remote_state[7] >> 4; } + +void IRHaierACYRW02::setTemp(const uint8_t celcius) { + uint8_t temp = celcius; + if (temp < kHaierAcMinTemp) + temp = kHaierAcMinTemp; + else if (temp > kHaierAcMaxTemp) + temp = kHaierAcMaxTemp; + + uint8_t old_temp = getTemp(); + if (old_temp == temp) return; + if (old_temp > temp) + setButton(kHaierAcYrw02ButtonTempDown); + else + setButton(kHaierAcYrw02ButtonTempUp); + + remote_state[1] &= 0b00001111; // Clear the previous temp. + remote_state[1] |= ((temp - kHaierAcMinTemp) << 4); +} + +uint8_t IRHaierACYRW02::getTemp() { + return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp; +} + +void IRHaierACYRW02::setHealth(bool state) { + setButton(kHaierAcYrw02ButtonHealth); + remote_state[3] &= 0b11111101; + remote_state[3] |= (state << 1); +} + +bool IRHaierACYRW02::getHealth(void) { return remote_state[3] & 0b00000010; } + +bool IRHaierACYRW02::getPower() { return remote_state[4] & kHaierAcYrw02Power; } + +void IRHaierACYRW02::setPower(bool state) { + setButton(kHaierAcYrw02ButtonPower); + if (state) + remote_state[4] |= kHaierAcYrw02Power; + else + remote_state[4] &= ~kHaierAcYrw02Power; +} + +void IRHaierACYRW02::on() { setPower(true); } + +void IRHaierACYRW02::off() { setPower(false); } + +bool IRHaierACYRW02::getSleep() { return remote_state[8] & kHaierAcYrw02Sleep; } + +void IRHaierACYRW02::setSleep(bool state) { + setButton(kHaierAcYrw02ButtonSleep); + if (state) + remote_state[8] |= kHaierAcYrw02Sleep; + else + remote_state[8] &= ~kHaierAcYrw02Sleep; +} + +uint8_t IRHaierACYRW02::getTurbo() { return remote_state[6] >> 6; } + +void IRHaierACYRW02::setTurbo(uint8_t speed) { + switch (speed) { + case kHaierAcYrw02TurboOff: + case kHaierAcYrw02TurboLow: + case kHaierAcYrw02TurboHigh: + remote_state[6] &= 0b00111111; + remote_state[6] |= (speed << 6); + setButton(kHaierAcYrw02ButtonTurbo); + } +} + +uint8_t IRHaierACYRW02::getFan() { return remote_state[5] >> 4; } + +void IRHaierACYRW02::setFan(uint8_t speed) { + switch (speed) { + case kHaierAcYrw02FanLow: + case kHaierAcYrw02FanMed: + case kHaierAcYrw02FanHigh: + case kHaierAcYrw02FanAuto: + remote_state[5] &= 0b00001111; + remote_state[5] |= (speed << 4); + setButton(kHaierAcYrw02ButtonFan); + } +} + +uint8_t IRHaierACYRW02::getSwing() { return remote_state[1] & 0b00001111; } + +void IRHaierACYRW02::setSwing(uint8_t state) { + uint8_t newstate = state; + switch (state) { + case kHaierAcYrw02SwingOff: + case kHaierAcYrw02SwingAuto: + case kHaierAcYrw02SwingTop: + case kHaierAcYrw02SwingMiddle: + case kHaierAcYrw02SwingBottom: + case kHaierAcYrw02SwingDown: + setButton(kHaierAcYrw02ButtonSwing); + break; + default: + return; // Unexpected value so don't do anything. + } + + // Heat mode has no MIDDLE setting, use BOTTOM instead. + if (state == kHaierAcYrw02SwingMiddle && getMode() == kHaierAcYrw02Heat) + newstate = kHaierAcYrw02SwingBottom; + + // BOTTOM is only allowed if we are in Heat mode, otherwise MIDDLE. + if (state == kHaierAcYrw02SwingBottom && getMode() != kHaierAcYrw02Heat) + newstate = kHaierAcYrw02SwingMiddle; + + remote_state[1] &= 0b11110000; + remote_state[1] |= newstate; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRHaierACYRW02::toString() { + String result = ""; +#else +std::string IRHaierACYRW02::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + uint8_t cmd = getButton(); + result += ", Button: " + uint64ToString(cmd) + " ("; + switch (cmd) { + case kHaierAcYrw02ButtonPower: + result += "Power"; + break; + case kHaierAcYrw02ButtonMode: + result += "Mode"; + break; + case kHaierAcYrw02ButtonFan: + result += "Fan"; + break; + case kHaierAcYrw02ButtonTempUp: + result += "Temp Up"; + break; + case kHaierAcYrw02ButtonTempDown: + result += "Temp Down"; + break; + case kHaierAcYrw02ButtonSleep: + result += "Sleep"; + break; + case kHaierAcYrw02ButtonHealth: + result += "Health"; + break; + case kHaierAcYrw02ButtonSwing: + result += "Swing"; + break; + case kHaierAcYrw02ButtonTurbo: + result += "Turbo"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kHaierAcYrw02Auto: + result += " (Auto)"; + break; + case kHaierAcYrw02Cool: + result += " (Cool)"; + break; + case kHaierAcYrw02Heat: + result += " (Heat)"; + break; + case kHaierAcYrw02Dry: + result += " (Dry)"; + break; + case kHaierAcYrw02Fan: + result += " (Fan)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kHaierAcYrw02FanAuto: + result += " (Auto)"; + break; + case kHaierAcYrw02FanHigh: + result += " (High)"; + break; + case kHaierAcYrw02FanLow: + result += " (Low)"; + break; + case kHaierAcYrw02FanMed: + result += " (Med)"; + break; + default: + result += " (Unknown)"; + } + result += ", Turbo: " + uint64ToString(getTurbo()) + " ("; + switch (getTurbo()) { + case kHaierAcYrw02TurboOff: + result += "Off"; + break; + case kHaierAcYrw02TurboLow: + result += "Low"; + break; + case kHaierAcYrw02TurboHigh: + result += "High"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Swing: " + uint64ToString(getSwing()) + " ("; + switch (getSwing()) { + case kHaierAcYrw02SwingOff: + result += "Off"; + break; + case kHaierAcYrw02SwingAuto: + result += "Auto"; + break; + case kHaierAcYrw02SwingBottom: + result += "Bottom"; + break; + case kHaierAcYrw02SwingDown: + result += "Down"; + break; + case kHaierAcYrw02SwingTop: + result += "Top"; + break; + case kHaierAcYrw02SwingMiddle: + result += "Middle"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Sleep: "; + if (getSleep()) + result += "On"; + else + result += "Off"; + result += ", Health: "; + if (getHealth()) + result += "On"; + else + result += "Off"; + + return result; +} +// End of IRHaierACYRW02 class. + +#if (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02) +// Decode the supplied Haier HSU07-HEA03 remote message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kHaierACBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to be working. +// +bool IRrecv::decodeHaierAC(decode_results* results, uint16_t nbits, + bool strict) { + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + if (strict) { + if (nbits != kHaierACBits) + return false; // Not strictly a HAIER_AC message. + } + + if (results->rawlen < (2 * nbits + kHeader) + kFooter - 1) + return false; // Can't possibly be a valid HAIER_AC message. + + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset++], kHaierAcHdr)) return false; + if (!matchSpace(results->rawbuf[offset++], kHaierAcHdr)) return false; + if (!matchMark(results->rawbuf[offset++], kHaierAcHdr)) return false; + if (!matchSpace(results->rawbuf[offset++], kHaierAcHdrGap)) return false; + + // Data + for (uint16_t i = 0; i < nbits / 8; i++) { + match_result_t data_result = + matchData(&(results->rawbuf[offset]), 8, kHaierAcBitMark, + kHaierAcOneSpace, kHaierAcBitMark, kHaierAcZeroSpace); + if (data_result.success == false) return false; + offset += data_result.used; + results->state[i] = (uint8_t)data_result.data; + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kHaierAcBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kHaierAcMinGap)) + return false; + + // Compliance + if (strict) { + if (results->state[0] != kHaierAcPrefix) return false; + if (!IRHaierAC::validChecksum(results->state, nbits / 8)) return false; + } + + // Success + results->decode_type = HAIER_AC; + results->bits = nbits; + return true; +} +#endif // (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02) + +#if DECODE_HAIER_AC_YRW02 +// Decode the supplied Haier YR-W02 remote A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kHaierACYRW02Bits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to be working. +// +bool IRrecv::decodeHaierACYRW02(decode_results* results, uint16_t nbits, + bool strict) { + if (strict) { + if (nbits != kHaierACYRW02Bits) + return false; // Not strictly a HAIER_AC_YRW02 message. + } + + // The protocol is almost exactly the same as HAIER_AC + if (!decodeHaierAC(results, nbits, false)) return false; + + // Compliance + if (strict) { + if (results->state[0] != kHaierAcYrw02Prefix) return false; + if (!IRHaierACYRW02::validChecksum(results->state, nbits / 8)) return false; + } + + // Success + // It looks correct, but we haven't check the checksum etc. + results->decode_type = HAIER_AC_YRW02; + return true; +} +#endif // DECODE_HAIER_AC_YRW02 diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h new file mode 100644 index 000000000..fdc15a3a8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h @@ -0,0 +1,297 @@ +// Copyright 2018 crankyoldgit +// The specifics of reverse engineering the protocol details by kuzin2006 + +#ifndef IR_HAIER_H_ +#define IR_HAIER_H_ + +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// HH HH AAA IIIII EEEEEEE RRRRRR +// HH HH AAAAA III EE RR RR +// HHHHHHH AA AA III EEEEE RRRRRR +// HH HH AAAAAAA III EE RR RR +// HH HH AA AA IIIII EEEEEEE RR RR + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/404 +// https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0 +// https://github.com/markszabo/IRremoteESP8266/issues/485 +// https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods + +// Constants + +// Haier HSU07-HEA03 remote +// Byte 0 +const uint8_t kHaierAcPrefix = 0b10100101; + +// Byte 1 +const uint8_t kHaierAcMinTemp = 16; +const uint8_t kHaierAcDefTemp = 25; +const uint8_t kHaierAcMaxTemp = 30; +const uint8_t kHaierAcCmdOff = 0b00000000; +const uint8_t kHaierAcCmdOn = 0b00000001; +const uint8_t kHaierAcCmdMode = 0b00000010; +const uint8_t kHaierAcCmdFan = 0b00000011; +const uint8_t kHaierAcCmdTempUp = 0b00000110; +const uint8_t kHaierAcCmdTempDown = 0b00000111; +const uint8_t kHaierAcCmdSleep = 0b00001000; +const uint8_t kHaierAcCmdTimerSet = 0b00001001; +const uint8_t kHaierAcCmdTimerCancel = 0b00001010; +const uint8_t kHaierAcCmdHealth = 0b00001100; +const uint8_t kHaierAcCmdSwing = 0b00001101; + +// Byte 2 +const uint8_t kHaierAcSwingOff = 0b00000000; +const uint8_t kHaierAcSwingUp = 0b00000001; +const uint8_t kHaierAcSwingDown = 0b00000010; +const uint8_t kHaierAcSwingChg = 0b00000011; + +// Byte 6 +const uint8_t kHaierAcAuto = 0; +const uint8_t kHaierAcCool = 1; +const uint8_t kHaierAcDry = 2; +const uint8_t kHaierAcHeat = 3; +const uint8_t kHaierAcFan = 4; + +const uint8_t kHaierAcFanAuto = 0; +const uint8_t kHaierAcFanLow = 1; +const uint8_t kHaierAcFanMed = 2; +const uint8_t kHaierAcFanHigh = 3; + +const uint16_t kHaierAcMaxTime = (23 * 60) + 59; + +// Legacy Haier AC defines. +#define HAIER_AC_MIN_TEMP kHaierAcMinTemp +#define HAIER_AC_DEF_TEMP kHaierAcDefTemp +#define HAIER_AC_MAX_TEMP kHaierAcMaxTemp +#define HAIER_AC_CMD_OFF kHaierAcCmdOff +#define HAIER_AC_CMD_ON kHaierAcCmdOn +#define HAIER_AC_CMD_MODE kHaierAcCmdMode +#define HAIER_AC_CMD_FAN kHaierAcCmdFan +#define HAIER_AC_CMD_TEMP_UP kHaierAcCmdTempUp +#define HAIER_AC_CMD_TEMP_DOWN kHaierAcCmdTempDown +#define HAIER_AC_CMD_SLEEP kHaierAcCmdSleep +#define HAIER_AC_CMD_TIMER_SET kHaierAcCmdTimerSet +#define HAIER_AC_CMD_TIMER_CANCEL kHaierAcCmdTimerCancel +#define HAIER_AC_CMD_HEALTH kHaierAcCmdHealth +#define HAIER_AC_CMD_SWING kHaierAcCmdSwing +#define HAIER_AC_SWING_OFF kHaierAcSwingOff +#define HAIER_AC_SWING_UP kHaierAcSwingUp +#define HAIER_AC_SWING_DOWN kHaierAcSwingDown +#define HAIER_AC_SWING_CHG kHaierAcSwingChg +#define HAIER_AC_AUTO kHaierAcAuto +#define HAIER_AC_COOL kHaierAcCool +#define HAIER_AC_DRY kHaierAcDry +#define HAIER_AC_HEAT kHaierAcHeat +#define HAIER_AC_FAN kHaierAcFan +#define HAIER_AC_FAN_AUTO kHaierAcFanAuto +#define HAIER_AC_FAN_LOW kHaierAcFanLow +#define HAIER_AC_FAN_MED kHaierAcFanMed +#define HAIER_AC_FAN_HIGH kHaierAcFanHigh + +// Haier YRW02 remote +// Byte 0 +const uint8_t kHaierAcYrw02Prefix = 0xA6; + +// Byte 1 +// Bits 0-3 +// 0x0 = 16DegC, ... 0xE = 30DegC +// Bits 4-7 - Swing +const uint8_t kHaierAcYrw02SwingOff = 0x0; +const uint8_t kHaierAcYrw02SwingTop = 0x1; +const uint8_t kHaierAcYrw02SwingMiddle = 0x2; // Not available in heat mode. +const uint8_t kHaierAcYrw02SwingBottom = 0x3; // Only available in heat mode. +const uint8_t kHaierAcYrw02SwingDown = 0xA; +const uint8_t kHaierAcYrw02SwingAuto = 0xC; // Airflow + +// Byte 3 +// Bit 7 - Health mode + +// Byte 4 +const uint8_t kHaierAcYrw02Power = 0b01000000; + +// Byte 5 +// Bits 0-3 +const uint8_t kHaierAcYrw02FanHigh = 0x2; +const uint8_t kHaierAcYrw02FanMed = 0x4; +const uint8_t kHaierAcYrw02FanLow = 0x6; +const uint8_t kHaierAcYrw02FanAuto = 0xA; + +// Byte 6 +// Bits 0-1 +const uint8_t kHaierAcYrw02TurboOff = 0x0; +const uint8_t kHaierAcYrw02TurboHigh = 0x1; +const uint8_t kHaierAcYrw02TurboLow = 0x2; + +// Byte 7 +// Bits 0-3 +const uint8_t kHaierAcYrw02Auto = 0x0; +const uint8_t kHaierAcYrw02Cool = 0x2; +const uint8_t kHaierAcYrw02Dry = 0x4; +const uint8_t kHaierAcYrw02Heat = 0x8; +const uint8_t kHaierAcYrw02Fan = 0xC; + +// Byte 8 +const uint8_t kHaierAcYrw02Sleep = 0b10000000; + +// Byte 12 +// Bits 4-7 +const uint8_t kHaierAcYrw02ButtonTempUp = 0x0; +const uint8_t kHaierAcYrw02ButtonTempDown = 0x1; +const uint8_t kHaierAcYrw02ButtonSwing = 0x2; +const uint8_t kHaierAcYrw02ButtonFan = 0x4; +const uint8_t kHaierAcYrw02ButtonPower = 0x5; +const uint8_t kHaierAcYrw02ButtonMode = 0x6; +const uint8_t kHaierAcYrw02ButtonHealth = 0x7; +const uint8_t kHaierAcYrw02ButtonTurbo = 0x8; +const uint8_t kHaierAcYrw02ButtonSleep = 0xB; + +// Legacy Haier YRW02 remote defines. +#define HAIER_AC_YRW02_SWING_OFF kHaierAcYrw02SwingOff +#define HAIER_AC_YRW02_SWING_TOP kHaierAcYrw02SwingTop +#define HAIER_AC_YRW02_SWING_MIDDLE kHaierAcYrw02SwingMiddle +#define HAIER_AC_YRW02_SWING_BOTTOM kHaierAcYrw02SwingBottom +#define HAIER_AC_YRW02_SWING_DOWN kHaierAcYrw02SwingDown +#define HAIER_AC_YRW02_SWING_AUTO kHaierAcYrw02SwingAuto +#define HAIER_AC_YRW02_FAN_HIGH kHaierAcYrw02FanHigh +#define HAIER_AC_YRW02_FAN_MED kHaierAcYrw02FanMed +#define HAIER_AC_YRW02_FAN_LOW kHaierAcYrw02FanLow +#define HAIER_AC_YRW02_FAN_AUTO kHaierAcYrw02FanAuto +#define HAIER_AC_YRW02_TURBO_OFF kHaierAcYrw02TurboOff +#define HAIER_AC_YRW02_TURBO_HIGH kHaierAcYrw02TurboHigh +#define HAIER_AC_YRW02_TURBO_LOW kHaierAcYrw02TurboLow +#define HAIER_AC_YRW02_AUTO kHaierAcYrw02Auto +#define HAIER_AC_YRW02_COOL kHaierAcYrw02Cool +#define HAIER_AC_YRW02_DRY kHaierAcYrw02Dry +#define HAIER_AC_YRW02_HEAT kHaierAcYrw02Heat +#define HAIER_AC_YRW02_FAN kHaierAcYrw02Fan +#define HAIER_AC_YRW02_BUTTON_TEMP_UP kHaierAcYrw02ButtonTempUp +#define HAIER_AC_YRW02_BUTTON_TEMP_DOWN kHaierAcYrw02ButtonTempDown +#define HAIER_AC_YRW02_BUTTON_SWING kHaierAcYrw02ButtonSwing +#define HAIER_AC_YRW02_BUTTON_FAN kHaierAcYrw02ButtonFan +#define HAIER_AC_YRW02_BUTTON_POWER kHaierAcYrw02ButtonPower +#define HAIER_AC_YRW02_BUTTON_MODE kHaierAcYrw02ButtonMode +#define HAIER_AC_YRW02_BUTTON_HEALTH kHaierAcYrw02ButtonHealth +#define HAIER_AC_YRW02_BUTTON_TURBO kHaierAcYrw02ButtonTurbo +#define HAIER_AC_YRW02_BUTTON_SLEEP kHaierAcYrw02ButtonSleep + +class IRHaierAC { + public: + explicit IRHaierAC(uint16_t pin); + +#if SEND_HAIER_AC + void send(); +#endif // SEND_HAIER_AC + void begin(); + + void setCommand(const uint8_t command); + uint8_t getCommand(); + + void setTemp(const uint8_t temp); + uint8_t getTemp(); + + void setFan(const uint8_t speed); + uint8_t getFan(); + + uint8_t getMode(); + void setMode(const uint8_t mode); + + bool getSleep(); + void setSleep(const bool state); + bool getHealth(); + void setHealth(const bool state); + + int16_t getOnTimer(); + void setOnTimer(const uint16_t mins); + int16_t getOffTimer(); + void setOffTimer(const uint16_t mins); + void cancelTimers(); + + uint16_t getCurrTime(); + void setCurrTime(const uint16_t mins); + + uint8_t getSwing(); + void setSwing(const uint8_t state); + + uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); + static bool validChecksum(uint8_t state[], + const uint16_t length = kHaierACStateLength); +#ifdef ARDUINO + String toString(); + static String timeToString(const uint16_t nr_mins); +#else + std::string toString(); + static std::string timeToString(const uint16_t nr_mins); +#endif + + private: + uint8_t remote_state[kHaierACStateLength]; + void stateReset(); + void checksum(); + static uint16_t getTime(const uint8_t ptr[]); + static void setTime(uint8_t ptr[], const uint16_t nr_mins); + IRsend _irsend; +}; + +class IRHaierACYRW02 { + public: + explicit IRHaierACYRW02(uint16_t pin); + +#if SEND_HAIER_AC_YRW02 + void send(); +#endif // SEND_HAIER_AC_YRW02 + void begin(); + + void setButton(const uint8_t button); + uint8_t getButton(); + + void setTemp(const uint8_t temp); + uint8_t getTemp(); + + void setFan(const uint8_t speed); + uint8_t getFan(); + + uint8_t getMode(); + void setMode(const uint8_t mode); + + bool getPower(); + void setPower(const bool state); + void on(); + void off(); + + bool getSleep(); + void setSleep(const bool state); + bool getHealth(); + void setHealth(const bool state); + + uint8_t getTurbo(); + void setTurbo(const uint8_t speed); + + uint8_t getSwing(); + void setSwing(const uint8_t state); + + uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); + static bool validChecksum(uint8_t state[], + const uint16_t length = kHaierACYRW02StateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + uint8_t remote_state[kHaierACYRW02StateLength]; + void stateReset(); + void checksum(); + IRsend _irsend; +}; + +#endif // IR_HAIER_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp new file mode 100644 index 000000000..111051974 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp @@ -0,0 +1,424 @@ +// Copyright 2018 David Conran +// +// Code to emulate Hitachi protocol compatible devices. +// Should be compatible with: +// * Hitachi RAS-35THA6 remote +// + +#include "ir_Hitachi.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" + +// HH HH IIIII TTTTTTT AAA CCCCC HH HH IIIII +// HH HH III TTT AAAAA CC C HH HH III +// HHHHHHH III TTT AA AA CC HHHHHHH III +// HH HH III TTT AAAAAAA CC C HH HH III +// HH HH IIIII TTT AA AA CCCCC HH HH IIIII + +// Constants +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/417 +const uint16_t kHitachiAcHdrMark = 3300; +const uint16_t kHitachiAcHdrSpace = 1700; +const uint16_t kHitachiAc1HdrMark = 3400; +const uint16_t kHitachiAc1HdrSpace = 3400; +const uint16_t kHitachiAcBitMark = 400; +const uint16_t kHitachiAcOneSpace = 1250; +const uint16_t kHitachiAcZeroSpace = 500; +const uint32_t kHitachiAcMinGap = 100000; // Completely made up value. + +#if (SEND_HITACHI_AC || SEND_HITACHI_AC2) +// Send a Hitachi A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAcStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/417 +void IRsend::sendHitachiAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kHitachiAcStateLength) + return; // Not enough bytes to send a proper message. + sendGeneric(kHitachiAcHdrMark, kHitachiAcHdrSpace, kHitachiAcBitMark, + kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace, + kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, 38, true, + repeat, 50); +} +#endif // (SEND_HITACHI_AC || SEND_HITACHI_AC2) + +#if SEND_HITACHI_AC1 +// Send a Hitachi A/C 13-byte message. +// +// For devices: +// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc1StateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: BETA / Appears to work. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/453 +// Basically the same as sendHitatchiAC() except different size and header. +void IRsend::sendHitachiAC1(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kHitachiAc1StateLength) + return; // Not enough bytes to send a proper message. + sendGeneric(kHitachiAc1HdrMark, kHitachiAc1HdrSpace, kHitachiAcBitMark, + kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace, + kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, 38, true, + repeat, 50); +} +#endif // SEND_HITACHI_AC1 + +#if SEND_HITACHI_AC2 +// Send a Hitachi A/C 53-byte message. +// +// For devices: +// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc2StateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: BETA / Appears to work. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/417 +// Basically the same as sendHitatchiAC() except different size. +void IRsend::sendHitachiAC2(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kHitachiAc2StateLength) + return; // Not enough bytes to send a proper message. + sendHitachiAC(data, nbytes, repeat); +} +#endif // SEND_HITACHI_AC2 + +// Class for handling the remote control oh a Hitachi 28 byte A/C message. +// Inspired by: +// https://github.com/ToniA/arduino-heatpumpir/blob/master/HitachiHeatpumpIR.cpp + +IRHitachiAc::IRHitachiAc(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRHitachiAc::stateReset() { + remote_state[0] = 0x80; + remote_state[1] = 0x08; + remote_state[2] = 0x0C; + remote_state[3] = 0x02; + remote_state[4] = 0xFD; + remote_state[5] = 0x80; + remote_state[6] = 0x7F; + remote_state[7] = 0x88; + remote_state[8] = 0x48; + remote_state[9] = 0x10; + for (uint8_t i = 10; i < kHitachiAcStateLength; i++) remote_state[i] = 0x00; + remote_state[14] = 0x60; + remote_state[15] = 0x60; + remote_state[24] = 0x80; + setTemp(23); +} + +void IRHitachiAc::begin() { _irsend.begin(); } + +uint8_t IRHitachiAc::calcChecksum(const uint8_t state[], + const uint16_t length) { + int8_t sum = 62; + for (uint16_t i = 0; i < length - 1; i++) sum -= reverseBits(state[i], 8); + return reverseBits((uint8_t)sum, 8); +} + +void IRHitachiAc::checksum(const uint16_t length) { + remote_state[length - 1] = calcChecksum(remote_state, length); +} + +bool IRHitachiAc::validChecksum(const uint8_t state[], const uint16_t length) { + if (length < 2) return true; // Assume true for lengths that are too short. + return (state[length - 1] == calcChecksum(state, length)); +} + +uint8_t *IRHitachiAc::getRaw() { + checksum(); + return remote_state; +} + +void IRHitachiAc::setRaw(const uint8_t new_code[], const uint16_t length) { + for (uint8_t i = 0; i < length && i < kHitachiAcStateLength; i++) + remote_state[i] = new_code[i]; +} + +#if SEND_HITACHI_AC +void IRHitachiAc::send() { + checksum(); + _irsend.sendHitachiAC(remote_state); +} +#endif // SEND_HITACHI_AC + +bool IRHitachiAc::getPower() { return (remote_state[17] & 0x01); } + +void IRHitachiAc::setPower(const bool on) { + if (on) + remote_state[17] |= 0x01; + else + remote_state[17] &= 0xFE; +} + +void IRHitachiAc::on() { setPower(true); } + +void IRHitachiAc::off() { setPower(false); } + +uint8_t IRHitachiAc::getMode() { return reverseBits(remote_state[10], 8); } + +void IRHitachiAc::setMode(const uint8_t mode) { + uint8_t newmode = mode; + switch (mode) { + case kHitachiAcFan: + // Fan mode sets a special temp. + setTemp(64); + break; + case kHitachiAcAuto: + case kHitachiAcHeat: + case kHitachiAcCool: + case kHitachiAcDry: + break; + default: + newmode = kHitachiAcAuto; + } + remote_state[10] = reverseBits(newmode, 8); + if (mode != kHitachiAcFan) setTemp(_previoustemp); + setFan(getFan()); // Reset the fan speed after the mode change. +} + +uint8_t IRHitachiAc::getTemp() { return reverseBits(remote_state[11], 8) >> 1; } + +void IRHitachiAc::setTemp(const uint8_t celsius) { + uint8_t temp; + if (celsius != 64) _previoustemp = celsius; + switch (celsius) { + case 64: + temp = celsius; + break; + default: + temp = std::min(celsius, kHitachiAcMaxTemp); + temp = std::max(temp, kHitachiAcMinTemp); + } + remote_state[11] = reverseBits(temp << 1, 8); + if (temp == kHitachiAcMinTemp) + remote_state[9] = 0x90; + else + remote_state[9] = 0x10; +} + +uint8_t IRHitachiAc::getFan() { return reverseBits(remote_state[13], 8); } + +void IRHitachiAc::setFan(const uint8_t speed) { + uint8_t fanmin = kHitachiAcFanAuto; + uint8_t fanmax = kHitachiAcFanHigh; + switch (getMode()) { + case kHitachiAcDry: // Only 2 x low speeds in Dry mode. + fanmin = kHitachiAcFanLow; + fanmax = kHitachiAcFanLow + 1; + break; + case kHitachiAcFan: + fanmin = kHitachiAcFanLow; // No Auto in Fan mode. + break; + } + uint8_t newspeed = std::max(speed, fanmin); + newspeed = std::min(newspeed, fanmax); + remote_state[13] = reverseBits(newspeed, 8); +} + +bool IRHitachiAc::getSwingVertical() { return remote_state[14] & 0x80; } + +void IRHitachiAc::setSwingVertical(const bool on) { + if (on) + remote_state[14] |= 0x80; + else + remote_state[14] &= 0x7F; +} + +bool IRHitachiAc::getSwingHorizontal() { return remote_state[15] & 0x80; } + +void IRHitachiAc::setSwingHorizontal(const bool on) { + if (on) + remote_state[15] |= 0x80; + else + remote_state[15] &= 0x7F; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRHitachiAc::toString() { + String result = ""; +#else +std::string IRHitachiAc::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kHitachiAcAuto: + result += " (AUTO)"; + break; + case kHitachiAcCool: + result += " (COOL)"; + break; + case kHitachiAcHeat: + result += " (HEAT)"; + break; + case kHitachiAcDry: + result += " (DRY)"; + break; + case kHitachiAcFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kHitachiAcFanAuto: + result += " (AUTO)"; + break; + case kHitachiAcFanLow: + result += " (LOW)"; + break; + case kHitachiAcFanHigh: + result += " (HIGH)"; + break; + default: + result += " (UNKNOWN)"; + break; + } + result += ", Swing (Vertical): "; + if (getSwingVertical()) + result += "On"; + else + result += "Off"; + result += ", Swing (Horizontal): "; + if (getSwingHorizontal()) + result += "On"; + else + result += "Off"; + return result; +} + +#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2) +// Decode the supplied Hitachi A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. +// Typically kHitachiAcBits, kHitachiAc1Bits, kHitachiAc2Bits +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +// Supported devices: +// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/417 +// https://github.com/markszabo/IRremoteESP8266/issues/453 +bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t nbits, + bool strict) { + const uint8_t kTolerance = 30; + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid HitachiAC message. + if (strict) { + switch (nbits) { + case kHitachiAcBits: + case kHitachiAc1Bits: + case kHitachiAc2Bits: + break; // Okay to continue. + default: + return false; // Not strictly a Hitachi message. + } + } + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + match_result_t data_result; + + // Header + if (nbits == kHitachiAc1Bits) { + if (!matchMark(results->rawbuf[offset++], kHitachiAc1HdrMark, kTolerance)) + return false; + if (!matchSpace(results->rawbuf[offset++], kHitachiAc1HdrSpace, kTolerance)) + return false; + } else { // Everything else. + if (!matchMark(results->rawbuf[offset++], kHitachiAcHdrMark, kTolerance)) + return false; + if (!matchSpace(results->rawbuf[offset++], kHitachiAcHdrSpace, kTolerance)) + return false; + } + // Data + // Keep reading bytes until we either run out of message or state to fill. + for (uint16_t i = 0; offset <= results->rawlen - 16 && i < nbits / 8; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData(&(results->rawbuf[offset]), 8, kHitachiAcBitMark, + kHitachiAcOneSpace, kHitachiAcBitMark, + kHitachiAcZeroSpace, kTolerance); + if (data_result.success == false) break; // Fail + results->state[i] = (uint8_t)data_result.data; + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kHitachiAcBitMark, kTolerance)) + return false; + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset], kHitachiAcMinGap, kTolerance)) + return false; + + // Compliance + if (strict) { + // Re-check we got the correct size/length due to the way we read the data. + switch (dataBitsSoFar / 8) { + case kHitachiAcStateLength: + case kHitachiAc1StateLength: + case kHitachiAc2StateLength: + break; // Continue + default: + return false; + } + if (dataBitsSoFar / 8 == kHitachiAcStateLength && + !IRHitachiAc::validChecksum(results->state, kHitachiAcStateLength)) + return false; + } + + // Success + switch (dataBitsSoFar) { + case kHitachiAc1Bits: + results->decode_type = HITACHI_AC1; + break; + case kHitachiAc2Bits: + results->decode_type = HITACHI_AC2; + break; + case kHitachiAcBits: + default: + results->decode_type = HITACHI_AC; + } + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2) diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h new file mode 100644 index 000000000..eddab59e4 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h @@ -0,0 +1,76 @@ +// Hitachi A/C +// +// Copyright 2018 David Conran + +#ifndef IR_HITACHI_H_ +#define IR_HITACHI_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// Constants +const uint8_t kHitachiAcAuto = 2; +const uint8_t kHitachiAcHeat = 3; +const uint8_t kHitachiAcCool = 4; +const uint8_t kHitachiAcDry = 5; +const uint8_t kHitachiAcFan = 0xC; +const uint8_t kHitachiAcFanAuto = 1; +const uint8_t kHitachiAcFanLow = 2; +const uint8_t kHitachiAcFanHigh = 5; +const uint8_t kHitachiAcMinTemp = 16; // 16C +const uint8_t kHitachiAcMaxTemp = 32; // 32C +const uint8_t kHitachiAcAutoTemp = 23; // 23C + +// Classes +class IRHitachiAc { + public: + explicit IRHitachiAc(uint16_t pin); + + void stateReset(); +#if SEND_HITACHI_AC + void send(); +#endif // SEND_HITACHI_AC + void begin(); + void on(); + void off(); + void setPower(const bool on); + bool getPower(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t speed); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setSwingVertical(const bool on); + bool getSwingVertical(); + void setSwingHorizontal(const bool on); + bool getSwingHorizontal(); + uint8_t* getRaw(); + void setRaw(const uint8_t new_code[], + const uint16_t length = kHitachiAcStateLength); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kHitachiAcStateLength); + static uint8_t calcChecksum(const uint8_t state[], + const uint16_t length = kHitachiAcStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + // The state of the IR remote in IR code form. + uint8_t remote_state[kHitachiAcStateLength]; + void checksum(const uint16_t length = kHitachiAcStateLength); + IRsend _irsend; + uint8_t _previoustemp; +}; + +#endif // IR_HITACHI_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_JVC.cpp similarity index 57% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_JVC.cpp index 194e39250..47df29dc4 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_JVC.cpp @@ -19,31 +19,31 @@ // Constants // Ref: // http://www.sbprojects.com/knowledge/ir/jvc.php -#define JVC_TICK 75U -#define JVC_HDR_MARK_TICKS 112U -#define JVC_HDR_MARK (JVC_HDR_MARK_TICKS * JVC_TICK) -#define JVC_HDR_SPACE_TICKS 56U -#define JVC_HDR_SPACE (JVC_HDR_SPACE_TICKS * JVC_TICK) -#define JVC_BIT_MARK_TICKS 7U -#define JVC_BIT_MARK (JVC_BIT_MARK_TICKS * JVC_TICK) -#define JVC_ONE_SPACE_TICKS 23U -#define JVC_ONE_SPACE (JVC_ONE_SPACE_TICKS * JVC_TICK) -#define JVC_ZERO_SPACE_TICKS 7U -#define JVC_ZERO_SPACE (JVC_ZERO_SPACE_TICKS * JVC_TICK) -#define JVC_RPT_LENGTH_TICKS 800U -#define JVC_RPT_LENGTH (JVC_RPT_LENGTH_TICKS * JVC_TICK) -#define JVC_MIN_GAP_TICKS (JVC_RPT_LENGTH_TICKS - \ - (JVC_HDR_MARK_TICKS + JVC_HDR_SPACE_TICKS + \ - JVC_BITS * (JVC_BIT_MARK_TICKS + JVC_ONE_SPACE_TICKS) + \ - JVC_BIT_MARK_TICKS)) -#define JVC_MIN_GAP (JVC_MIN_GAP_TICKS * JVC_TICK) +const uint16_t kJvcTick = 75; +const uint16_t kJvcHdrMarkTicks = 112; +const uint16_t kJvcHdrMark = kJvcHdrMarkTicks * kJvcTick; +const uint16_t kJvcHdrSpaceTicks = 56; +const uint16_t kJvcHdrSpace = kJvcHdrSpaceTicks * kJvcTick; +const uint16_t kJvcBitMarkTicks = 7; +const uint16_t kJvcBitMark = kJvcBitMarkTicks * kJvcTick; +const uint16_t kJvcOneSpaceTicks = 23; +const uint16_t kJvcOneSpace = kJvcOneSpaceTicks * kJvcTick; +const uint16_t kJvcZeroSpaceTicks = 7; +const uint16_t kJvcZeroSpace = kJvcZeroSpaceTicks * kJvcTick; +const uint16_t kJvcRptLengthTicks = 800; +const uint16_t kJvcRptLength = kJvcRptLengthTicks * kJvcTick; +const uint16_t kJvcMinGapTicks = + kJvcRptLengthTicks - + (kJvcHdrMarkTicks + kJvcHdrSpaceTicks + + kJvcBits * (kJvcBitMarkTicks + kJvcOneSpaceTicks) + kJvcBitMarkTicks); +const uint16_t kJvcMinGap = kJvcMinGapTicks * kJvcTick; #if SEND_JVC // Send a JVC message. // // Args: // data: The contents of the command you want to send. -// nbits: The bit size of the command being sent. (JVC_BITS) +// nbits: The bit size of the command being sent. (kJvcBits) // repeat: The number of times you want the command to be repeated. // // Status: STABLE. @@ -57,18 +57,21 @@ void IRsend::sendJVC(uint64_t data, uint16_t nbits, uint16_t repeat) { IRtimer usecs = IRtimer(); // Header // Only sent for the first message. - mark(JVC_HDR_MARK); - space(JVC_HDR_SPACE); + mark(kJvcHdrMark); + space(kJvcHdrSpace); // We always send the data & footer at least once, hence '<= repeat'. for (uint16_t i = 0; i <= repeat; i++) { - // Data - sendData(JVC_BIT_MARK, JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, - data, nbits, true); - // Footer - mark(JVC_BIT_MARK); + sendGeneric(0, 0, // No Header + kJvcBitMark, kJvcOneSpace, kJvcBitMark, kJvcZeroSpace, + kJvcBitMark, kJvcMinGap, data, nbits, 38, true, + 0, // Repeats are handles elsewhere. + 33); // Wait till the end of the repeat time window before we send another code. - space(std::max(JVC_MIN_GAP, JVC_RPT_LENGTH - usecs.elapsed())); + uint32_t elapsed = usecs.elapsed(); + // Avoid potential unsigned integer underflow. + // e.g. when elapsed > kJvcRptLength. + if (elapsed < kJvcRptLength) space(kJvcRptLength - elapsed); usecs.reset(); } } @@ -95,7 +98,7 @@ uint16_t IRsend::encodeJVC(uint8_t address, uint8_t command) { // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits of data to expect. Typically JVC_BITS. +// nbits: Nr. of bits of data to expect. Typically kJvcBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. @@ -106,50 +109,48 @@ uint16_t IRsend::encodeJVC(uint8_t address, uint8_t command) { // JVC repeat codes don't have a header. // Ref: // http://www.sbprojects.com/knowledge/ir/jvc.php -bool IRrecv::decodeJVC(decode_results *results, uint16_t nbits, bool strict) { - if (strict && nbits != JVC_BITS) +bool IRrecv::decodeJVC(decode_results *results, uint16_t nbits, bool strict) { + if (strict && nbits != kJvcBits) return false; // Must be called with the correct nr. of bits. - if (results->rawlen < 2 * nbits + FOOTER - 1) + if (results->rawlen < 2 * nbits + kFooter - 1) return false; // Can't possibly be a valid JVC message. uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; bool isRepeat = true; uint32_t m_tick; uint32_t s_tick; // Header // (Optional as repeat codes don't have the header) - if (matchMark(results->rawbuf[offset], JVC_HDR_MARK)) { + if (matchMark(results->rawbuf[offset], kJvcHdrMark)) { isRepeat = false; - m_tick = results->rawbuf[offset++] * RAWTICK / JVC_HDR_MARK_TICKS; + m_tick = results->rawbuf[offset++] * kRawTick / kJvcHdrMarkTicks; if (results->rawlen < 2 * nbits + 4) return false; // Can't possibly be a valid JVC message with a header. - if (!matchSpace(results->rawbuf[offset], JVC_HDR_SPACE)) - return false; - s_tick = results->rawbuf[offset++] * RAWTICK / JVC_HDR_SPACE_TICKS; + if (!matchSpace(results->rawbuf[offset], kJvcHdrSpace)) return false; + s_tick = results->rawbuf[offset++] * kRawTick / kJvcHdrSpaceTicks; } else { // We can't easily auto-calibrate as there is no header, so assume // the default tick time. - m_tick = JVC_TICK; - s_tick = JVC_TICK; + m_tick = kJvcTick; + s_tick = kJvcTick; } // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - JVC_BIT_MARK_TICKS * m_tick, - JVC_ONE_SPACE_TICKS * s_tick, - JVC_BIT_MARK_TICKS * m_tick, - JVC_ZERO_SPACE_TICKS * s_tick); + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kJvcBitMarkTicks * m_tick, + kJvcOneSpaceTicks * s_tick, kJvcBitMarkTicks * m_tick, + kJvcZeroSpaceTicks * s_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer - if (!matchMark(results->rawbuf[offset++], JVC_BIT_MARK_TICKS * m_tick)) + if (!matchMark(results->rawbuf[offset++], kJvcBitMarkTicks * m_tick)) return false; if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], JVC_MIN_GAP_TICKS * s_tick)) + !matchAtLeast(results->rawbuf[offset], kJvcMinGapTicks * s_tick)) return false; // Success @@ -157,7 +158,7 @@ bool IRrecv::decodeJVC(decode_results *results, uint16_t nbits, bool strict) { results->bits = nbits; results->value = data; // command & address are transmitted LSB first, so we need to reverse them. - results->address = reverseBits(data >> 8, 8); // The first 8 bits sent. + results->address = reverseBits(data >> 8, 8); // The first 8 bits sent. results->command = reverseBits(data & 0xFF, 8); // The last 8 bits sent. results->repeat = isRepeat; return true; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp new file mode 100644 index 000000000..ddf61b097 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp @@ -0,0 +1,550 @@ +// Copyright 2016 David Conran +// +// Code to emulate IR Kelvinator YALIF remote control unit, which should control +// at least the following Kelvinator A/C units: +// KSV26CRC, KSV26HRC, KSV35CRC, KSV35HRC, KSV53HRC, KSV62HRC, KSV70CRC, +// KSV70HRC, KSV80HRC. +// +// Note: +// * Unsupported: +// - All Sleep modes. +// - All Timer modes. +// - "I Feel" button & mode. +// - Energy Saving mode. +// - Low Heat mode. +// - Fahrenheit. + +#include "ir_Kelvinator.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// KK KK EEEEEEE LL VV VV IIIII NN NN AAA TTTTTTT OOOOO RRRRRR +// KK KK EE LL VV VV III NNN NN AAAAA TTT OO OO RR RR +// KKKK EEEEE LL VV VV III NN N NN AA AA TTT OO OO RRRRRR +// KK KK EE LL VV VV III NN NNN AAAAAAA TTT OO OO RR RR +// KK KK EEEEEEE LLLLLLL VVV IIIII NN NN AA AA TTT OOOO0 RR RR + +// Constants + +const uint16_t kKelvinatorTick = 85; +const uint16_t kKelvinatorHdrMarkTicks = 106; +const uint16_t kKelvinatorHdrMark = kKelvinatorHdrMarkTicks * kKelvinatorTick; +const uint16_t kKelvinatorHdrSpaceTicks = 53; +const uint16_t kKelvinatorHdrSpace = kKelvinatorHdrSpaceTicks * kKelvinatorTick; +const uint16_t kKelvinatorBitMarkTicks = 8; +const uint16_t kKelvinatorBitMark = kKelvinatorBitMarkTicks * kKelvinatorTick; +const uint16_t kKelvinatorOneSpaceTicks = 18; +const uint16_t kKelvinatorOneSpace = kKelvinatorOneSpaceTicks * kKelvinatorTick; +const uint16_t kKelvinatorZeroSpaceTicks = 6; +const uint16_t kKelvinatorZeroSpace = + kKelvinatorZeroSpaceTicks * kKelvinatorTick; +const uint16_t kKelvinatorGapSpaceTicks = 235; +const uint16_t kKelvinatorGapSpace = kKelvinatorGapSpaceTicks * kKelvinatorTick; + +const uint8_t kKelvinatorCmdFooter = 2; +const uint8_t kKelvinatorCmdFooterBits = 3; + +const uint8_t kKelvinatorPower = 8; +const uint8_t kKelvinatorModeMask = 0xF8; +const uint8_t kKelvinatorFanOffset = 4; +const uint8_t kKelvinatorBasicFanMask = 0xFF ^ (3U << kKelvinatorFanOffset); +const uint8_t kKelvinatorFanMask = 0xFF ^ (7U << kKelvinatorFanOffset); +const uint8_t kKelvinatorChecksumStart = 10; +const uint8_t kKelvinatorVentSwingOffset = 6; +const uint8_t kKelvinatorVentSwing = 1 << kKelvinatorVentSwingOffset; +const uint8_t kKelvinatorVentSwingV = 1; +const uint8_t kKelvinatorVentSwingH = 1 << 4; +const uint8_t kKelvinatorSleep1And3 = 1 << 7; +const uint8_t kKelvinatorQuietOffset = 7; +const uint8_t kKelvinatorQuiet = 1 << kKelvinatorQuietOffset; +const uint8_t kKelvinatorIonFilterOffset = 6; +const uint8_t kKelvinatorIonFilter = 1 << kKelvinatorIonFilterOffset; +const uint8_t kKelvinatorLightOffset = 5; +const uint8_t kKelvinatorLight = 1 << kKelvinatorLightOffset; +const uint8_t kKelvinatorXfanOffset = 7; +const uint8_t kKelvinatorXfan = 1 << kKelvinatorXfanOffset; +const uint8_t kKelvinatorTurboOffset = 4; +const uint8_t kKelvinatorTurbo = 1 << kKelvinatorTurboOffset; + +#if SEND_KELVINATOR +// Send a Kelvinator A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kKelvinatorStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: STABLE / Known working. +// +void IRsend::sendKelvinator(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kKelvinatorStateLength) + return; // Not enough bytes to send a proper message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Command Block #1 (4 bytes) + sendGeneric(kKelvinatorHdrMark, kKelvinatorHdrSpace, kKelvinatorBitMark, + kKelvinatorOneSpace, kKelvinatorBitMark, kKelvinatorZeroSpace, + 0, 0, // No Footer yet. + data, 4, 38, false, 0, 50); + // Send Footer for the command block (3 bits (b010)) + sendGeneric(0, 0, // No Header + kKelvinatorBitMark, kKelvinatorOneSpace, kKelvinatorBitMark, + kKelvinatorZeroSpace, kKelvinatorBitMark, kKelvinatorGapSpace, + kKelvinatorCmdFooter, kKelvinatorCmdFooterBits, 38, false, 0, + 50); + // Data Block #1 (4 bytes) + sendGeneric(0, 0, // No header + kKelvinatorBitMark, kKelvinatorOneSpace, kKelvinatorBitMark, + kKelvinatorZeroSpace, kKelvinatorBitMark, + kKelvinatorGapSpace * 2, data + 4, 4, 38, false, 0, 50); + // Command Block #2 (4 bytes) + sendGeneric(kKelvinatorHdrMark, kKelvinatorHdrSpace, kKelvinatorBitMark, + kKelvinatorOneSpace, kKelvinatorBitMark, kKelvinatorZeroSpace, + 0, 0, // No Footer yet. + data + 8, 4, 38, false, 0, 50); + // Send Footer for the command block (3 bits (B010)) + sendGeneric(0, 0, // No Header + kKelvinatorBitMark, kKelvinatorOneSpace, kKelvinatorBitMark, + kKelvinatorZeroSpace, kKelvinatorBitMark, kKelvinatorGapSpace, + kKelvinatorCmdFooter, kKelvinatorCmdFooterBits, 38, false, 0, + 50); + // Data Block #2 (4 bytes) + sendGeneric(0, 0, // No header + kKelvinatorBitMark, kKelvinatorOneSpace, kKelvinatorBitMark, + kKelvinatorZeroSpace, kKelvinatorBitMark, + kKelvinatorGapSpace * 2, data + 12, 4, 38, false, 0, 50); + } +} +#endif // SEND_KELVINATOR + +IRKelvinatorAC::IRKelvinatorAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRKelvinatorAC::stateReset() { + for (uint8_t i = 0; i < kKelvinatorStateLength; i++) remote_state[i] = 0x0; + remote_state[3] = 0x50; + remote_state[11] = 0x70; +} + +void IRKelvinatorAC::begin() { _irsend.begin(); } + +void IRKelvinatorAC::fixup() { + // X-Fan mode is only valid in COOL or DRY modes. + if (getMode() != kKelvinatorCool && getMode() != kKelvinatorDry) + setXFan(false); + checksum(); // Calculate the checksums +} + +#if SEND_KELVINATOR +void IRKelvinatorAC::send() { + fixup(); // Ensure correct settings before sending. + _irsend.sendKelvinator(remote_state); +} +#endif // SEND_KELVINATOR + +uint8_t *IRKelvinatorAC::getRaw() { + fixup(); // Ensure correct settings before sending. + return remote_state; +} + +void IRKelvinatorAC::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kKelvinatorStateLength; i++) { + remote_state[i] = new_code[i]; + } +} + +uint8_t IRKelvinatorAC::calcBlockChecksum(const uint8_t *block, + const uint16_t length) { + uint8_t sum = kKelvinatorChecksumStart; + // Sum the lower half of the first 4 bytes of this block. + for (uint8_t i = 0; i < 4 && i < length - 1; i++, block++) + sum += (*block & 0x0FU); + // then sum the upper half of the next 3 bytes. + for (uint8_t i = 4; i < length - 1; i++, block++) sum += (*block >> 4); + // Trim it down to fit into the 4 bits allowed. i.e. Mod 16. + return sum & 0x0FU; +} + +// Many Bothans died to bring us this information. +void IRKelvinatorAC::checksum(const uint16_t length) { + // For each command + options block. + for (uint16_t offset = 0; offset + 7 < length; offset += 8) { + uint8_t sum = calcBlockChecksum(remote_state + offset); + remote_state[7 + offset] = (sum << 4) | (remote_state[7 + offset] & 0xFU); + } +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRKelvinatorAC::validChecksum(const uint8_t state[], + const uint16_t length) { + for (uint16_t offset = 0; offset + 7 < length; offset += 8) { + // Top 4 bits of the last byte in the block is the block's checksum. + if (state[offset + 7] >> 4 != calcBlockChecksum(state + offset)) + return false; + } + return true; +} + +void IRKelvinatorAC::on() { + remote_state[0] |= kKelvinatorPower; + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. +} + +void IRKelvinatorAC::off() { + remote_state[0] &= ~kKelvinatorPower; + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. +} + +void IRKelvinatorAC::setPower(bool state) { + if (state) + on(); + else + off(); +} + +bool IRKelvinatorAC::getPower() { + return ((remote_state[0] & kKelvinatorPower) != 0); +} + +// Set the temp. in deg C +void IRKelvinatorAC::setTemp(uint8_t temp) { + temp = std::max(kKelvinatorMinTemp, temp); + temp = std::min(kKelvinatorMaxTemp, temp); + remote_state[1] = (remote_state[1] & 0xF0U) | (temp - kKelvinatorMinTemp); + remote_state[9] = remote_state[1]; // Duplicate to the 2nd command chunk. +} + +// Return the set temp. in deg C +uint8_t IRKelvinatorAC::getTemp() { + return ((remote_state[1] & 0xFU) + kKelvinatorMinTemp); +} + +// Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed +void IRKelvinatorAC::setFan(uint8_t fan) { + fan = std::min(kKelvinatorFanMax, fan); // Bounds check + + // Only change things if we need to. + if (fan != getFan()) { + // Set the basic fan values. + uint8_t fan_basic = std::min(kKelvinatorBasicFanMax, fan); + remote_state[0] = (remote_state[0] & kKelvinatorBasicFanMask) | + (fan_basic << kKelvinatorFanOffset); + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. + // Set the advanced(?) fan value. + remote_state[14] = + (remote_state[14] & kKelvinatorFanMask) | (fan << kKelvinatorFanOffset); + setTurbo(false); // Turbo mode is turned off if we change the fan settings. + } +} + +uint8_t IRKelvinatorAC::getFan() { + return ((remote_state[14] & ~kKelvinatorFanMask) >> kKelvinatorFanOffset); +} + +uint8_t IRKelvinatorAC::getMode() { + return (remote_state[0] & ~kKelvinatorModeMask); +} + +void IRKelvinatorAC::setMode(uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + if (mode > kKelvinatorHeat) mode = kKelvinatorAuto; + remote_state[0] = (remote_state[0] & kKelvinatorModeMask) | mode; + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. + if (mode == kKelvinatorAuto || kKelvinatorDry) + // When the remote is set to Auto or Dry, it defaults to 25C and doesn't + // show it. + setTemp(kKelvinatorAutoTemp); +} + +void IRKelvinatorAC::setSwingVertical(bool state) { + if (state) { + remote_state[0] |= kKelvinatorVentSwing; + remote_state[4] |= kKelvinatorVentSwingV; + } else { + remote_state[4] &= ~kKelvinatorVentSwingV; + if (!getSwingHorizontal()) remote_state[0] &= ~kKelvinatorVentSwing; + } + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getSwingVertical() { + return ((remote_state[4] & kKelvinatorVentSwingV) != 0); +} + +void IRKelvinatorAC::setSwingHorizontal(bool state) { + if (state) { + remote_state[0] |= kKelvinatorVentSwing; + remote_state[4] |= kKelvinatorVentSwingH; + } else { + remote_state[4] &= ~kKelvinatorVentSwingH; + if (!getSwingVertical()) remote_state[0] &= ~kKelvinatorVentSwing; + } + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getSwingHorizontal() { + return ((remote_state[4] & kKelvinatorVentSwingH) != 0); +} + +void IRKelvinatorAC::setQuiet(bool state) { + remote_state[12] &= ~kKelvinatorQuiet; + remote_state[12] |= (state << kKelvinatorQuietOffset); +} + +bool IRKelvinatorAC::getQuiet() { + return ((remote_state[12] & kKelvinatorQuiet) != 0); +} + +void IRKelvinatorAC::setIonFilter(bool state) { + remote_state[2] &= ~kKelvinatorIonFilter; + remote_state[2] |= (state << kKelvinatorIonFilterOffset); + remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getIonFilter() { + return ((remote_state[2] & kKelvinatorIonFilter) != 0); +} + +void IRKelvinatorAC::setLight(bool state) { + remote_state[2] &= ~kKelvinatorLight; + remote_state[2] |= (state << kKelvinatorLightOffset); + remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getLight() { + return ((remote_state[2] & kKelvinatorLight) != 0); +} + +// Note: XFan mode is only valid in Cool or Dry mode. +void IRKelvinatorAC::setXFan(bool state) { + remote_state[2] &= ~kKelvinatorXfan; + remote_state[2] |= (state << kKelvinatorXfanOffset); + remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getXFan() { + return ((remote_state[2] & kKelvinatorXfan) != 0); +} + +// Note: Turbo mode is turned off if the fan speed is changed. +void IRKelvinatorAC::setTurbo(bool state) { + remote_state[2] &= ~kKelvinatorTurbo; + remote_state[2] |= (state << kKelvinatorTurboOffset); + remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getTurbo() { + return ((remote_state[2] & kKelvinatorTurbo) != 0); +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRKelvinatorAC::toString() { + String result = ""; +#else +std::string IRKelvinatorAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kKelvinatorAuto: + result += " (AUTO)"; + break; + case kKelvinatorCool: + result += " (COOL)"; + break; + case kKelvinatorHeat: + result += " (HEAT)"; + break; + case kKelvinatorDry: + result += " (DRY)"; + break; + case kKelvinatorFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kKelvinatorFanAuto: + result += " (AUTO)"; + break; + case kKelvinatorFanMax: + result += " (MAX)"; + break; + } + result += ", Turbo: "; + if (getTurbo()) + result += "On"; + else + result += "Off"; + result += ", Quiet: "; + if (getQuiet()) + result += "On"; + else + result += "Off"; + result += ", XFan: "; + if (getXFan()) + result += "On"; + else + result += "Off"; + result += ", IonFilter: "; + if (getIonFilter()) + result += "On"; + else + result += "Off"; + result += ", Light: "; + if (getLight()) + result += "On"; + else + result += "Off"; + result += ", Swing (Horizontal): "; + if (getSwingHorizontal()) + result += "On"; + else + result += "Off"; + result += ", Swing (Vertical): "; + if (getSwingVertical()) + result += "On"; + else + result += "Off"; + return result; +} + +#if DECODE_KELVINATOR +// Decode the supplied Kelvinator message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kKelvinatorBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +bool IRrecv::decodeKelvinator(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < + 2 * (nbits + kKelvinatorCmdFooterBits) + (kHeader + kFooter + 1) * 2 - 1) + return false; // Can't possibly be a valid Kelvinator message. + if (strict && nbits != kKelvinatorBits) + return false; // Not strictly a Kelvinator message. + + uint32_t data; + uint16_t offset = kStartOffset; + + // There are two messages back-to-back in a full Kelvinator IR message + // sequence. + int8_t state_pos = 0; + for (uint8_t s = 0; s < 2; s++) { + match_result_t data_result; + + // Header + if (!matchMark(results->rawbuf[offset], kKelvinatorHdrMark)) return false; + // Calculate how long the lowest tick time is based on the header mark. + uint32_t mark_tick = + results->rawbuf[offset++] * kRawTick / kKelvinatorHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kKelvinatorHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t space_tick = + results->rawbuf[offset++] * kRawTick / kKelvinatorHdrSpaceTicks; + + // Data (Command) (32 bits) + data_result = matchData( + &(results->rawbuf[offset]), 32, kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorOneSpaceTicks * space_tick, + kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorZeroSpaceTicks * space_tick, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Record command data in the state. + for (uint16_t i = 0; i < 4; i++, data >>= 8) + results->state[state_pos + i] = data & 0xFF; + state_pos += 4; + + // Command data footer (3 bits, B010) + data_result = matchData( + &(results->rawbuf[offset]), kKelvinatorCmdFooterBits, + kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorOneSpaceTicks * space_tick, + kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorZeroSpaceTicks * space_tick, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + if (data_result.data != kKelvinatorCmdFooter) return false; + offset += data_result.used; + + // Interdata gap. + if (!matchMark(results->rawbuf[offset++], + kKelvinatorBitMarkTicks * mark_tick)) + return false; + if (!matchSpace(results->rawbuf[offset++], + kKelvinatorGapSpaceTicks * space_tick)) + return false; + + // Data (Options) (32 bits) + data_result = matchData( + &(results->rawbuf[offset]), 32, kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorOneSpaceTicks * space_tick, + kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorZeroSpaceTicks * space_tick, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Record option data in the state. + for (uint16_t i = 0; i < 4; i++, data >>= 8) + results->state[state_pos + i] = data & 0xFF; + state_pos += 4; + + // Inter-sequence gap. (Double length gap) + if (!matchMark(results->rawbuf[offset++], + kKelvinatorBitMarkTicks * mark_tick)) + return false; + if (s == 0) { + if (!matchSpace(results->rawbuf[offset++], + kKelvinatorGapSpaceTicks * space_tick * 2)) + return false; + } else { + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset], + kKelvinatorGapSpaceTicks * 2 * space_tick)) + return false; + } + } + + // Compliance + if (strict) { + // Correct size/length) + if (state_pos != kKelvinatorStateLength) return false; + // Verify the message's checksum is correct. + if (!IRKelvinatorAC::validChecksum(results->state)) return false; + } + + // Success + results->decode_type = KELVINATOR; + results->bits = state_pos * 8; + // 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_KELVINATOR diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.h similarity index 71% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.h rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.h index c15d85c6e..1508d6cdc 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.h +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.h @@ -7,6 +7,11 @@ #define __STDC_LIMIT_MACROS #include +#ifndef UNIT_TEST +#include +#else +#include +#endif #include "IRremoteESP8266.h" #include "IRsend.h" @@ -17,19 +22,33 @@ // KK KK EEEEEEE LLLLLLL VVV IIIII NN NN AA AA TTT OOOO0 RR RR // Constants -#define KELVINATOR_AUTO 0U -#define KELVINATOR_COOL 1U -#define KELVINATOR_DRY 2U -#define KELVINATOR_FAN 3U -#define KELVINATOR_HEAT 4U -#define KELVINATOR_BASIC_FAN_MAX 3U -#define KELVINATOR_FAN_MAX 5U -#define KELVINATOR_MIN_TEMP 16U // 16C -#define KELVINATOR_MAX_TEMP 30U // 30C -#define KELVINATOR_AUTO_TEMP 25U // 25C +const uint8_t kKelvinatorAuto = 0; +const uint8_t kKelvinatorCool = 1; +const uint8_t kKelvinatorDry = 2; +const uint8_t kKelvinatorFan = 3; +const uint8_t kKelvinatorHeat = 4; +const uint8_t kKelvinatorBasicFanMax = 3; +const uint8_t kKelvinatorFanAuto = 0; +const uint8_t kKelvinatorFanMax = 5; +const uint8_t kKelvinatorMinTemp = 16; // 16C +const uint8_t kKelvinatorMaxTemp = 30; // 30C +const uint8_t kKelvinatorAutoTemp = 25; // 25C + +// Legacy defines (Deprecated) +#define KELVINATOR_MIN_TEMP kKelvinatorMinTemp +#define KELVINATOR_MAX_TEMP kKelvinatorMaxTemp +#define KELVINATOR_HEAT kKelvinatorHeat +#define KELVINATOR_FAN_MAX kKelvinatorFanMax +#define KELVINATOR_FAN_AUTO kKelvinatorFanAuto +#define KELVINATOR_FAN kKelvinatorFan +#define KELVINATOR_DRY kKelvinatorDry +#define KELVINATOR_COOL kKelvinatorCool +#define KELVINATOR_BASIC_FAN_MAX kKelvinatorBasicFanMax +#define KELVINATOR_AUTO_TEMP kKelvinatorAutoTemp +#define KELVINATOR_AUTO kKelvinatorAuto /* - Kelvinator AC map + Kelvinator AC map (header mark and space) byte 0 = Basic Modes @@ -104,15 +123,15 @@ b7-4 = checksum of the previous bytes (8-14) */ -#if SEND_KELVINATOR - // Classes class IRKelvinatorAC { public: explicit IRKelvinatorAC(uint16_t pin); void stateReset(); +#if SEND_KELVINATOR void send(); +#endif // SEND_KELVINATOR void begin(); void on(); void off(); @@ -139,14 +158,23 @@ class IRKelvinatorAC { void setTurbo(bool state); bool getTurbo(); uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); + static uint8_t calcBlockChecksum( + const uint8_t* block, const uint16_t length = kKelvinatorStateLength / 2); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kKelvinatorStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif private: // The state of the IR remote in IR code form. - uint8_t remote_state[KELVINATOR_STATE_LENGTH]; - void checksum(); + uint8_t remote_state[kKelvinatorStateLength]; + void checksum(const uint16_t length = kKelvinatorStateLength); void fixup(); IRsend _irsend; }; -#endif #endif // IR_KELVINATOR_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp new file mode 100644 index 000000000..f9d922fc7 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp @@ -0,0 +1,290 @@ +// Copyright 2015 Darryl Smith +// Copyright 2015 cheaplin +// Copyright 2017, 2018 David Conran + +#include "ir_LG.h" +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// L GGGG +// L G +// L G GG +// L G G +// LLLLL GGG + +// LG decode originally added by Darryl Smith (based on the JVC protocol) +// LG send originally added by https://github.com/chaeplin +// +// Known supported devices: +// IR Remotes: +// 6711A20083V +// AKB74395308 + +// Constants +const uint16_t kLgTick = 50; +const uint16_t kLgHdrMarkTicks = 170; +const uint16_t kLgHdrMark = kLgHdrMarkTicks * kLgTick; // 8500 +const uint16_t kLgHdrSpaceTicks = 85; +const uint16_t kLgHdrSpace = kLgHdrSpaceTicks * kLgTick; // 4250 +const uint16_t kLgBitMarkTicks = 11; +const uint16_t kLgBitMark = kLgBitMarkTicks * kLgTick; // 550 +const uint16_t kLgOneSpaceTicks = 32; +const uint16_t kLgOneSpace = kLgOneSpaceTicks * kLgTick; // 1600 +const uint16_t kLgZeroSpaceTicks = 11; +const uint16_t kLgZeroSpace = kLgZeroSpaceTicks * kLgTick; // 550 +const uint16_t kLgRptSpaceTicks = 45; +const uint16_t kLgRptSpace = kLgRptSpaceTicks * kLgTick; // 2250 +const uint16_t kLgMinGapTicks = 795; +const uint16_t kLgMinGap = kLgMinGapTicks * kLgTick; // 39750 +const uint16_t kLgMinMessageLengthTicks = 2161; +const uint32_t kLgMinMessageLength = kLgMinMessageLengthTicks * kLgTick; + +const uint16_t kLg32HdrMarkTicks = 90; +const uint16_t kLg32HdrMark = kLg32HdrMarkTicks * kLgTick; // 4500 +const uint16_t kLg32HdrSpaceTicks = 89; +const uint16_t kLg32HdrSpace = kLg32HdrSpaceTicks * kLgTick; // 4450 +const uint16_t kLg32RptHdrMarkTicks = 179; +const uint16_t kLg32RptHdrMark = kLg32RptHdrMarkTicks * kLgTick; // 8950 + +const uint16_t kLg2HdrMarkTicks = 64; +const uint16_t kLg2HdrMark = kLg2HdrMarkTicks * kLgTick; // 3200 +const uint16_t kLg2HdrSpaceTicks = 197; +const uint16_t kLg2HdrSpace = kLg2HdrSpaceTicks * kLgTick; // 9850 +const uint16_t kLg2BitMarkTicks = 10; +const uint16_t kLg2BitMark = kLg2BitMarkTicks * kLgTick; // 500 + +#if (SEND_LG || DECODE_LG) +// Calculate the rolling 4-bit wide checksum over all of the data. +// Args: +// data: The value to be checksum'ed. +// Returns: +// A 4-bit checksum. +uint8_t calcLGChecksum(uint16_t data) { + return (((data >> 12) + ((data >> 8) & 0xF) + ((data >> 4) & 0xF) + + (data & 0xF)) & + 0xF); +} +#endif + +#if SEND_LG +// Send an LG formatted message. +// +// Args: +// data: The contents of the message you want to send. +// nbits: The bit size of the message being sent. +// Typically kLgBits or kLg32Bits. +// repeat: The number of times you want the message to be repeated. +// +// Status: Beta / Should be working. +// +// Notes: +// LG has a separate message to indicate a repeat, like NEC does. +// Supports: +// IR Remote models: 6711A20083V +void IRsend::sendLG(uint64_t data, uint16_t nbits, uint16_t repeat) { + uint16_t repeatHeaderMark = 0; + + if (nbits >= kLg32Bits) { + // LG 32bit protocol is near identical to Samsung except for repeats. + sendSAMSUNG(data, nbits, 0); // Send it as a single Samsung message. + repeatHeaderMark = kLg32RptHdrMark; + repeat++; + } else { + // LG (28-bit) protocol. + repeatHeaderMark = kLgHdrMark; + sendGeneric(kLgHdrMark, kLgHdrSpace, kLgBitMark, kLgOneSpace, kLgBitMark, + kLgZeroSpace, kLgBitMark, kLgMinGap, kLgMinMessageLength, data, + nbits, 38, true, 0, // Repeats are handled later. + 50); + } + + // Repeat + // Protocol has a mandatory repeat-specific code sent after every command. + if (repeat) + sendGeneric(repeatHeaderMark, kLgRptSpace, 0, 0, 0, 0, // No data is sent. + kLgBitMark, kLgMinGap, kLgMinMessageLength, 0, 0, // No data. + 38, true, repeat - 1, 50); +} + +// Send an LG Variant-2 formatted message. +// +// Args: +// data: The contents of the message you want to send. +// nbits: The bit size of the message being sent. +// Typically kLgBits or kLg32Bits. +// repeat: The number of times you want the message to be repeated. +// +// Status: Beta / Should be working. +// +// Notes: +// LG has a separate message to indicate a repeat, like NEC does. +// Supports: +// IR Remote models: AKB74395308 +void IRsend::sendLG2(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits >= kLg32Bits) { + // Let the original routine handle it. + sendLG(data, nbits, repeat); // Send it as a single Samsung message. + return; + } + + // LGv2 (28-bit) protocol. + sendGeneric(kLg2HdrMark, kLg2HdrSpace, kLgBitMark, kLgOneSpace, kLgBitMark, + kLgZeroSpace, kLgBitMark, kLgMinGap, kLgMinMessageLength, data, + nbits, 38, true, 0, // Repeats are handled later. + 50); + + // TODO(crackn): Verify the details of what repeat messages look like. + // Repeat + // Protocol has a mandatory repeat-specific code sent after every command. + if (repeat) + sendGeneric(kLg2HdrMark, kLgRptSpace, 0, 0, 0, 0, // No data is sent. + kLgBitMark, kLgMinGap, kLgMinMessageLength, 0, 0, // No data. + 38, true, repeat - 1, 50); +} + +// Construct a raw 28-bit LG message code from the supplied address & command. +// +// Args: +// address: The address code. +// command: The command code. +// Returns: +// A raw 28-bit LG message code suitable for sendLG() etc. +// +// Status: BETA / Should work. +// +// Notes: +// e.g. Sequence of bits = address + command + checksum. +uint32_t IRsend::encodeLG(uint16_t address, uint16_t command) { + return ((address << 20) | (command << 4) | calcLGChecksum(command)); +} +#endif + +#if DECODE_LG +// Decode the supplied LG message. +// LG protocol has a repeat code which is 4 items long. +// Even though the protocol has 28/32 bits of data, only 24/28 bits are +// distinct. +// In transmission order, the 28/32 bits are constructed as follows: +// 8/12 bits of address + 16 bits of command + 4 bits of checksum. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. +// Typically kLgBits or kLg32Bits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should work. +// +// Note: +// LG 32bit protocol appears near identical to the Samsung protocol. +// They possibly differ on how they repeat and initial HDR mark. +// +// Supports: +// IR Remote models: 6711A20083V, AKB74395308 + +// Ref: +// https://funembedded.wordpress.com/2014/11/08/ir-remote-control-for-lg-conditioner-using-stm32f302-mcu-on-mbed-platform/ +bool IRrecv::decodeLG(decode_results *results, uint16_t nbits, bool strict) { + if (nbits >= kLg32Bits) { + if (results->rawlen < 2 * nbits + 2 * (kHeader + kFooter) - 1) + return false; // Can't possibly be a valid LG32 message. + } else { + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid LG message. + } + if (strict && nbits != kLgBits && nbits != kLg32Bits) + return false; // Doesn't comply with expected LG protocol. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + bool isLg2 = false; + + // Header + uint32_t m_tick; + if (matchMark(results->rawbuf[offset], kLgHdrMark)) { + m_tick = results->rawbuf[offset++] * kRawTick / kLgHdrMarkTicks; + } else if (matchMark(results->rawbuf[offset], kLg2HdrMark)) { + m_tick = results->rawbuf[offset++] * kRawTick / kLg2HdrMarkTicks; + isLg2 = true; + } else if (matchMark(results->rawbuf[offset], kLg32HdrMark)) { + m_tick = results->rawbuf[offset++] * kRawTick / kLg32HdrMarkTicks; + } else { + return false; + } + uint32_t s_tick; + if (isLg2) { + if (matchSpace(results->rawbuf[offset], kLg2HdrSpace)) + s_tick = results->rawbuf[offset++] * kRawTick / kLg2HdrSpaceTicks; + else + return false; + } else { + if (matchSpace(results->rawbuf[offset], kLgHdrSpace)) + s_tick = results->rawbuf[offset++] * kRawTick / kLgHdrSpaceTicks; + else if (matchSpace(results->rawbuf[offset], kLg2HdrSpace)) + s_tick = results->rawbuf[offset++] * kRawTick / kLg32HdrSpaceTicks; + else + return false; + } + + // Set up the expected tick sizes based on variant. + uint16_t bitmarkticks; + if (isLg2) { + bitmarkticks = kLg2BitMarkTicks; + } else { + bitmarkticks = kLgBitMarkTicks; + } + + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, bitmarkticks * m_tick, + kLgOneSpaceTicks * s_tick, bitmarkticks * m_tick, + kLgZeroSpaceTicks * s_tick, kTolerance, 0); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Footer + if (!matchMark(results->rawbuf[offset++], bitmarkticks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kLgMinGapTicks * s_tick)) + return false; + + // Repeat + if (nbits >= kLg32Bits) { + // If we are expecting the LG 32-bit protocol, there is always + // a repeat message. So, check for it. + offset++; + if (!matchMark(results->rawbuf[offset++], kLg32RptHdrMarkTicks * m_tick)) + return false; + if (!matchSpace(results->rawbuf[offset++], kLgRptSpaceTicks * s_tick)) + return false; + if (!matchMark(results->rawbuf[offset++], bitmarkticks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kLgMinGapTicks * s_tick)) + return false; + } + + // Compliance + uint16_t command = (data >> 4) & 0xFFFF; // The 16 bits before the checksum. + + if (strict && (data & 0xF) != calcLGChecksum(command)) + return false; // The last 4 bits sent are the expected checksum. + + // Success + if (isLg2) + results->decode_type = LG2; + else + results->decode_type = LG; + results->bits = nbits; + results->value = data; + results->command = command; + results->address = data >> 20; // The bits before the command. + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.h similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_LG.h rename to lib/IRremoteESP8266-2.5.2.03/src/ir_LG.h diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp new file mode 100644 index 000000000..7f0b89ae9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp @@ -0,0 +1,122 @@ +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// LL AAA SSSSS EEEEEEE RRRRRR TTTTTTT AAA GGGG +// LL AAAAA SS EE RR RR TTT AAAAA GG GG +// LL AA AA SSSSS EEEEE RRRRRR TTT AA AA GG +// LL AAAAAAA SS EE RR RR TTT AAAAAAA GG GG +// LLLLLLL AA AA SSSSS EEEEEEE RR RR TTT AA AA GGGGGG + +// Constants +const uint16_t kLasertagMinSamples = 13; +const uint16_t kLasertagTick = 333; +const uint32_t kLasertagMinGap = 100000; // Completely made up amount. +const uint8_t kLasertagTolerance = 0; // Percentage error margin. +const uint16_t kLasertagExcess = 0; // See kMarkExcess. +const uint16_t kLasertagDelta = 150; // Use instead of Excess and Tolerance. +const int16_t kSpace = 1; +const int16_t kMark = 0; + +#if SEND_LASERTAG +// Send a Lasertag packet. +// This protocol is pretty much just raw Manchester encoding. +// +// Args: +// data: The message you wish to send. +// nbits: Bit size of the protocol you want to send. +// repeat: Nr. of extra times the data will be sent. +// +// Status: STABLE / Working. +// +void IRsend::sendLasertag(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits > sizeof(data) * 8) return; // We can't send something that big. + + // Set 36kHz IR carrier frequency & a 1/4 (25%) duty cycle. + // NOTE: duty cycle is not confirmed. Just guessing based on RC5/6 protocols. + enableIROut(36, 25); + + for (uint16_t i = 0; i <= repeat; i++) { + // Data + for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) + if (data & mask) { // 1 + space(kLasertagTick); // 1 is space, then mark. + mark(kLasertagTick); + } else { // 0 + mark(kLasertagTick); // 0 is mark, then space. + space(kLasertagTick); + } + // Footer + space(kLasertagMinGap); + } +} +#endif // SEND_LASERTAG + +#if DECODE_LASERTAG +// Decode the supplied Lasertag message. +// This protocol is pretty much just raw Manchester encoding. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to be working 90% of the time. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/rc5.php +// https://en.wikipedia.org/wiki/RC-5 +// https://en.wikipedia.org/wiki/Manchester_code +bool IRrecv::decodeLasertag(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < kLasertagMinSamples) return false; + + // Compliance + if (strict && nbits != kLasertagBits) return false; + + uint16_t offset = kStartOffset; + uint16_t used = 0; + uint64_t data = 0; + uint16_t actual_bits = 0; + + // No Header + + // Data + for (; offset <= results->rawlen; actual_bits++) { + int16_t levelA = + getRClevel(results, &offset, &used, kLasertagTick, kLasertagTolerance, + kLasertagExcess, kLasertagDelta); + int16_t levelB = + getRClevel(results, &offset, &used, kLasertagTick, kLasertagTolerance, + kLasertagExcess, kLasertagDelta); + if (levelA == kSpace && levelB == kMark) { + data = (data << 1) | 1; // 1 + } else { + if (levelA == kMark && levelB == kSpace) { + data <<= 1; // 0 + } else { + break; + } + } + } + // Footer (None) + + // Compliance + if (actual_bits < nbits) return false; // Less data than we expected. + if (strict && actual_bits != kLasertagBits) return false; + + // Success + results->decode_type = LASERTAG; + results->value = data; + results->address = data & 0xF; // Unit + results->command = data >> 4; // Team + results->repeat = false; + results->bits = actual_bits; + return true; +} +#endif // DECODE_LASERTAG diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp new file mode 100644 index 000000000..00eb9383b --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp @@ -0,0 +1,156 @@ +// Copyright 2018 David Conran + +#define __STDC_LIMIT_MACROS +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// LL UU UU TTTTTTT RRRRRR OOOOO NN NN +// LL UU UU TTT RR RR OO OO NNN NN +// LL UU UU TTT RRRRRR OO OO NN N NN +// LL UU UU TTT RR RR OO OO NN NNN +// LLLLLLL UUUUU TTT RR RR OOOO0 NN NN + +// Notes: +// The Lutron protocol uses a sort of Run Length encoding to encode +// its data. There is no header or footer per-se. +// As a mark is the first data we will notice, we always assume the First +// bit of the technically 36-bit protocol is '1'. So it is assumed, and thus +// we only care about the 35 bits of data. + +// Constants +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/515 +const uint16_t kLutronTick = 2288; +const uint32_t kLutronGap = 150000; // Completely made up value. +const uint16_t kLutronDelta = 400; // +/- 300 usecs. + +#if SEND_LUTRON +// Send a Lutron formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The number of bits of the message to be sent. Typically kLutronBits +// repeat: The number of times the command is to be repeated. +// +// Status: Stable / Appears to be working for real devices. + +// Notes: +// Protocol is really 36 bits long, but the first bit is always a 1. +// So, assume the 1 and only have a normal payload of 35 bits. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/515 +void IRsend::sendLutron(uint64_t data, uint16_t nbits, uint16_t repeat) { + enableIROut(40000, 40); // 40Khz & 40% dutycycle. + for (uint16_t r = 0; r <= repeat; r++) { + mark(kLutronTick); // 1st bit is always '1'. + // Send the supplied data in MSB First order. + for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) + if (data & mask) + mark(kLutronTick); // Send a 1 + else + space(kLutronTick); // Send a 0 + space(kLutronGap); // Inter-message gap. + } +} +#endif // SEND_LUTRON + +#if DECODE_LUTRON +// Decode the supplied Lutron message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kLutronBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +// Notes: +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/515 +bool IRrecv::decodeLutron(decode_results *results, uint16_t nbits, + bool strict) { + // Technically the smallest number of entries for the smallest message is '1'. + // i.e. All the bits set to 1, would produce a single huge mark signal. + // So no minimum length check is required. + if (strict && nbits != kLutronBits) + return false; // Not strictly an Lutron message. + + uint64_t data = 0; + int16_t bitsSoFar = -1; + + if (nbits > sizeof(data) * 8) return false; // To large to store the data. + for (uint16_t offset = kStartOffset; + bitsSoFar < nbits && offset < results->rawlen; offset++) { + uint16_t entry = results->rawbuf[offset]; + // It has to be large enough to qualify as a bit. + if (!matchAtLeast(entry, kLutronTick, 0, kLutronDelta)) { + DPRINTLN("Entry too small. Aborting."); + return false; + } + // Keep reading bits of the same value until we run out. + while (entry != 0 && matchAtLeast(entry, kLutronTick, 0, kLutronDelta)) { + bitsSoFar++; + DPRINT("Bit: "); + DPRINT(bitsSoFar); + if (offset % 2) { // Is Odd? + data = (data << 1) + 1; // Append a '1'. + DPRINTLN(" is a 1."); + } else { // Is it Even? + data <<= 1; // Append a '0'. + DPRINTLN(" is a 0."); + if (bitsSoFar == nbits && matchAtLeast(entry, kLutronGap)) + break; // We've likely reached the end of a message. + } + // Remove a bit length from the current entry. + entry = std::max(entry, (uint16_t)(kLutronTick / kRawTick)) - + kLutronTick / kRawTick; + } + if (offset % 2 && !match(entry, kLutronDelta, 0, kLutronDelta)) { + DPRINT("offset = "); + DPRINTLN(offset); + DPRINT("rawlen = "); + DPRINTLN(results->rawlen); + DPRINT("entry = "); + DPRINTLN(entry); + DPRINTLN("Odd Entry has too much left over. Aborting."); + return false; // Too much left over to be a good value. Reject it. + } + if (offset % 2 == 0 && offset <= results->rawlen - 1 && + !matchAtLeast(entry, kLutronDelta, 0, kLutronDelta)) { + DPRINT("offset = "); + DPRINTLN(offset); + DPRINT("rawlen = "); + DPRINTLN(results->rawlen); + DPRINT("entry = "); + DPRINTLN(entry); + DPRINTLN("Entry has too much left over. Aborting."); + return false; // Too much left over to be a good value. Reject it. + } + } + + // We got too many bits. + if (bitsSoFar > nbits || bitsSoFar < 0) { + DPRINTLN("Wrong number of bits found. Aborting."); + return false; + } + // If we got less bits than we were expecting, we need to pad with zeros + // until we get the correct number of bits. + if (bitsSoFar < nbits) data <<= (nbits - bitsSoFar); + + // Success + DPRINTLN("Lutron Success!"); + results->decode_type = LUTRON; + results->bits = bitsSoFar; + results->value = data ^ (1ULL << nbits); // Mask off the initial '1'. + results->address = 0; + results->command = 0; + return true; +} +#endif // DECODE_LUTRON diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp new file mode 100644 index 000000000..a75e99e3a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp @@ -0,0 +1,202 @@ +// Copyright 2018 Brett T. Warden +// derived from ir_Lasertag.cpp, Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// MM MM WW WW MM MM +// MMM MMM WW WW MMM MMM +// MM M MM WW W WW MM M MM +// MM MM WWW WWW MM MM +// MM MM WW WW MM MM + +// Constants +const uint16_t kMWMMinSamples = 6; // Msgs are >=3 bytes, bytes have >=2 + // samples +const uint16_t kMWMTick = 417; +const uint32_t kMWMMinGap = 30000; // Typical observed delay b/w commands +const uint8_t kMWMTolerance = 0; // Percentage error margin. +const uint16_t kMWMExcess = 0; // See kMarkExcess. +const uint16_t kMWMDelta = 150; // Use instead of Excess and Tolerance. +const uint8_t kMWMMaxWidth = 9; // Maximum number of successive bits at a + // single level - worst case +const int16_t kSpace = 1; +const int16_t kMark = 0; + +#if SEND_MWM +// Send a MWM packet. +// This protocol is 2400 bps serial, 1 start bit (mark), 1 stop bit (space), no +// parity +// +// Args: +// data: The message you wish to send. +// nbits: Bit size of the protocol you want to send. +// repeat: Nr. of extra times the data will be sent. +// +// Status: Implemented. +// +void IRsend::sendMWM(uint8_t data[], uint16_t nbytes, uint16_t repeat) { + if (nbytes < 3) return; // Shortest possible message is 3 bytes + + // Set 38kHz IR carrier frequency & a 1/4 (25%) duty cycle. + // NOTE: duty cycle is not confirmed. Just guessing based on RC5/6 protocols. + enableIROut(38, 25); + + for (uint16_t r = 0; r <= repeat; r++) { + // Data + for (uint16_t i = 0; i < nbytes; i++) { + uint8_t byte = data[i]; + + // Start bit + mark(kMWMTick); + + // LSB first, space=1 + for (uint8_t mask = 0x1; mask; mask <<= 1) { + if (byte & mask) { // 1 + space(kMWMTick); + } else { // 0 + mark(kMWMTick); + } + } + // Stop bit + space(kMWMTick); + } + // Footer + space(kMWMMinGap); + } +} +#endif // SEND_MWM + +#if DECODE_MWM +// Decode the supplied MWM message. +// This protocol is 2400 bps serial, 1 start bit (mark), 1 stop bit (space), no +// parity +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Implemented. +// +bool IRrecv::decodeMWM(decode_results *results, uint16_t nbits, bool strict) { + DPRINTLN("DEBUG: decodeMWM"); + + // Compliance + if (results->rawlen < kMWMMinSamples) { + DPRINTLN("DEBUG: decodeMWM: too few samples"); + return false; + } + + uint16_t offset = kStartOffset; + uint16_t used = 0; + uint64_t data = 0; + uint16_t frame_bits = 0; + uint16_t data_bits = 0; + + // No Header + + // Data + uint8_t bits_per_frame = 10; + for (; offset < results->rawlen && results->bits < 8 * kStateSizeMax; + frame_bits++) { + DPRINT("DEBUG: decodeMWM: offset = "); + DPRINTLN(uint64ToString(offset)); + int16_t level = getRClevel(results, &offset, &used, kMWMTick, kMWMTolerance, + kMWMExcess, kMWMDelta, kMWMMaxWidth); + if (level < 0) { + DPRINTLN("DEBUG: decodeMWM: getRClevel returned error"); + break; + } + switch (frame_bits % bits_per_frame) { + case 0: + // Start bit + if (level != kMark) { + DPRINTLN("DEBUG: decodeMWM: framing error - invalid start bit"); + goto done; + } + break; + case 9: + // Stop bit + if (level != kSpace) { + DPRINTLN("DEBUG: decodeMWM: framing error - invalid stop bit"); + return false; + } else { + DPRINT("DEBUG: decodeMWM: data_bits = "); + DPRINTLN(data_bits); + DPRINT("DEBUG: decodeMWM: Finished byte: "); + DPRINTLN(data); + results->state[data_bits / 8 - 1] = data & 0xFF; + results->bits = data_bits; + data = 0; + } + break; + default: + // Data bits + DPRINT("DEBUG: decodeMWM: Storing bit: "); + DPRINTLN((level == kSpace)); + // Transmission is LSB-first, space=1 + data |= ((level == kSpace)) << 8; + data >>= 1; + data_bits++; + break; + } + } + +done: + // Footer (None) + + // Compliance + DPRINT("DEBUG: decodeMWM: frame_bits = "); + DPRINTLN(frame_bits); + DPRINT("DEBUG: decodeMWM: data_bits = "); + DPRINTLN(data_bits); + if (data_bits < nbits) { + DPRINT("DEBUG: decodeMWM: too few bits; expected "); + DPRINTLN(nbits); + return false; // Less data than we expected. + } + + uint16_t payload_length = 0; + switch (results->state[0] & 0xf0) { + case 0x90: + case 0xf0: + // Normal commands + payload_length = results->state[0] & 0x0f; + DPRINT("DEBUG: decodeMWM: payload_length = "); + DPRINTLN(payload_length); + break; + default: + if (strict) { + // Show commands + if (results->state[0] != 0x55 && results->state[1] != 0xAA) { + return false; + } + } + break; + } + if (data_bits < (payload_length + 3) * 8) { + DPRINT("DEBUG: decodeMWM: too few bytes; expected "); + DPRINTLN((payload_length + 3)); + return false; + } + if (strict) { + if (payload_length && (data_bits > (payload_length + 3) * 8)) { + DPRINT("DEBUG: decodeMWM: too many bytes; expected "); + DPRINTLN((payload_length + 3)); + return false; + } + } + + // Success + results->decode_type = MWM; + results->repeat = false; + return true; +} +#endif // DECODE_MWM + +// vim: et:ts=2:sw=2 diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp new file mode 100644 index 000000000..863aa0ec3 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp @@ -0,0 +1,166 @@ +// Copyright 2013 mpflaga +// Copyright 2015 kitlaan +// Copyright 2017 Jason kendall, David Conran + +#include "ir_Magiquest.h" +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +#define IS_ZERO(m, s) (((m)*100 / ((m) + (s))) <= kMagiQuestZeroRatio) +#define IS_ONE(m, s) (((m)*100 / ((m) + (s))) >= kMagiQuestOneRatio) + +// Strips taken from: +// https://github.com/kitlaan/Arduino-IRremote/blob/master/ir_Magiquest.cpp +// and +// https://github.com/mpflaga/Arduino-IRremote + +// Source: https://github.com/mpflaga/Arduino-IRremote + +#if SEND_MAGIQUEST +// Send a MagiQuest formatted message. +// +// Args: +// data: The contents of the message you want to send. +// nbits: The bit size of the message being sent. +// Typically kMagiquestBits. +// repeat: The number of times you want the message to be repeated. +// +// Status: Alpha / Should be working. +// +void IRsend::sendMagiQuest(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(0, 0, // No Headers - Technically it's included in the data. + // i.e. 8 zeros. + kMagiQuestMarkOne, kMagiQuestSpaceOne, kMagiQuestMarkZero, + kMagiQuestSpaceZero, + 0, // No footer mark. + kMagiQuestGap, data, nbits, 36, true, repeat, 50); +} + +// Encode a MagiQuest wand_id, and a magnitude into a single 64bit value. +// (Only 48 bits of real data + 8 leading zero bits) +// This is suitable for calling sendMagiQuest() with. +// e.g. sendMagiQuest(encodeMagiQuest(wand_id, magnitude)); +uint64_t IRsend::encodeMagiQuest(uint32_t wand_id, uint16_t magnitude) { + uint64_t result = 0; + result = wand_id; + result <<= 16; + result |= magnitude; + // Shouldn't be needed, but ensure top 8/16 bit are zero. + result &= 0xFFFFFFFFFFFFULL; + return result; +} +#endif + +// Source: +// https://github.com/kitlaan/Arduino-IRremote/blob/master/ir_Magiquest.cpp + +#if DECODE_MAGIQUEST +// Decode the supplied MagiQuest message. +// MagiQuest protocol appears to be a header of 8 'zero' bits, followed +// by 32 bits of "wand ID" and finally 16 bits of "magnitude". +// Even though we describe this protocol as 56 bits, it really only has +// 48 bits of data that matter. +// +// In transmission order, 8 zeros + 32 wand_id + 16 magnitude. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion, inc. the 8 bit header. +// Typically kMagiquestBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Should work. +// +// Ref: +// https://github.com/kitlaan/Arduino-IRremote/blob/master/ir_Magiquest.cpp +bool IRrecv::decodeMagiQuest(decode_results *results, uint16_t nbits, + bool strict) { + uint16_t bits = 0; + uint64_t data = 0; + uint16_t offset = kStartOffset; + + if (results->rawlen < (2 * kMagiquestBits)) { + DPRINT("Not enough bits to be Magiquest - Rawlen: "); + DPRINT(results->rawlen); + DPRINT(" Expected: "); + DPRINTLN((2 * kMagiquestBits)); + return false; + } + + // Compliance + if (strict && nbits != kMagiquestBits) return false; + + // Of six wands as datapoints, so far they all start with 8 ZEROs. + // For example, here is the data from two wands + // 00000000 00100011 01001100 00100110 00000010 00000010 00010111 + // 00000000 00100000 10001000 00110001 00000010 00000010 10110100 + + // Decode the (MARK + SPACE) bits + while (offset + 1 < results->rawlen && bits < nbits - 1) { + uint16_t mark = results->rawbuf[offset]; + uint16_t space = results->rawbuf[offset + 1]; + if (!matchMark(mark + space, kMagiQuestTotalUsec)) { + DPRINT("Not enough time to be Magiquest - Mark: "); + DPRINT(mark); + DPRINT(" Space: "); + DPRINT(space); + DPRINT(" Total: "); + DPRINT(mark + space); + DPRINT("Expected: "); + DPRINTLN(kMagiQuestTotalUsec); + return false; + } + + if (IS_ZERO(mark, space)) + data = (data << 1) | 0; + else if (IS_ONE(mark, space)) + data = (data << 1) | 1; + else + return false; + + bits++; + offset += 2; + + // Compliance + // The first 8 bits of this protocol are supposed to all be 0. + // Exit out early as it is never going to match. + if (strict && bits == 8 && data != 0) return false; + } + + // Last bit is special as the protocol ends with a SPACE, not a MARK. + // Grab the last MARK bit, assuming a good SPACE after it + if (offset < results->rawlen) { + uint16_t mark = results->rawbuf[offset]; + uint16_t space = (kMagiQuestTotalUsec / kRawTick) - mark; + + if (IS_ZERO(mark, space)) + data = (data << 1) | 0; + else if (IS_ONE(mark, space)) + data = (data << 1) | 1; + else + return false; + + bits++; + } + + if (bits != nbits) return false; + + if (strict) { + // The top 8 bits of the 56 bits needs to be 0x00 to be valid. + // i.e. bits 56 to 49 are all zero. + if ((data >> (nbits - 8)) != 0) return false; + } + + // Success + results->decode_type = MAGIQUEST; + results->bits = bits; + results->value = data; + results->address = data >> 16; // Wand ID + results->command = data & 0xFFFF; // Magnitude + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h new file mode 100644 index 000000000..d2d82d152 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h @@ -0,0 +1,35 @@ +// Copyright 2013 mpflaga +// Copyright 2015 kitlaan +// Copyright 2017 Jason kendall, David Conran + +#ifndef IR_MAGIQUEST_H_ +#define IR_MAGIQUEST_H_ + +#define __STDC_LIMIT_MACROS +#include +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// MagiQuest packet is both Wand ID and magnitude of swish and flick +union magiquest { + uint64_t llword; + uint8_t byte[8]; + // uint16_t word[4]; + uint32_t lword[2]; + struct { + uint16_t magnitude; + uint32_t wand_id; + uint8_t padding; + uint8_t scrap; + } cmd; +}; + +const uint16_t kMagiQuestTotalUsec = 1150; +const uint8_t kMagiQuestZeroRatio = 30; // usually <= ~25% +const uint8_t kMagiQuestOneRatio = 38; // usually >= ~50% +const uint16_t kMagiQuestMarkZero = 280; +const uint16_t kMagiQuestSpaceZero = 850; +const uint16_t kMagiQuestMarkOne = 580; +const uint16_t kMagiQuestSpaceOne = 600; +const uint32_t kMagiQuestGap = 100000; // A guess of the gap between messages +#endif // IR_MAGIQUEST_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp new file mode 100644 index 000000000..8e55c7d22 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp @@ -0,0 +1,403 @@ +// Copyright 2017 bwze, crankyoldgit + +#include "ir_Midea.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// MM MM IIIII DDDDD EEEEEEE AAA +// MMM MMM III DD DD EE AAAAA +// MM MM MM III DD DD EEEEE AA AA +// MM MM III DD DD EE AAAAAAA +// MM MM IIIII DDDDDD EEEEEEE AA AA + +// Midea A/C added by (send) bwze/crankyoldgit & (decode) crankyoldgit +// +// Equipment it seems compatible with: +// * Pioneer System Model RYBO12GMFILCAD (12K BTU) +// * Pioneer System Model RUBO18GMFILCAD (18K BTU) +// * + +// Ref: +// https://docs.google.com/spreadsheets/d/1TZh4jWrx4h9zzpYUI9aYXMl1fYOiqu-xVuOOMqagxrs/edit?usp=sharing + +// Constants +const uint16_t kMideaTick = 80; +const uint16_t kMideaBitMarkTicks = 7; +const uint16_t kMideaBitMark = kMideaBitMarkTicks * kMideaTick; +const uint16_t kMideaOneSpaceTicks = 21; +const uint16_t kMideaOneSpace = kMideaOneSpaceTicks * kMideaTick; +const uint16_t kMideaZeroSpaceTicks = 7; +const uint16_t kMideaZeroSpace = kMideaZeroSpaceTicks * kMideaTick; +const uint16_t kMideaHdrMarkTicks = 56; +const uint16_t kMideaHdrMark = kMideaHdrMarkTicks * kMideaTick; +const uint16_t kMideaHdrSpaceTicks = 56; +const uint16_t kMideaHdrSpace = kMideaHdrSpaceTicks * kMideaTick; +const uint16_t kMideaMinGapTicks = + kMideaHdrMarkTicks + kMideaZeroSpaceTicks + kMideaBitMarkTicks; +const uint16_t kMideaMinGap = kMideaMinGapTicks * kMideaTick; +const uint8_t kMideaTolerance = 30; // Percent + +#if SEND_MIDEA +// Send a Midea message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMideaBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: Alpha / Needs testing against a real device. +// +void IRsend::sendMidea(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits % 8 != 0) return; // nbits is required to be a multiple of 8. + + // Set IR carrier frequency + enableIROut(38); + + for (uint16_t r = 0; r <= repeat; r++) { + // The protcol sends the message, then follows up with an entirely + // inverted payload. + for (size_t inner_loop = 0; inner_loop < 2; inner_loop++) { + // Header + mark(kMideaHdrMark); + space(kMideaHdrSpace); + // Data + // Break data into byte segments, starting at the Most Significant + // Byte. Each byte then being sent normal, then followed inverted. + for (uint16_t i = 8; i <= nbits; i += 8) { + // Grab a bytes worth of data. + uint8_t segment = (data >> (nbits - i)) & 0xFF; + sendData(kMideaBitMark, kMideaOneSpace, kMideaBitMark, kMideaZeroSpace, + segment, 8, true); + } + // Footer + mark(kMideaBitMark); + space(kMideaMinGap); // Pause before repeating + + // Invert the data for the 2nd phase of the message. + // As we get called twice in the inner loop, we will always revert + // to the original 'data' state. + data = ~data; + } + } +} +#endif + +// Code to emulate Midea A/C IR remote control unit. +// Warning: Consider this very alpha code. + +// Initialise the object. +IRMideaAC::IRMideaAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRMideaAC::stateReset() { + // Power On, Mode Auto, Fan Auto, Temp = 25C/77F + remote_state = 0xA1826FFFFF62; +} + +// Configure the pin for output. +void IRMideaAC::begin() { _irsend.begin(); } + +#if SEND_MIDEA +// Send the current desired state to the IR LED. +void IRMideaAC::send() { + checksum(); // Ensure correct checksum before sending. + _irsend.sendMidea(remote_state); +} +#endif // SEND_MIDEA + +// Return a pointer to the internal state date of the remote. +uint64_t IRMideaAC::getRaw() { + checksum(); + return remote_state & kMideaACStateMask; +} + +// Override the internal state with the new state. +void IRMideaAC::setRaw(uint64_t newState) { + remote_state = newState & kMideaACStateMask; +} + +// Set the requested power state of the A/C to off. +void IRMideaAC::on() { remote_state |= kMideaACPower; } + +// Set the requested power state of the A/C to off. +void IRMideaAC::off() { remote_state &= (kMideaACStateMask ^ kMideaACPower); } + +// Set the requested power state of the A/C. +void IRMideaAC::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +// Return the requested power state of the A/C. +bool IRMideaAC::getPower() { return (remote_state & kMideaACPower); } + +// Set the temperature. +// Args: +// temp: Temp. in degrees. +// useCelsius: Degree type to use. Celsius (true) or Fahrenheit (false) +void IRMideaAC::setTemp(const uint8_t temp, const bool useCelsius) { + uint8_t new_temp = temp; + if (useCelsius) { + new_temp = std::max(kMideaACMinTempC, new_temp); + new_temp = std::min(kMideaACMaxTempC, new_temp); + new_temp = (uint8_t)((new_temp * 1.8) + 32.5); // 0.5 so we rounding. + } + new_temp = std::max(kMideaACMinTempF, new_temp); + new_temp = std::min(kMideaACMaxTempF, new_temp); + new_temp -= kMideaACMinTempF; + remote_state &= kMideaACTempMask; + remote_state |= ((uint64_t)new_temp << 24); +} + +// Return the set temp. +// Args: +// useCelsius: Flag indicating if the results are in Celsius or Fahrenheit. +// Returns: +// A uint8_t containing the temperature. +uint8_t IRMideaAC::getTemp(const bool useCelsius) { + uint8_t temp = ((remote_state >> 24) & 0x1F) + kMideaACMinTempF; + if (useCelsius) { + temp = (uint8_t)((temp - 32) / 1.8); + } + return temp; +} + +// Set the speed of the fan, +// 1-3 set the speed, 0 or anything else set it to auto. +void IRMideaAC::setFan(const uint8_t fan) { + uint64_t new_fan; + switch (fan) { + case kMideaACFanLow: + case kMideaACFanMed: + case kMideaACFanHigh: + new_fan = fan; + break; + default: + new_fan = kMideaACFanAuto; + } + remote_state &= kMideaACFanMask; + remote_state |= (new_fan << 35); +} + +// Return the requested state of the unit's fan. +uint8_t IRMideaAC::getFan() { return (remote_state >> 35) & 0b111; } + +// Get the requested climate operation mode of the a/c unit. +// Returns: +// A uint8_t containing the A/C mode. +uint8_t IRMideaAC::getMode() { return ((remote_state >> 32) & 0b111); } + +// Set the requested climate operation mode of the a/c unit. +void IRMideaAC::setMode(const uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + uint64_t new_mode; + switch (mode) { + case kMideaACAuto: + case kMideaACCool: + case kMideaACHeat: + case kMideaACDry: + case kMideaACFan: + new_mode = mode; + break; + default: + new_mode = kMideaACAuto; + } + remote_state &= kMideaACModeMask; + remote_state |= (new_mode << 32); +} + +// Set the Sleep state of the A/C. +void IRMideaAC::setSleep(const bool state) { + if (state) + remote_state |= kMideaACSleep; + else + remote_state &= (kMideaACStateMask ^ kMideaACSleep); +} + +// Return the Sleep state of the A/C. +bool IRMideaAC::getSleep() { return (remote_state & kMideaACSleep); } + +// Calculate the checksum for a given array. +// Args: +// state: The state to calculate the checksum over. +// Returns: +// The 8 bit checksum value. +uint8_t IRMideaAC::calcChecksum(const uint64_t state) { + uint8_t sum = 0; + uint64_t temp_state = state; + + for (uint8_t i = 0; i < 5; i++) { + temp_state >>= 8; + sum += reverseBits((temp_state & 0xFF), 8); + } + sum = 256 - sum; + return reverseBits(sum, 8); +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The state to verify the checksum of. +// Returns: +// A boolean. +bool IRMideaAC::validChecksum(const uint64_t state) { + return ((state & 0xFF) == calcChecksum(state)); +} + +// Calculate & set the checksum for the current internal state of the remote. +void IRMideaAC::checksum() { + // Stored the checksum value in the last byte. + remote_state &= kMideaACChecksumMask; + remote_state |= calcChecksum(remote_state); +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRMideaAC::toString() { + String result = ""; +#else +std::string IRMideaAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kMideaACAuto: + result += " (AUTO)"; + break; + case kMideaACCool: + result += " (COOL)"; + break; + case kMideaACHeat: + result += " (HEAT)"; + break; + case kMideaACDry: + result += " (DRY)"; + break; + case kMideaACFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp(true)) + "C/" + + uint64ToString(getTemp(false)) + "F"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kMideaACFanAuto: + result += " (AUTO)"; + break; + case kMideaACFanLow: + result += " (LOW)"; + break; + case kMideaACFanMed: + result += " (MED)"; + break; + case kMideaACFanHigh: + result += " (HI)"; + break; + } + result += ", Sleep: "; + if (getSleep()) + result += "On"; + else + result += "Off"; + return result; +} + +#if DECODE_MIDEA +// Decode the supplied Midea message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kMideaBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Needs testing against a real device. +// +bool IRrecv::decodeMidea(decode_results *results, uint16_t nbits, bool strict) { + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + uint8_t min_nr_of_messages = 1; + if (strict) { + if (nbits != kMideaBits) return false; // Not strictly a MIDEA message. + min_nr_of_messages = 2; + } + + // The protocol sends the data normal + inverted, alternating on + // each byte. Hence twice the number of expected data bits. + if (results->rawlen < + min_nr_of_messages * (2 * nbits + kHeader + kFooter) - 1) + return false; // Can't possibly be a valid MIDEA message. + + uint64_t data = 0; + uint64_t inverted = 0; + uint16_t offset = kStartOffset; + + if (nbits > sizeof(data) * 8) + return false; // We can't possibly capture a Midea packet that big. + + for (uint8_t i = 0; i < min_nr_of_messages; i++) { + // Header + if (!matchMark(results->rawbuf[offset], kMideaHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kMideaHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kMideaHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kMideaHdrSpaceTicks; + + // Data (Normal) + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits, kMideaBitMarkTicks * m_tick, + kMideaOneSpaceTicks * s_tick, kMideaBitMarkTicks * m_tick, + kMideaZeroSpaceTicks * s_tick, kMideaTolerance); + if (data_result.success == false) return false; + offset += data_result.used; + if (i % 2 == 0) + data = data_result.data; + else + inverted = data_result.data; + + // Footer + if (!matchMark(results->rawbuf[offset++], kMideaBitMarkTicks * m_tick, + kMideaTolerance)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kMideaMinGapTicks * s_tick, + kMideaTolerance)) + return false; + } + + // Compliance + if (strict) { + // Protocol requires a second message with all the data bits inverted. + // We should have checked we got a second message in the previous loop. + // Just need to check it's value is an inverted copy of the first message. + uint64_t mask = (1ULL << kMideaBits) - 1; + if ((data & mask) != ((inverted ^ mask) & mask)) return false; + if (!IRMideaAC::validChecksum(data)) return false; + } + + // Success + results->decode_type = MIDEA; + results->bits = nbits; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +#endif // DECODE_MIDEA diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h new file mode 100644 index 000000000..aa9f94a92 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h @@ -0,0 +1,103 @@ +// Copyright 2017 David Conran +#ifndef IR_MIDEA_H_ +#define IR_MIDEA_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef ARDUINO +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// MM MM IIIII DDDDD EEEEEEE AAA +// MMM MMM III DD DD EE AAAAA +// MM MM MM III DD DD EEEEE AA AA +// MM MM III DD DD EE AAAAAAA +// MM MM IIIII DDDDDD EEEEEEE AA AA + +// Midea added by crankyoldgit & bwze +// Ref: +// https://docs.google.com/spreadsheets/d/1TZh4jWrx4h9zzpYUI9aYXMl1fYOiqu-xVuOOMqagxrs/edit?usp=sharing + +// Constants +const uint8_t kMideaACCool = 0; // 0b000 +const uint8_t kMideaACDry = 1; // 0b001 +const uint8_t kMideaACAuto = 2; // 0b010 +const uint8_t kMideaACHeat = 3; // 0b011 +const uint8_t kMideaACFan = 4; // 0b100 +const uint8_t kMideaACFanAuto = 0; // 0b000 +const uint8_t kMideaACFanLow = 1; // 0b001 +const uint8_t kMideaACFanMed = 2; // 0b010 +const uint8_t kMideaACFanHigh = 3; // 0b011 +const uint64_t kMideaACPower = 1ULL << 39; +const uint64_t kMideaACSleep = 1ULL << 38; +const uint8_t kMideaACMinTempF = 62; // Fahrenheit +const uint8_t kMideaACMaxTempF = 86; // Fahrenheit +const uint8_t kMideaACMinTempC = 16; // Celsius +const uint8_t kMideaACMaxTempC = 30; // Celsius +const uint64_t kMideaACStateMask = 0x0000FFFFFFFFFFFF; +const uint64_t kMideaACTempMask = 0x0000FFFFE0FFFFFF; +const uint64_t kMideaACFanMask = 0x0000FFC7FFFFFFFF; +const uint64_t kMideaACModeMask = 0x0000FFF8FFFFFFFF; +const uint64_t kMideaACChecksumMask = 0x0000FFFFFFFFFF00; + +// Legacy defines. (Deprecated) +#define MIDEA_AC_COOL kMideaACCool +#define MIDEA_AC_DRY kMideaACDry +#define MIDEA_AC_AUTO kMideaACAuto +#define MIDEA_AC_HEAT kMideaACHeat +#define MIDEA_AC_FAN kMideaACFan +#define MIDEA_AC_FAN_AUTO kMideaACFanAuto +#define MIDEA_AC_FAN_LOW kMideaACFanLow +#define MIDEA_AC_FAN_MED kMideaACFanMed +#define MIDEA_AC_FAN_HI kMideaACFanHigh +#define MIDEA_AC_POWER kMideaACPower +#define MIDEA_AC_SLEEP kMideaACSleep +#define MIDEA_AC_MIN_TEMP_F kMideaACMinTempF +#define MIDEA_AC_MAX_TEMP_F kMideaACMaxTempF +#define MIDEA_AC_MIN_TEMP_C kMideaACMinTempC +#define MIDEA_AC_MAX_TEMP_C kMideaACMaxTempC + +class IRMideaAC { + public: + explicit IRMideaAC(uint16_t pin); + + void stateReset(); +#if SEND_MIDEA + void send(); +#endif // SEND_MIDEA + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp, const bool useCelsius = false); + uint8_t getTemp(const bool useCelsius = false); + void setFan(const uint8_t fan); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setRaw(uint64_t newState); + uint64_t getRaw(); + static bool validChecksum(const uint64_t state); + void setSleep(const bool state); + bool getSleep(); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif +#ifndef UNIT_TEST + + private: +#endif + uint64_t remote_state; + void checksum(); + static uint8_t calcChecksum(const uint64_t state); + IRsend _irsend; +}; + +#endif // IR_MIDEA_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp new file mode 100644 index 000000000..b092c27b9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp @@ -0,0 +1,714 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017-2018 David Conran +// Copyright 2018 Denes Varga + +#include "ir_Mitsubishi.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII +// M M M I T S U U B B I S H H I +// M M M I T SSS U U BBBB I SSS HHHHH I +// M M I T S U U B B I S H H I +// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII + +// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote +// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran + +// Constants +// Mitsubishi TV +// period time is 1/33000Hz = 30.303 uSeconds (T) +// Ref: +// GlobalCache's Control Tower's Mitsubishi TV data. +// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp +const uint16_t kMitsubishiTick = 30; +const uint16_t kMitsubishiBitMarkTicks = 10; +const uint16_t kMitsubishiBitMark = kMitsubishiBitMarkTicks * kMitsubishiTick; +const uint16_t kMitsubishiOneSpaceTicks = 70; +const uint16_t kMitsubishiOneSpace = kMitsubishiOneSpaceTicks * kMitsubishiTick; +const uint16_t kMitsubishiZeroSpaceTicks = 30; +const uint16_t kMitsubishiZeroSpace = + kMitsubishiZeroSpaceTicks * kMitsubishiTick; +const uint16_t kMitsubishiMinCommandLengthTicks = 1786; +const uint16_t kMitsubishiMinCommandLength = + kMitsubishiMinCommandLengthTicks * kMitsubishiTick; +const uint16_t kMitsubishiMinGapTicks = 936; +const uint16_t kMitsubishiMinGap = kMitsubishiMinGapTicks * kMitsubishiTick; + +// Mitsubishi Projector (HC3000) +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/441 + +const uint16_t kMitsubishi2HdrMark = 8400; +const uint16_t kMitsubishi2HdrSpace = kMitsubishi2HdrMark / 2; +const uint16_t kMitsubishi2BitMark = 560; +const uint16_t kMitsubishi2ZeroSpace = 520; +const uint16_t kMitsubishi2OneSpace = kMitsubishi2ZeroSpace * 3; +const uint16_t kMitsubishi2MinGap = 28500; + +// Mitsubishi A/C +// Ref: +// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L84 + +const uint16_t kMitsubishiAcHdrMark = 3400; +const uint16_t kMitsubishiAcHdrSpace = 1750; +const uint16_t kMitsubishiAcBitMark = 450; +const uint16_t kMitsubishiAcOneSpace = 1300; +const uint16_t kMitsubishiAcZeroSpace = 420; +const uint16_t kMitsubishiAcRptMark = 440; +const uint16_t kMitsubishiAcRptSpace = 17100; + +#if SEND_MITSUBISHI +// Send a Mitsubishi message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMitsubishiBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: ALPHA / untested. +// +// Notes: +// This protocol appears to have no header. +// Ref: +// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp +// GlobalCache's Control Tower's Mitsubishi TV data. +void IRsend::sendMitsubishi(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(0, 0, // No Header + kMitsubishiBitMark, kMitsubishiOneSpace, kMitsubishiBitMark, + kMitsubishiZeroSpace, kMitsubishiBitMark, kMitsubishiMinGap, + kMitsubishiMinCommandLength, data, nbits, 33, true, repeat, 50); +} +#endif // SEND_MITSUBISHI + +#if DECODE_MITSUBISHI +// Decode the supplied Mitsubishi message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / previously working. +// +// Notes: +// This protocol appears to have no header. +// +// Ref: +// GlobalCache's Control Tower's Mitsubishi TV data. +bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kFooter - 1) + return false; // Shorter than shortest possibly expected. + if (strict && nbits != kMitsubishiBits) + return false; // Request is out of spec. + + uint16_t offset = kStartOffset; + uint64_t data = 0; + + // No Header + // But try to auto-calibrate off the initial mark signal. + if (!matchMark(results->rawbuf[offset], kMitsubishiBitMark, 30)) return false; + // Calculate how long the common tick time is based on the initial mark. + uint32_t tick = results->rawbuf[offset] * kRawTick / kMitsubishiBitMarkTicks; + + // Data + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits, kMitsubishiBitMarkTicks * tick, + kMitsubishiOneSpaceTicks * tick, kMitsubishiBitMarkTicks * tick, + kMitsubishiZeroSpaceTicks * tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + uint16_t actualBits = data_result.used / 2; + + // Footer + if (!matchMark(results->rawbuf[offset++], kMitsubishiBitMarkTicks * tick, 30)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kMitsubishiMinGapTicks * tick)) + return false; + + // Compliance + if (actualBits < nbits) return false; + if (strict && actualBits != nbits) return false; // Not as we expected. + + // Success + results->decode_type = MITSUBISHI; + results->bits = actualBits; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +#endif // DECODE_MITSUBISHI + +#if SEND_MITSUBISHI2 +// Send a Mitsubishi2 message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMitsubishiBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: ALPHA / untested. +// +// Notes: +// Based on a Mitsubishi HC3000 projector's remote. +// This protocol appears to have a manditory in-protocol repeat. +// That is in *addition* to the entire message needing to be sent twice +// for the device to accept the command. That is separate from the repeat. +// i.e. Allegedly, the real remote requires the "OFF" button pressed twice. +// You will need to add a suitable gap yourself. +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/441 +void IRsend::sendMitsubishi2(uint64_t data, uint16_t nbits, uint16_t repeat) { + for (uint16_t i = 0; i <= repeat; i++) { + // First half of the data. + sendGeneric(kMitsubishi2HdrMark, kMitsubishi2HdrSpace, kMitsubishi2BitMark, + kMitsubishi2OneSpace, kMitsubishi2BitMark, + kMitsubishi2ZeroSpace, kMitsubishi2BitMark, + kMitsubishi2HdrSpace, data >> (nbits / 2), nbits / 2, 33, true, + 0, 50); + // Second half of the data. + sendGeneric(0, 0, // No header for the second data block + kMitsubishi2BitMark, kMitsubishi2OneSpace, kMitsubishi2BitMark, + kMitsubishi2ZeroSpace, kMitsubishi2BitMark, kMitsubishi2MinGap, + data & ((1 << (nbits / 2)) - 1), nbits / 2, 33, true, 0, 50); + } +} +#endif // SEND_MITSUBISHI2 + +#if DECODE_MITSUBISHI2 +// Decode the supplied Mitsubishi2 message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Works with simulated data. +// +// Notes: +// Hardware supported: +// * Mitsubishi HC3000 projector's remote. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/441 +bool IRrecv::decodeMitsubishi2(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kHeader + (kFooter * 2) - 1) + return false; // Shorter than shortest possibly expected. + if (strict && nbits != kMitsubishiBits) + return false; // Request is out of spec. + + uint16_t offset = kStartOffset; + uint64_t data = 0; + uint16_t actualBits = 0; + + // Header + if (!matchMark(results->rawbuf[offset++], kMitsubishi2HdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kMitsubishi2HdrSpace)) + return false; + for (uint8_t i = 1; i <= 2; i++) { + // Data + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits / 2, kMitsubishi2BitMark, + kMitsubishi2OneSpace, kMitsubishi2BitMark, kMitsubishi2ZeroSpace); + if (data_result.success == false) return false; + data <<= nbits / 2; + data += data_result.data; + offset += data_result.used; + actualBits += data_result.used / 2; + + // Footer + if (!matchMark(results->rawbuf[offset++], kMitsubishi2BitMark)) + return false; + if (i % 2) { // Every odd data block, we expect a HDR space. + if (!matchSpace(results->rawbuf[offset++], kMitsubishi2HdrSpace)) + return false; + } else { // Every even data block, we expect Min Gap or end of the message. + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kMitsubishi2MinGap)) + return false; + } + } + + // Compliance + if (actualBits < nbits) return false; + if (strict && actualBits != nbits) return false; // Not as we expected. + + // Success + results->decode_type = MITSUBISHI2; + results->bits = actualBits; + results->value = data; + results->address = data >> actualBits / 2; + results->command = data & ((1 << (actualBits / 2)) - 1); + return true; +} +#endif // DECODE_MITSUBISHI2 + +#if SEND_MITSUBISHI_AC +// Send a Mitsubishi A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kMitsubishiACStateLength) +// repeat: Nr. of times the message is to be repeated. +// (Default = kMitsubishiACMinRepeat). +// +// Status: BETA / Appears to be working. +// +void IRsend::sendMitsubishiAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kMitsubishiACStateLength) + return; // Not enough bytes to send a proper message. + + sendGeneric(kMitsubishiAcHdrMark, kMitsubishiAcHdrSpace, kMitsubishiAcBitMark, + kMitsubishiAcOneSpace, kMitsubishiAcBitMark, + kMitsubishiAcZeroSpace, kMitsubishiAcRptMark, + kMitsubishiAcRptSpace, data, nbytes, 38, false, repeat, 50); +} +#endif // SEND_MITSUBISHI_AC + +#if DECODE_MITSUBISHI_AC +// Decode the supplied Mitsubishi message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Under development +// +// Ref: +// https://www.analysir.com/blog/2015/01/06/reverse-engineering-mitsubishi-ac-infrared-protocol/ +bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < ((kMitsubishiACBits * 2) + 2)) { + DPRINTLN("Shorter than shortest possibly expected."); + return false; // Shorter than shortest possibly expected. + } + if (strict && nbits != kMitsubishiACBits) { + DPRINTLN("Request is out of spec."); + return false; // Request is out of spec. + } + uint16_t offset = kStartOffset; + for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) { + results->state[i] = 0; + } + bool failure = false; + uint8_t rep = 0; + do { + failure = false; + // Header: + // Somtime happens that junk signals arrives before the real message + bool headerFound = false; + while (!headerFound && + offset < (results->rawlen - (kMitsubishiACBits * 2 + 2))) { + headerFound = + matchMark(results->rawbuf[offset++], kMitsubishiAcHdrMark) && + matchSpace(results->rawbuf[offset++], kMitsubishiAcHdrSpace); + } + if (!headerFound) { + DPRINTLN("Header mark not found."); + failure = true; + } + // Decode byte-by-byte: + match_result_t data_result; + for (uint8_t i = 0; i < kMitsubishiACStateLength && !failure; i++) { + results->state[i] = 0; + data_result = + matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark, + kMitsubishiAcOneSpace, kMitsubishiAcBitMark, + kMitsubishiAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) { + failure = true; + DPRINT("Byte decode failed at #"); + DPRINTLN((uint16_t)i); + } else { + results->state[i] = data_result.data; + offset += data_result.used; + DPRINT((uint16_t)results->state[i]); + DPRINT(","); + } + DPRINTLN(""); + } + // HEADER validation: + if (failure || results->state[0] != 0x23 || results->state[1] != 0xCB || + results->state[2] != 0x26 || results->state[3] != 0x01 || + results->state[4] != 0x00) { + DPRINTLN("Header mismatch."); + failure = true; + } else { + // DATA part: + + // FOOTER checksum: + if (IRMitsubishiAC::calculateChecksum(results->state) != + results->state[kMitsubishiACStateLength - 1]) { + DPRINTLN("Checksum error."); + failure = true; + } + } + if (rep != kMitsubishiACMinRepeat && failure) { + bool repeatMarkFound = false; + while (!repeatMarkFound && + offset < (results->rawlen - (kMitsubishiACBits * 2 + 4))) { + repeatMarkFound = + matchMark(results->rawbuf[offset++], kMitsubishiAcRptMark) && + matchSpace(results->rawbuf[offset++], kMitsubishiAcRptSpace); + } + if (!repeatMarkFound) { + DPRINTLN("First attempt failure and repeat mark not found."); + return false; + } + } + rep++; + // Check if the repeat is correct if we need strict decode: + if (strict && !failure) { + DPRINTLN("Strict repeat check enabled."); + // Repeat mark and space: + if (!matchMark(results->rawbuf[offset++], kMitsubishiAcRptMark) || + !matchSpace(results->rawbuf[offset++], kMitsubishiAcRptSpace)) { + DPRINTLN("Repeat mark error."); + return false; + } + // Header mark and space: + if (!matchMark(results->rawbuf[offset++], kMitsubishiAcHdrMark) || + !matchSpace(results->rawbuf[offset++], kMitsubishiAcHdrSpace)) { + DPRINTLN("Repeat header error."); + return false; + } + // Payload: + for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) { + data_result = + matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark, + kMitsubishiAcOneSpace, kMitsubishiAcBitMark, + kMitsubishiAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false || + data_result.data != results->state[i]) { + DPRINTLN("Repeat payload error."); + return false; + } + offset += data_result.used; + } + } // strict repeat check + } while (failure && rep <= kMitsubishiACMinRepeat); + results->decode_type = MITSUBISHI_AC; + results->bits = kMitsubishiACStateLength * 8; + return true; +} +#endif // DECODE_MITSUBISHI_AC + +// Code to emulate Mitsubishi A/C IR remote control unit. +// Inspired and derived from the work done at: +// https://github.com/r45635/HVAC-IR-Control +// +// Warning: Consider this very alpha code. Seems to work, but not validated. +// +// Equipment it seems compatible with: +// * +// Initialise the object. +IRMitsubishiAC::IRMitsubishiAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRMitsubishiAC::stateReset() { + // The state of the IR remote in IR code form. + // Known good state obtained from: + // https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L108 + // Note: Can't use the following because it requires -std=c++11 + // uint8_t known_good_state[kMitsubishiACStateLength] = { + // 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; + remote_state[0] = 0x23; + remote_state[1] = 0xCB; + remote_state[2] = 0x26; + remote_state[3] = 0x01; + remote_state[4] = 0x00; + remote_state[5] = 0x20; + remote_state[6] = 0x08; + remote_state[7] = 0x06; + remote_state[8] = 0x30; + remote_state[9] = 0x45; + remote_state[10] = 0x67; + for (uint8_t i = 11; i < kMitsubishiACStateLength - 1; i++) + remote_state[i] = 0; + remote_state[kMitsubishiACStateLength - 1] = 0x1F; + checksum(); // Calculate the checksum +} + +// Configure the pin for output. +void IRMitsubishiAC::begin() { _irsend.begin(); } + +#if SEND_MITSUBISHI_AC +// Send the current desired state to the IR LED. +void IRMitsubishiAC::send() { + checksum(); // Ensure correct checksum before sending. + _irsend.sendMitsubishiAC(remote_state); +} +#endif // SEND_MITSUBISHI_AC + +// Return a pointer to the internal state date of the remote. +uint8_t *IRMitsubishiAC::getRaw() { + checksum(); + return remote_state; +} + +void IRMitsubishiAC::setRaw(uint8_t *data) { + for (uint8_t i = 0; i < (kMitsubishiACStateLength - 1); i++) { + remote_state[i] = data[i]; + } + checksum(); +} + +// Calculate the checksum for the current internal state of the remote. +void IRMitsubishiAC::checksum() { + remote_state[17] = calculateChecksum(remote_state); +} + +uint8_t IRMitsubishiAC::calculateChecksum(uint8_t *data) { + uint8_t sum = 0; + // Checksum is simple addition of all previous bytes stored + // as an 8 bit value. + for (uint8_t i = 0; i < 17; i++) sum += data[i]; + return sum & 0xFFU; +} + +// Set the requested power state of the A/C to off. +void IRMitsubishiAC::on() { + // state = ON; + remote_state[5] |= kMitsubishiAcPower; +} + +// Set the requested power state of the A/C to off. +void IRMitsubishiAC::off() { + // state = OFF; + remote_state[5] &= ~kMitsubishiAcPower; +} + +// Set the requested power state of the A/C. +void IRMitsubishiAC::setPower(bool state) { + if (state) + on(); + else + off(); +} + +// Return the requested power state of the A/C. +bool IRMitsubishiAC::getPower() { + return ((remote_state[5] & kMitsubishiAcPower) != 0); +} + +// Set the temp. in deg C +void IRMitsubishiAC::setTemp(uint8_t temp) { + temp = std::max((uint8_t)kMitsubishiAcMinTemp, temp); + temp = std::min((uint8_t)kMitsubishiAcMaxTemp, temp); + remote_state[7] = temp - kMitsubishiAcMinTemp; +} + +// Return the set temp. in deg C +uint8_t IRMitsubishiAC::getTemp() { + return (remote_state[7] + kMitsubishiAcMinTemp); +} + +// Set the speed of the fan, 0-6. +// 0 is auto, 1-5 is the speed, 6 is silent. +void IRMitsubishiAC::setFan(uint8_t fan) { + // Bounds check + if (fan > kMitsubishiAcFanSilent) + fan = kMitsubishiAcFanMax; // Set the fan to maximum if out of range. + if (fan == kMitsubishiAcFanAuto) { // Automatic is a special case. + remote_state[9] = 0b10000000 | (remote_state[9] & 0b01111000); + return; + } else if (fan >= kMitsubishiAcFanMax) { + fan--; // There is no spoon^H^H^Heed 5 (max), pretend it doesn't exist. + } + remote_state[9] &= 0b01111000; // Clear the previous state + remote_state[9] |= fan; +} + +// Return the requested state of the unit's fan. +uint8_t IRMitsubishiAC::getFan() { + uint8_t fan = remote_state[9] & 0b111; + if (fan == kMitsubishiAcFanMax) return kMitsubishiAcFanSilent; + return fan; +} + +// Return the requested climate operation mode of the a/c unit. +uint8_t IRMitsubishiAC::getMode() { return (remote_state[6]); } + +// Set the requested climate operation mode of the a/c unit. +void IRMitsubishiAC::setMode(uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + switch (mode) { + case kMitsubishiAcAuto: + remote_state[8] = 0b00110000; + break; + case kMitsubishiAcCool: + remote_state[8] = 0b00110110; + break; + case kMitsubishiAcDry: + remote_state[8] = 0b00110010; + break; + case kMitsubishiAcHeat: + remote_state[8] = 0b00110000; + break; + default: + mode = kMitsubishiAcAuto; + remote_state[8] = 0b00110000; + } + remote_state[6] = mode; +} + +// Set the requested vane operation mode of the a/c unit. +void IRMitsubishiAC::setVane(uint8_t mode) { + mode = std::min(mode, (uint8_t)0b111); // bounds check + mode |= 0b1000; + mode <<= 3; + remote_state[9] &= 0b11000111; // Clear the previous setting. + remote_state[9] |= mode; +} + +// Return the requested vane operation mode of the a/c unit. +uint8_t IRMitsubishiAC::getVane() { + return ((remote_state[9] & 0b00111000) >> 3); +} + +// Return the clock setting of the message. 1=1/6 hour. e.g. 4pm = 48 +uint8_t IRMitsubishiAC::getClock() { return remote_state[10]; } + +// Set the current time. 1 = 1/6 hour. e.g. 6am = 36. +void IRMitsubishiAC::setClock(uint8_t clock) { remote_state[10] = clock; } + +// Return the desired start time. 1 = 1/6 hour. e.g. 1am = 6 +uint8_t IRMitsubishiAC::getStartClock() { return remote_state[12]; } + +// Set the desired start tiem of the AC. 1 = 1/6 hour. e.g. 8pm = 120 +void IRMitsubishiAC::setStartClock(uint8_t clock) { remote_state[12] = clock; } + +// Return the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132 +uint8_t IRMitsubishiAC::getStopClock() { return remote_state[11]; } + +// Set the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132 +void IRMitsubishiAC::setStopClock(uint8_t clock) { remote_state[11] = clock; } + +// Return the timer setting. Possible values: kMitsubishiAcNoTimer, +// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer, +// kMitsubishiAcStartStopTimer +uint8_t IRMitsubishiAC::getTimer() { return remote_state[13] & 0b111; } + +// Set the timer setting. Possible values: kMitsubishiAcNoTimer, +// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer, +// kMitsubishiAcStartStopTimer +void IRMitsubishiAC::setTimer(uint8_t timer) { + remote_state[13] = timer & 0b111; +} + +#ifdef ARDUINO +String IRMitsubishiAC::timeToString(uint64_t time) { + String result = ""; +#else +std::string IRMitsubishiAC::timeToString(uint64_t time) { + std::string result = ""; +#endif // ARDUINO + if (time / 6 < 10) result += "0"; + result += uint64ToString(time / 6); + result += ":"; + if (time * 10 % 60 < 10) result += "0"; + result += uint64ToString(time * 10 % 60); + return result; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRMitsubishiAC::toString() { + String result = ""; +#else +std::string IRMitsubishiAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + switch (getMode()) { + case MITSUBISHI_AC_AUTO: + result += " (AUTO)"; + break; + case MITSUBISHI_AC_COOL: + result += " (COOL)"; + break; + case MITSUBISHI_AC_DRY: + result += " (DRY)"; + break; + case MITSUBISHI_AC_HEAT: + result += " (HEAT)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", FAN: "; + switch (getFan()) { + case MITSUBISHI_AC_FAN_AUTO: + result += "AUTO"; + break; + case MITSUBISHI_AC_FAN_MAX: + result += "MAX"; + break; + case MITSUBISHI_AC_FAN_SILENT: + result += "SILENT"; + break; + default: + result += uint64ToString(getFan()); + } + result += ", VANE: "; + switch (getVane()) { + case MITSUBISHI_AC_VANE_AUTO: + result += "AUTO"; + break; + case MITSUBISHI_AC_VANE_AUTO_MOVE: + result += "AUTO MOVE"; + break; + default: + result += uint64ToString(getVane()); + } + result += ", Time: "; + result += timeToString(getClock()); + result += ", On timer: "; + result += timeToString(getStartClock()); + result += ", Off timer: "; + result += timeToString(getStopClock()); + result += ", Timer: "; + switch (getTimer()) { + case kMitsubishiAcNoTimer: + result += "-"; + break; + case kMitsubishiAcStartTimer: + result += "Start"; + break; + case kMitsubishiAcStopTimer: + result += "Stop"; + break; + case kMitsubishiAcStartStopTimer: + result += "Start+Stop"; + break; + default: + result += "? ("; + result += getTimer(); + result += ")\n"; + } + return result; +} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h new file mode 100644 index 000000000..7b03efce6 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h @@ -0,0 +1,109 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran +#ifndef IR_MITSUBISHI_H_ +#define IR_MITSUBISHI_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII +// M M M I T S U U B B I S H H I +// M M M I T SSS U U BBBB I SSS HHHHH I +// M M I T S U U B B I S H H I +// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII + +// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote +// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran + +// Constants +const uint8_t kMitsubishiAcAuto = 0x20; +const uint8_t kMitsubishiAcCool = 0x18; +const uint8_t kMitsubishiAcDry = 0x10; +const uint8_t kMitsubishiAcHeat = 0x08; +const uint8_t kMitsubishiAcPower = 0x20; +const uint8_t kMitsubishiAcFanAuto = 0; +const uint8_t kMitsubishiAcFanMax = 5; +const uint8_t kMitsubishiAcFanRealMax = 4; +const uint8_t kMitsubishiAcFanSilent = 6; +const uint8_t kMitsubishiAcMinTemp = 16; // 16C +const uint8_t kMitsubishiAcMaxTemp = 31; // 31C +const uint8_t kMitsubishiAcVaneAuto = 0; +const uint8_t kMitsubishiAcVaneAutoMove = 7; +const uint8_t kMitsubishiAcNoTimer = 0; +const uint8_t kMitsubishiAcStartTimer = 5; +const uint8_t kMitsubishiAcStopTimer = 3; +const uint8_t kMitsubishiAcStartStopTimer = 7; + +// Legacy defines (Deprecated) +#define MITSUBISHI_AC_VANE_AUTO_MOVE kMitsubishiAcVaneAutoMove +#define MITSUBISHI_AC_VANE_AUTO kMitsubishiAcVaneAuto +#define MITSUBISHI_AC_POWER kMitsubishiAcPower +#define MITSUBISHI_AC_MIN_TEMP kMitsubishiAcMinTemp +#define MITSUBISHI_AC_MAX_TEMP kMitsubishiAcMaxTemp +#define MITSUBISHI_AC_HEAT kMitsubishiAcHeat +#define MITSUBISHI_AC_FAN_SILENT kMitsubishiAcFanSilent +#define MITSUBISHI_AC_FAN_REAL_MAX kMitsubishiAcFanRealMax +#define MITSUBISHI_AC_FAN_MAX kMitsubishiAcFanMax +#define MITSUBISHI_AC_FAN_AUTO kMitsubishiAcFanAuto +#define MITSUBISHI_AC_DRY kMitsubishiAcDry +#define MITSUBISHI_AC_COOL kMitsubishiAcCool +#define MITSUBISHI_AC_AUTO kMitsubishiAcAuto + +class IRMitsubishiAC { + public: + explicit IRMitsubishiAC(uint16_t pin); + + static uint8_t calculateChecksum(uint8_t* data); + + void stateReset(); +#if SEND_MITSUBISHI_AC + void send(); +#endif // SEND_MITSUBISHI_AC + void begin(); + void on(); + void off(); + void setPower(bool state); + bool getPower(); + void setTemp(uint8_t temp); + uint8_t getTemp(); + void setFan(uint8_t fan); + uint8_t getFan(); + void setMode(uint8_t mode); + uint8_t getMode(); + void setVane(uint8_t mode); + uint8_t getVane(); + uint8_t* getRaw(); + void setRaw(uint8_t* data); + uint8_t getClock(); + void setClock(uint8_t clock); + uint8_t getStartClock(); + void setStartClock(uint8_t clock); + uint8_t getStopClock(); + void setStopClock(uint8_t clock); + uint8_t getTimer(); + void setTimer(uint8_t timer); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: +#ifdef ARDUINO + String timeToString(uint64_t time); +#else + std::string timeToString(uint64_t time); +#endif + uint8_t remote_state[kMitsubishiACStateLength]; + void checksum(); + IRsend _irsend; +}; + +#endif // IR_MITSUBISHI_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.cpp similarity index 53% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.cpp index a5febe1b8..660b51109 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.cpp @@ -2,11 +2,11 @@ // Copyright 2017 David Conran #define __STDC_LIMIT_MACROS +#include "ir_NEC.h" #include #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // N N EEEEE CCCC @@ -17,39 +17,13 @@ // NEC originally added from https://github.com/shirriff/Arduino-IRremote/ -// Constants -// Ref: -// http://www.sbprojects.com/knowledge/ir/nec.php -#define NEC_TICK 560U -#define NEC_HDR_MARK_TICKS 16U -#define NEC_HDR_MARK (NEC_HDR_MARK_TICKS * NEC_TICK) -#define NEC_HDR_SPACE_TICKS 8U -#define NEC_HDR_SPACE (NEC_HDR_SPACE_TICKS * NEC_TICK) -#define NEC_BIT_MARK_TICKS 1U -#define NEC_BIT_MARK (NEC_BIT_MARK_TICKS * NEC_TICK) -#define NEC_ONE_SPACE_TICKS 3U -#define NEC_ONE_SPACE (NEC_TICK * NEC_ONE_SPACE_TICKS) -#define NEC_ZERO_SPACE_TICKS 1U -#define NEC_ZERO_SPACE (NEC_TICK * NEC_ZERO_SPACE_TICKS) -#define NEC_RPT_SPACE_TICKS 4U -#define NEC_RPT_SPACE (NEC_RPT_SPACE_TICKS * NEC_TICK) -#define NEC_RPT_LENGTH 4U -#define NEC_MIN_COMMAND_LENGTH_TICKS 193U -#define NEC_MIN_COMMAND_LENGTH (NEC_MIN_COMMAND_LENGTH_TICKS * NEC_TICK) -#define NEC_MIN_GAP (NEC_MIN_COMMAND_LENGTH - \ - (NEC_HDR_MARK + NEC_HDR_SPACE + NEC_BITS * (NEC_BIT_MARK + NEC_ONE_SPACE) \ - + NEC_BIT_MARK)) -#define NEC_MIN_GAP_TICKS (NEC_MIN_COMMAND_LENGTH_TICKS - \ - (NEC_HDR_MARK_TICKS + NEC_HDR_SPACE_TICKS + \ - NEC_BITS * (NEC_BIT_MARK_TICKS + NEC_ONE_SPACE_TICKS) + \ - NEC_BIT_MARK_TICKS)) - -#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO) +#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO || \ + SEND_PIONEER) // Send a raw NEC(Renesas) formatted message. // // Args: // data: The message to be sent. -// nbits: The number of bits of the message to be sent. Typically NEC_BITS. +// nbits: The number of bits of the message to be sent. Typically kNECBits. // repeat: The number of times the command is to be repeated. // // Status: STABLE / Known working. @@ -57,29 +31,17 @@ // Ref: // http://www.sbprojects.com/knowledge/ir/nec.php void IRsend::sendNEC(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 38kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(38, 33); - IRtimer usecs = IRtimer(); - // Header - mark(NEC_HDR_MARK); - space(NEC_HDR_SPACE); - // Data - sendData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, - data, nbits, true); - // Footer - mark(NEC_BIT_MARK); - // Gap to next command. - space(std::max(NEC_MIN_GAP, NEC_MIN_COMMAND_LENGTH - usecs.elapsed())); - + sendGeneric(kNecHdrMark, kNecHdrSpace, kNecBitMark, kNecOneSpace, kNecBitMark, + kNecZeroSpace, kNecBitMark, kNecMinGap, kNecMinCommandLength, + data, nbits, 38, true, 0, // Repeats are handled later. + 33); // Optional command repeat sequence. - for (uint16_t i = 0; i < repeat; i++) { - usecs.reset(); - mark(NEC_HDR_MARK); - space(NEC_RPT_SPACE); - mark(NEC_BIT_MARK); - // Gap till next command. - space(std::max(NEC_MIN_GAP, NEC_MIN_COMMAND_LENGTH - usecs.elapsed())); - } + if (repeat) + sendGeneric(kNecHdrMark, kNecRptSpace, 0, 0, 0, 0, // No actual data sent. + kNecBitMark, kNecMinGap, kNecMinCommandLength, 0, + 0, // No data to be sent. + 38, true, repeat - 1, // We've already sent a one message. + 33); } // Calculate the raw NEC data based on address and command. @@ -97,8 +59,8 @@ uint32_t IRsend::encodeNEC(uint16_t address, uint16_t command) { command &= 0xFF; // We only want the least significant byte of command. // sendNEC() sends MSB first, but protocol says this is LSB first. command = reverseBits(command, 8); - command = (command << 8) + (command ^ 0xFF); // Calculate the new command. - if (address > 0xFF) { // Is it Extended NEC? + command = (command << 8) + (command ^ 0xFF); // Calculate the new command. + if (address > 0xFF) { // Is it Extended NEC? address = reverseBits(address, 16); return ((address << 16) + command); // Extended. } else { @@ -113,7 +75,7 @@ uint32_t IRsend::encodeNEC(uint16_t address, uint16_t command) { // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: The number of data bits to expect. Typically NEC_BITS. +// nbits: The number of data bits to expect. Typically kNECBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. @@ -122,34 +84,33 @@ uint32_t IRsend::encodeNEC(uint16_t address, uint16_t command) { // // Notes: // NEC protocol has three varients/forms. -// Normal: a 8 bit address & a 8 bit command in 32 bit data form. +// Normal: an 8 bit address & an 8 bit command in 32 bit data form. // i.e. address + inverted(address) + command + inverted(command) -// Extended: a 16 bit address & a 8 bit command in 32 bit data form. +// Extended: a 16 bit address & an 8 bit command in 32 bit data form. // i.e. address + command + inverted(command) // Repeat: a 0-bit code. i.e. No data bits. Just the header + footer. // // Ref: // http://www.sbprojects.com/knowledge/ir/nec.php bool IRrecv::decodeNEC(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1 && - results->rawlen != NEC_RPT_LENGTH) + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1 && + results->rawlen != kNecRptLength) return false; // Can't possibly be a valid NEC message. - if (strict && nbits != NEC_BITS) + if (strict && nbits != kNECBits) return false; // Not strictly an NEC message. uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // Header - if (!matchMark(results->rawbuf[offset], NEC_HDR_MARK)) return false; + if (!matchMark(results->rawbuf[offset], kNecHdrMark)) return false; // Calculate how long the lowest tick time is based on the header mark. - uint32_t mark_tick = results->rawbuf[offset++] * RAWTICK / - NEC_HDR_MARK_TICKS; + uint32_t mark_tick = results->rawbuf[offset++] * kRawTick / kNecHdrMarkTicks; // Check if it is a repeat code. - if (results->rawlen == NEC_RPT_LENGTH && - matchSpace(results->rawbuf[offset], NEC_RPT_SPACE) && - matchMark(results->rawbuf[offset + 1], NEC_BIT_MARK_TICKS * mark_tick)) { - results->value = REPEAT; + if (results->rawlen == kNecRptLength && + matchSpace(results->rawbuf[offset], kNecRptSpace) && + matchMark(results->rawbuf[offset + 1], kNecBitMarkTicks * mark_tick)) { + results->value = kRepeat; results->decode_type = NEC; results->bits = 0; results->address = 0; @@ -159,34 +120,32 @@ bool IRrecv::decodeNEC(decode_results *results, uint16_t nbits, bool strict) { } // Header (cont.) - if (!matchSpace(results->rawbuf[offset], NEC_HDR_SPACE)) return false; + if (!matchSpace(results->rawbuf[offset], kNecHdrSpace)) return false; // Calculate how long the common tick time is based on the header space. - uint32_t space_tick = results->rawbuf[offset++] * RAWTICK / - NEC_HDR_SPACE_TICKS; + uint32_t space_tick = + results->rawbuf[offset++] * kRawTick / kNecHdrSpaceTicks; // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - NEC_BIT_MARK_TICKS * mark_tick, - NEC_ONE_SPACE_TICKS * space_tick, - NEC_BIT_MARK_TICKS * mark_tick, - NEC_ZERO_SPACE_TICKS * space_tick); + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kNecBitMarkTicks * mark_tick, + kNecOneSpaceTicks * space_tick, kNecBitMarkTicks * mark_tick, + kNecZeroSpaceTicks * space_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer - if (!matchMark(results->rawbuf[offset++], NEC_BIT_MARK_TICKS * mark_tick)) - return false; - if (offset <= results->rawlen && - !matchAtLeast(results->rawbuf[offset], NEC_MIN_GAP_TICKS * space_tick)) + if (!matchMark(results->rawbuf[offset++], kNecBitMarkTicks * mark_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kNecMinGapTicks * space_tick)) return false; // Compliance // Calculate command and optionally enforce integrity checking. - uint8_t command = (data & 0xFF00) >> 8; + uint8_t command = (data & 0xFF00) >> 8; // Command is sent twice, once as plain and then inverted. if ((command ^ 0xFF) != (data & 0xFF)) { - if (strict) - return false; // Command integrity failed. + if (strict) return false; // Command integrity failed. command = 0; // The command value isn't valid, so default to zero. } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h new file mode 100644 index 000000000..c274c104e --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h @@ -0,0 +1,46 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017, 2018 David Conran + +#ifndef IR_NEC_H_ +#define IR_NEC_H_ + +#include +#include "IRremoteESP8266.h" + +// N N EEEEE CCCC +// NN N E C +// N N N EEE C +// N NN E C +// N N EEEEE CCCC + +// NEC originally added from https://github.com/shirriff/Arduino-IRremote/ + +// Constants +// Ref: +// http://www.sbprojects.com/knowledge/ir/nec.php +const uint16_t kNecTick = 560; +const uint16_t kNecHdrMarkTicks = 16; +const uint16_t kNecHdrMark = kNecHdrMarkTicks * kNecTick; +const uint16_t kNecHdrSpaceTicks = 8; +const uint16_t kNecHdrSpace = kNecHdrSpaceTicks * kNecTick; +const uint16_t kNecBitMarkTicks = 1; +const uint16_t kNecBitMark = kNecBitMarkTicks * kNecTick; +const uint16_t kNecOneSpaceTicks = 3; +const uint16_t kNecOneSpace = kNecOneSpaceTicks * kNecTick; +const uint16_t kNecZeroSpaceTicks = 1; +const uint16_t kNecZeroSpace = kNecZeroSpaceTicks * kNecTick; +const uint16_t kNecRptSpaceTicks = 4; +const uint16_t kNecRptSpace = kNecRptSpaceTicks * kNecTick; +const uint16_t kNecRptLength = 4; +const uint16_t kNecMinCommandLengthTicks = 193; +const uint32_t kNecMinCommandLength = kNecMinCommandLengthTicks * kNecTick; +const uint32_t kNecMinGap = + kNecMinCommandLength - + (kNecHdrMark + kNecHdrSpace + kNECBits * (kNecBitMark + kNecOneSpace) + + kNecBitMark); +const uint16_t kNecMinGapTicks = + kNecMinCommandLengthTicks - + (kNecHdrMarkTicks + kNecHdrSpaceTicks + + kNECBits * (kNecBitMarkTicks + kNecOneSpaceTicks) + kNecBitMarkTicks); + +#endif // IR_NEC_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp new file mode 100644 index 000000000..9ac22a849 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp @@ -0,0 +1,104 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// NN NN IIIII KK KK AAA IIIII +// NNN NN III KK KK AAAAA III +// NN N NN III KKKK AA AA III +// NN NNN III KK KK AAAAAAA III +// NN NN IIIII KK KK AA AA IIIII + +// Constants +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/309 +const uint16_t kNikaiTick = 500; +const uint16_t kNikaiHdrMarkTicks = 8; +const uint16_t kNikaiHdrMark = kNikaiHdrMarkTicks * kNikaiTick; +const uint16_t kNikaiHdrSpaceTicks = 8; +const uint16_t kNikaiHdrSpace = kNikaiHdrSpaceTicks * kNikaiTick; +const uint16_t kNikaiBitMarkTicks = 1; +const uint16_t kNikaiBitMark = kNikaiBitMarkTicks * kNikaiTick; +const uint16_t kNikaiOneSpaceTicks = 2; +const uint16_t kNikaiOneSpace = kNikaiOneSpaceTicks * kNikaiTick; +const uint16_t kNikaiZeroSpaceTicks = 4; +const uint16_t kNikaiZeroSpace = kNikaiZeroSpaceTicks * kNikaiTick; +const uint16_t kNikaiMinGapTicks = 17; +const uint16_t kNikaiMinGap = kNikaiMinGapTicks * kNikaiTick; + +#if SEND_NIKAI +// Send a Nikai TV formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The bit size of the message being sent. typically kNikaiBits. +// repeat: The number of times the message is to be repeated. +// +// Status: STABLE / Working. +// +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/309 +void IRsend::sendNikai(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kNikaiHdrMark, kNikaiHdrSpace, kNikaiBitMark, kNikaiOneSpace, + kNikaiBitMark, kNikaiZeroSpace, kNikaiBitMark, kNikaiMinGap, data, + nbits, 38, true, repeat, 33); +} +#endif + +#if DECODE_NIKAI +// Decode the supplied Nikai message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. +// Typically kNikaiBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Working. +// +bool IRrecv::decodeNikai(decode_results *results, uint16_t nbits, bool strict) { + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid Nikai message. + if (strict && nbits != kNikaiBits) + return false; // We expect Nikai to be a certain sized message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset], kNikaiHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kNikaiHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kNikaiHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kNikaiHdrSpaceTicks; + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kNikaiBitMarkTicks * m_tick, + kNikaiOneSpaceTicks * s_tick, kNikaiBitMarkTicks * m_tick, + kNikaiZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + // Footer + if (!matchMark(results->rawbuf[offset++], kNikaiBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kNikaiMinGapTicks * s_tick)) + return false; + + // Compliance + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = NIKAI; + results->command = 0; + results->address = 0; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp new file mode 100644 index 000000000..e79b136a5 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp @@ -0,0 +1,863 @@ +// Copyright 2015 Kristian Lauszus +// Copyright 2017, 2018 David Conran + +#include "ir_Panasonic.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC +// P P A A NN N A A S O O NN N I C +// PPPP AAAAA N N N AAAAA SSS O O N N N I C +// P A A N NN A A S O O N NN I C +// P A A N N A A SSSS OOO N N IIIII CCCC + +// Panasonic protocol originally added by Kristian Lauszus from: +// https://github.com/z3t0/Arduino-IRremote +// (Thanks to zenwheel and other people at the original blog post) +// +// Panasonic A/C support add by crankyoldgit but heavily influenced by: +// https://github.com/ToniA/ESPEasy/blob/HeatpumpIR/lib/HeatpumpIR/PanasonicHeatpumpIR.cpp +// Panasonic A/C Clock & Timer support: +// Reverse Engineering by MikkelTb +// Code by crankyoldgit +// Panasonic A/C models supported: +// A/C Series/models: +// JKE, LKE, DKE, CKP, & NKE series. (In theory) +// CS-YW9MKD (confirmed) +// CS-ME14CKPG / CS-ME12CKPG / CS-ME10CKPG +// A/C Remotes: +// A75C3747 (confirmed) +// A75C3704 +// A75C2311 (CKP) + +// Constants +// Ref: +// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 + +const uint16_t kPanasonicTick = 432; +const uint16_t kPanasonicHdrMarkTicks = 8; +const uint16_t kPanasonicHdrMark = kPanasonicHdrMarkTicks * kPanasonicTick; +const uint16_t kPanasonicHdrSpaceTicks = 4; +const uint16_t kPanasonicHdrSpace = kPanasonicHdrSpaceTicks * kPanasonicTick; +const uint16_t kPanasonicBitMarkTicks = 1; +const uint16_t kPanasonicBitMark = kPanasonicBitMarkTicks * kPanasonicTick; +const uint16_t kPanasonicOneSpaceTicks = 3; +const uint16_t kPanasonicOneSpace = kPanasonicOneSpaceTicks * kPanasonicTick; +const uint16_t kPanasonicZeroSpaceTicks = 1; +const uint16_t kPanasonicZeroSpace = kPanasonicZeroSpaceTicks * kPanasonicTick; +const uint16_t kPanasonicMinCommandLengthTicks = 378; +const uint32_t kPanasonicMinCommandLength = + kPanasonicMinCommandLengthTicks * kPanasonicTick; +const uint16_t kPanasonicEndGap = 5000; // See issue #245 +const uint16_t kPanasonicMinGapTicks = + kPanasonicMinCommandLengthTicks - + (kPanasonicHdrMarkTicks + kPanasonicHdrSpaceTicks + + kPanasonicBits * (kPanasonicBitMarkTicks + kPanasonicOneSpaceTicks) + + kPanasonicBitMarkTicks); +const uint32_t kPanasonicMinGap = kPanasonicMinGapTicks * kPanasonicTick; + +const uint16_t kPanasonicAcSectionGap = 10000; +const uint16_t kPanasonicAcSection1Length = 8; +const uint32_t kPanasonicAcMessageGap = 100000; // A complete guess. + +#if (SEND_PANASONIC || SEND_DENON) +// Send a Panasonic formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The number of bits of the message to be sent. (kPanasonicBits). +// repeat: The number of times the command is to be repeated. +// +// Status: BETA / Should be working. +// +// Note: +// This protocol is a modified version of Kaseikyo. +void IRsend::sendPanasonic64(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kPanasonicHdrMark, kPanasonicHdrSpace, kPanasonicBitMark, + kPanasonicOneSpace, kPanasonicBitMark, kPanasonicZeroSpace, + kPanasonicBitMark, kPanasonicMinGap, kPanasonicMinCommandLength, + data, nbits, kPanasonicFreq, true, repeat, 50); +} + +// Send a Panasonic formatted message. +// +// Args: +// address: The manufacturer code. +// data: The data portion to be sent. +// nbits: The number of bits of the message to be sent. (kPanasonicBits). +// repeat: The number of times the command is to be repeated. +// +// Status: STABLE. +// +// Note: +// This protocol is a modified version of Kaseikyo. +void IRsend::sendPanasonic(uint16_t address, uint32_t data, uint16_t nbits, + uint16_t repeat) { + sendPanasonic64(((uint64_t)address << 32) | (uint64_t)data, nbits, repeat); +} + +// Calculate the raw Panasonic data based on device, subdevice, & function. +// +// Args: +// manufacturer: A 16-bit manufacturer code. e.g. 0x4004 is Panasonic. +// device: An 8-bit code. +// subdevice: An 8-bit code. +// function: An 8-bit code. +// Returns: +// A raw uint64_t Panasonic message. +// +// Status: BETA / Should be working.. +// +// Note: +// Panasonic 48-bit protocol is a modified version of Kaseikyo. +// Ref: +// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?2615 +uint64_t IRsend::encodePanasonic(uint16_t manufacturer, uint8_t device, + uint8_t subdevice, uint8_t function) { + uint8_t checksum = device ^ subdevice ^ function; + return (((uint64_t)manufacturer << 32) | ((uint64_t)device << 24) | + ((uint64_t)subdevice << 16) | ((uint64_t)function << 8) | checksum); +} +#endif // (SEND_PANASONIC || SEND_DENON) + +#if (DECODE_PANASONIC || DECODE_DENON) +// Decode the supplied Panasonic message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should be working. +// Note: +// Panasonic 48-bit protocol is a modified version of Kaseikyo. +// Ref: +// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 +// http://www.hifi-remote.com/wiki/index.php?title=Panasonic +bool IRrecv::decodePanasonic(decode_results *results, uint16_t nbits, + bool strict, uint32_t manufacturer) { + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Not enough entries to be a Panasonic message. + if (strict && nbits != kPanasonicBits) + return false; // Request is out of spec. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset], kPanasonicHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = + results->rawbuf[offset++] * kRawTick / kPanasonicHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kPanasonicHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kPanasonicHdrSpaceTicks; + + // Data + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits, kPanasonicBitMarkTicks * m_tick, + kPanasonicOneSpaceTicks * s_tick, kPanasonicBitMarkTicks * m_tick, + kPanasonicZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Footer + if (!match(results->rawbuf[offset++], kPanasonicBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kPanasonicEndGap)) + return false; + + // Compliance + uint32_t address = data >> 32; + uint32_t command = data & 0xFFFFFFFF; + if (strict) { + if (address != manufacturer) // Verify the Manufacturer code. + return false; + // Verify the checksum. + uint8_t checksumOrig = data & 0xFF; + uint8_t checksumCalc = ((data >> 24) ^ (data >> 16) ^ (data >> 8)) & 0xFF; + if (checksumOrig != checksumCalc) return false; + } + + // Success + results->value = data; + results->address = address; + results->command = command; + results->decode_type = PANASONIC; + results->bits = nbits; + return true; +} +#endif // (DECODE_PANASONIC || DECODE_DENON) + +#if SEND_PANASONIC_AC +// Send a Panasonic A/C message. +// +// Args: +// data: Contents of the message to be sent. (Guessing MSBF order) +// nbits: Nr. of bits of data to be sent. Typically kPanasonicAcBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: Beta / Appears to work with real device(s). +//: +// Panasonic A/C models supported: +// A/C Series/models: +// JKE, LKE, DKE, & NKE series. +// CS-YW9MKD +// A/C Remotes: +// A75C3747 +// A75C3704 +// +void IRsend::sendPanasonicAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) { + if (nbytes < kPanasonicAcSection1Length) return; + for (uint16_t r = 0; r <= repeat; r++) { + // First section. (8 bytes) + sendGeneric(kPanasonicHdrMark, kPanasonicHdrSpace, kPanasonicBitMark, + kPanasonicOneSpace, kPanasonicBitMark, kPanasonicZeroSpace, + kPanasonicBitMark, kPanasonicAcSectionGap, data, + kPanasonicAcSection1Length, kPanasonicFreq, false, 0, 50); + // First section. (The rest of the data bytes) + sendGeneric(kPanasonicHdrMark, kPanasonicHdrSpace, kPanasonicBitMark, + kPanasonicOneSpace, kPanasonicBitMark, kPanasonicZeroSpace, + kPanasonicBitMark, kPanasonicAcMessageGap, + data + kPanasonicAcSection1Length, + nbytes - kPanasonicAcSection1Length, kPanasonicFreq, false, 0, + 50); + } +} +#endif // SEND_PANASONIC_AC + +IRPanasonicAc::IRPanasonicAc(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRPanasonicAc::stateReset() { + for (uint8_t i = 0; i < kPanasonicAcStateLength; i++) + remote_state[i] = kPanasonicKnownGoodState[i]; + _temp = 25; // An initial saved desired temp. Completely made up. + _swingh = kPanasonicAcSwingHMiddle; // A similar made up value for H Swing. +} + +void IRPanasonicAc::begin() { _irsend.begin(); } + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRPanasonicAc::validChecksum(uint8_t state[], const uint16_t length) { + if (length < 2) return false; // 1 byte of data can't have a checksum. + return (state[length - 1] == + sumBytes(state, length - 1, kPanasonicAcChecksumInit)); +} + +uint8_t IRPanasonicAc::calcChecksum(uint8_t state[], const uint16_t length) { + return sumBytes(state, length - 1, kPanasonicAcChecksumInit); +} + +void IRPanasonicAc::fixChecksum(const uint16_t length) { + remote_state[length - 1] = calcChecksum(remote_state, length); +} + +#if SEND_PANASONIC_AC +void IRPanasonicAc::send() { + fixChecksum(); + _irsend.sendPanasonicAC(remote_state); +} +#endif // SEND_PANASONIC_AC + +void IRPanasonicAc::setModel(const panasonic_ac_remote_model_t model) { + switch (model) { + case kPanasonicDke: + case kPanasonicJke: + case kPanasonicLke: + case kPanasonicNke: + case kPanasonicCkp: + break; + default: // Only proceed if we know what to do. + return; + } + // clear & set the various bits and bytes. + remote_state[13] &= 0xF0; + remote_state[17] = 0x00; + remote_state[21] &= 0b11101111; + remote_state[23] = 0x81; + remote_state[25] = 0x00; + + switch (model) { + case kPanasonicLke: + remote_state[13] |= 0x02; + remote_state[17] = 0x06; + break; + case kPanasonicDke: + remote_state[23] = 0x01; + remote_state[25] = 0x06; + // Has to be done last as setSwingHorizontal has model check built-in + setSwingHorizontal(_swingh); + break; + case kPanasonicNke: + remote_state[17] = 0x06; + break; + case kPanasonicJke: + break; + case kPanasonicCkp: + remote_state[21] |= 0x10; + remote_state[23] = 0x01; + default: + break; + } +} + +panasonic_ac_remote_model_t IRPanasonicAc::getModel() { + if (remote_state[17] == 0x00) { + if ((remote_state[21] & 0x10) && (remote_state[23] & 0x01)) + return kPanasonicCkp; + if (remote_state[23] & 0x80) return kPanasonicJke; + } + if (remote_state[17] == 0x06 && (remote_state[13] & 0x0F) == 0x02) + return kPanasonicLke; + if (remote_state[23] == 0x01) return kPanasonicDke; + if (remote_state[17] == 0x06) return kPanasonicNke; + return kPanasonicUnknown; +} + +uint8_t *IRPanasonicAc::getRaw() { + fixChecksum(); + return remote_state; +} + +void IRPanasonicAc::setRaw(const uint8_t state[]) { + for (uint8_t i = 0; i < kPanasonicAcStateLength; i++) { + remote_state[i] = state[i]; + } +} + +// Control the power state of the A/C unit. +// +// For CKP models, the remote has no memory of the power state the A/C unit +// should be in. For those models setting this on/true will toggle the power +// state of the Panasonic A/C unit with the next meessage. +// e.g. If the A/C unit is already on, setPower(true) will turn it off. +// If the A/C unit is already off, setPower(true) will turn it on. +// setPower(false) will leave the A/C power state as it was. +// +// For all other models, setPower(true) should set the internal state to +// turn it on, and setPower(false) should turn it off. +void IRPanasonicAc::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +// Return the A/C power state of the remote. +// Except for CKP models, where it returns if the power state will be toggled +// on the A/C unit when the next message is sent. +bool IRPanasonicAc::getPower() { + return (remote_state[13] & kPanasonicAcPower) == kPanasonicAcPower; +} + +void IRPanasonicAc::on() { remote_state[13] |= kPanasonicAcPower; } + +void IRPanasonicAc::off() { remote_state[13] &= ~kPanasonicAcPower; } + +uint8_t IRPanasonicAc::getMode() { return remote_state[13] >> 4; } + +void IRPanasonicAc::setMode(const uint8_t desired) { + uint8_t mode = kPanasonicAcAuto; // Default to Auto mode. + switch (desired) { + case kPanasonicAcFan: + // Allegedly Fan mode has a temperature of 27. + setTemp(kPanasonicAcFanModeTemp, false); + mode = desired; + break; + case kPanasonicAcAuto: + case kPanasonicAcCool: + case kPanasonicAcHeat: + case kPanasonicAcDry: + mode = desired; + // Set the temp to the saved temp, just incase our previous mode was Fan. + setTemp(_temp); + break; + } + remote_state[13] &= 0x0F; // Clear the previous mode bits. + remote_state[13] |= mode << 4; +} + +uint8_t IRPanasonicAc::getTemp() { return remote_state[14] >> 1; } + +// Set the desitred temperature in Celcius. +// Args: +// celsius: The temperature to set the A/C unit to. +// remember: A boolean flag for the class to remember the temperature. +// +// Automatically safely limits the temp to the operating range supported. +void IRPanasonicAc::setTemp(const uint8_t celsius, const bool remember) { + uint8_t temperature; + temperature = std::max(celsius, kPanasonicAcMinTemp); + temperature = std::min(temperature, kPanasonicAcMaxTemp); + remote_state[14] = temperature << 1; + if (remember) _temp = temperature; +} + +uint8_t IRPanasonicAc::getSwingVertical() { return remote_state[16] & 0x0F; } + +void IRPanasonicAc::setSwingVertical(const uint8_t desired_elevation) { + uint8_t elevation = desired_elevation; + if (elevation != kPanasonicAcSwingVAuto) { + elevation = std::max(elevation, kPanasonicAcSwingVUp); + elevation = std::min(elevation, kPanasonicAcSwingVDown); + } + remote_state[16] &= 0xF0; + remote_state[16] |= elevation; +} + +uint8_t IRPanasonicAc::getSwingHorizontal() { return remote_state[17]; } + +void IRPanasonicAc::setSwingHorizontal(const uint8_t desired_direction) { + switch (desired_direction) { + case kPanasonicAcSwingHAuto: + case kPanasonicAcSwingHMiddle: + case kPanasonicAcSwingHFullLeft: + case kPanasonicAcSwingHLeft: + case kPanasonicAcSwingHRight: + case kPanasonicAcSwingHFullRight: + break; + default: // Ignore anything that isn't valid. + return; + } + _swingh = desired_direction; // Store the direction for later. + uint8_t direction = desired_direction; + switch (getModel()) { + case kPanasonicDke: + break; + case kPanasonicNke: + case kPanasonicLke: + direction = kPanasonicAcSwingHMiddle; + break; + default: // Ignore everything else. + return; + } + remote_state[17] = direction; +} + +void IRPanasonicAc::setFan(const uint8_t speed) { + if (speed <= kPanasonicAcFanMax || speed == kPanasonicAcFanAuto) + remote_state[16] = + (remote_state[16] & 0x0F) | ((speed + kPanasonicAcFanOffset) << 4); +} + +uint8_t IRPanasonicAc::getFan() { + return (remote_state[16] >> 4) - kPanasonicAcFanOffset; +} + +bool IRPanasonicAc::getQuiet() { + if (getModel() == kPanasonicCkp) + return remote_state[21] & kPanasonicAcQuietCkp; + else + return remote_state[21] & kPanasonicAcQuiet; +} + +void IRPanasonicAc::setQuiet(const bool state) { + uint8_t quiet; + if (getModel() == kPanasonicCkp) + quiet = kPanasonicAcQuietCkp; + else + quiet = kPanasonicAcQuiet; + + if (state) { + setPowerful(false); // Powerful is mutually exclusive. + remote_state[21] |= quiet; + } else { + remote_state[21] &= ~quiet; + } +} + +bool IRPanasonicAc::getPowerful() { + if (getModel() == kPanasonicCkp) + return remote_state[21] & kPanasonicAcPowerfulCkp; + else + return remote_state[21] & kPanasonicAcPowerful; +} + +void IRPanasonicAc::setPowerful(const bool state) { + uint8_t powerful; + if (getModel() == kPanasonicCkp) + powerful = kPanasonicAcPowerfulCkp; + else + powerful = kPanasonicAcPowerful; + + if (state) { + setQuiet(false); // Quiet is mutually exclusive. + remote_state[21] |= powerful; + } else { + remote_state[21] &= ~powerful; + } +} + +uint16_t IRPanasonicAc::encodeTime(const uint8_t hours, const uint8_t mins) { + return std::min(hours, (uint8_t)23) * 60 + std::min(mins, (uint8_t)59); +} + +uint16_t IRPanasonicAc::getClock() { + uint16_t result = ((remote_state[25] & 0b00000111) << 8) + remote_state[24]; + if (result == kPanasonicAcTimeSpecial) return 0; + return result; +} + +void IRPanasonicAc::setClock(const uint16_t mins_since_midnight) { + uint16_t corrected = std::min(mins_since_midnight, kPanasonicAcTimeMax); + if (mins_since_midnight == kPanasonicAcTimeSpecial) + corrected = kPanasonicAcTimeSpecial; + remote_state[24] = corrected & 0xFF; + remote_state[25] &= 0b11111000; + remote_state[25] |= (corrected >> 8); +} + +uint16_t IRPanasonicAc::getOnTimer() { + uint16_t result = ((remote_state[19] & 0b00000111) << 8) + remote_state[18]; + if (result == kPanasonicAcTimeSpecial) return 0; + return result; +} + +void IRPanasonicAc::setOnTimer(const uint16_t mins_since_midnight, + const bool enable) { + // Ensure it's on a 10 minute boundary and no overflow. + uint16_t corrected = std::min(mins_since_midnight, kPanasonicAcTimeMax); + corrected -= corrected % 10; + if (mins_since_midnight == kPanasonicAcTimeSpecial) + corrected = kPanasonicAcTimeSpecial; + + if (enable) + remote_state[13] |= kPanasonicAcOnTimer; // Set the Ontimer flag. + else + remote_state[13] &= ~kPanasonicAcOnTimer; // Clear the Ontimer flag. + // Store the time. + remote_state[18] = corrected & 0xFF; + remote_state[19] &= 0b11111000; + remote_state[19] |= (corrected >> 8); +} + +void IRPanasonicAc::cancelOnTimer() { setOnTimer(0, false); } + +bool IRPanasonicAc::isOnTimerEnabled() { + return remote_state[13] & kPanasonicAcOnTimer; +} + +uint16_t IRPanasonicAc::getOffTimer() { + uint16_t result = + ((remote_state[20] & 0b01111111) << 4) + (remote_state[19] >> 4); + if (result == kPanasonicAcTimeSpecial) return 0; + return result; +} + +void IRPanasonicAc::setOffTimer(const uint16_t mins_since_midnight, + const bool enable) { + // Ensure its on a 10 minute boundary and no overflow. + uint16_t corrected = std::min(mins_since_midnight, kPanasonicAcTimeMax); + corrected -= corrected % 10; + if (mins_since_midnight == kPanasonicAcTimeSpecial) + corrected = kPanasonicAcTimeSpecial; + + if (enable) + remote_state[13] |= kPanasonicAcOffTimer; // Set the OffTimer flag. + else + remote_state[13] &= ~kPanasonicAcOffTimer; // Clear the OffTimer flag. + // Store the time. + remote_state[19] &= 0b00001111; + remote_state[19] |= (corrected & 0b00001111) << 4; + remote_state[20] &= 0b10000000; + remote_state[20] |= corrected >> 4; +} + +void IRPanasonicAc::cancelOffTimer() { setOffTimer(0, false); } + +bool IRPanasonicAc::isOffTimerEnabled() { + return remote_state[13] & kPanasonicAcOffTimer; +} + +#ifdef ARDUINO +String IRPanasonicAc::timeToString(const uint16_t mins_since_midnight) { + String result = ""; +#else +std::string IRPanasonicAc::timeToString(const uint16_t mins_since_midnight) { + std::string result = ""; +#endif // ARDUINO + result += uint64ToString(mins_since_midnight / 60) + ":"; + uint8_t mins = mins_since_midnight % 60; + if (mins < 10) result += "0"; // Zero pad the minutes. + return result + uint64ToString(mins); +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRPanasonicAc::toString() { + String result = ""; +#else +std::string IRPanasonicAc::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Model: " + uint64ToString(getModel()); + switch (getModel()) { + case kPanasonicDke: + result += " (DKE)"; + break; + case kPanasonicJke: + result += " (JKE)"; + break; + case kPanasonicNke: + result += " (NKE)"; + break; + case kPanasonicLke: + result += " (LKE)"; + break; + case kPanasonicCkp: + result += " (CKP)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kPanasonicAcAuto: + result += " (AUTO)"; + break; + case kPanasonicAcCool: + result += " (COOL)"; + break; + case kPanasonicAcHeat: + result += " (HEAT)"; + break; + case kPanasonicAcDry: + result += " (DRY)"; + break; + case kPanasonicAcFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kPanasonicAcFanAuto: + result += " (AUTO)"; + break; + case kPanasonicAcFanMax: + result += " (MAX)"; + break; + case kPanasonicAcFanMin: + result += " (MIN)"; + break; + default: + result += " (UNKNOWN)"; + break; + } + result += ", Swing (Vertical): " + uint64ToString(getSwingVertical()); + switch (getSwingVertical()) { + case kPanasonicAcSwingVAuto: + result += " (AUTO)"; + break; + case kPanasonicAcSwingVUp: + result += " (Full Up)"; + break; + case kPanasonicAcSwingVDown: + result += " (Full Down)"; + break; + case 2: + case 3: + case 4: + break; + default: + result += " (UNKNOWN)"; + break; + } + switch (getModel()) { + case kPanasonicJke: + case kPanasonicCkp: + break; // No Horizontal Swing support. + default: + result += ", Swing (Horizontal): " + uint64ToString(getSwingHorizontal()); + switch (getSwingHorizontal()) { + case kPanasonicAcSwingHAuto: + result += " (AUTO)"; + break; + case kPanasonicAcSwingHFullLeft: + result += " (Full Left)"; + break; + case kPanasonicAcSwingHLeft: + result += " (Left)"; + break; + case kPanasonicAcSwingHMiddle: + result += " (Middle)"; + break; + case kPanasonicAcSwingHFullRight: + result += " (Full Right)"; + break; + case kPanasonicAcSwingHRight: + result += " (Right)"; + break; + default: + result += " (UNKNOWN)"; + break; + } + } + result += ", Quiet: "; + if (getQuiet()) + result += "On"; + else + result += "Off"; + result += ", Powerful: "; + if (getPowerful()) + result += "On"; + else + result += "Off"; + result += ", Clock: " + timeToString(getClock()); + result += ", On Timer: "; + if (isOnTimerEnabled()) + result += timeToString(getOnTimer()); + else + result += "Off"; + result += ", Off Timer: "; + if (isOffTimerEnabled()) + result += timeToString(getOffTimer()); + else + result += "Off"; + return result; +} + +#if DECODE_PANASONIC_AC +// Decode the supplied Panasonic AC message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kPanasonicAcBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Beta / Appears to work with real device(s). +// +// Panasonic A/C models supported: +// A/C Series/models: +// JKE, LKE, DKE, & NKE series. +// CS-YW9MKD +// A/C Remotes: +// A75C3747 (Confirmed) +// A75C3704 +bool IRrecv::decodePanasonicAC(decode_results *results, uint16_t nbits, + bool strict) { + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + uint8_t min_nr_of_messages = 1; + if (strict) { + if (nbits != kPanasonicAcBits && nbits != kPanasonicAcShortBits) + return false; // Not strictly a PANASONIC_AC message. + } + + if (results->rawlen < + min_nr_of_messages * (2 * nbits + kHeader + kFooter) - 1) + return false; // Can't possibly be a valid PANASONIC_AC message. + + uint16_t dataBitsSoFar = 0; + uint16_t offset = kStartOffset; + match_result_t data_result; + + // Header + if (!matchMark(results->rawbuf[offset], kPanasonicHdrMark, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = + results->rawbuf[offset++] * kRawTick / kPanasonicHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kPanasonicHdrSpace, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kPanasonicHdrSpaceTicks; + + uint16_t i = 0; + // Data (Section #1) + // Keep reading bytes until we either run out of section or state to fill. + for (; offset <= results->rawlen - 16 && i < kPanasonicAcSection1Length; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData( + &(results->rawbuf[offset]), 8, kPanasonicBitMarkTicks * m_tick, + kPanasonicOneSpaceTicks * s_tick, kPanasonicBitMarkTicks * m_tick, + kPanasonicZeroSpaceTicks * s_tick, kPanasonicAcTolerance, + kPanasonicAcExcess, false); + if (data_result.success == false) { + DPRINT("DEBUG: offset = "); + DPRINTLN(offset + data_result.used); + return false; // Fail + } + results->state[i] = data_result.data; + } + // Section footer. + if (!matchMark(results->rawbuf[offset++], kPanasonicBitMarkTicks * m_tick, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + if (!matchSpace(results->rawbuf[offset++], kPanasonicAcSectionGap, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + // Header. + if (!matchMark(results->rawbuf[offset++], kPanasonicHdrMarkTicks * m_tick, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + if (!matchSpace(results->rawbuf[offset++], kPanasonicHdrSpaceTicks * s_tick, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + // Data (Section #2) + // Keep reading bytes until we either run out of data. + for (; offset <= results->rawlen - 16 && i < nbits / 8; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData( + &(results->rawbuf[offset]), 8, kPanasonicBitMarkTicks * m_tick, + kPanasonicOneSpaceTicks * s_tick, kPanasonicBitMarkTicks * m_tick, + kPanasonicZeroSpaceTicks * s_tick, kPanasonicAcTolerance, + kPanasonicAcExcess, false); + if (data_result.success == false) { + DPRINT("DEBUG: offset = "); + DPRINTLN(offset + data_result.used); + return false; // Fail + } + results->state[i] = data_result.data; + } + // Message Footer. + if (!matchMark(results->rawbuf[offset++], kPanasonicBitMarkTicks * m_tick, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kPanasonicAcMessageGap)) + return false; + + // Compliance + if (strict) { + // Check the signatures of the section blocks. They start with 0x02& 0x20. + if (results->state[0] != 0x02 || results->state[1] != 0x20 || + results->state[8] != 0x02 || results->state[9] != 0x20) + return false; + if (!IRPanasonicAc::validChecksum(results->state, nbits / 8)) return false; + } + + // Success + results->decode_type = PANASONIC_AC; + results->bits = nbits; + return true; +} +#endif // DECODE_PANASONIC_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h new file mode 100644 index 000000000..762631fe7 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h @@ -0,0 +1,145 @@ +// Copyright 2018 David Conran + +#ifndef IR_PANASONIC_H_ +#define IR_PANASONIC_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef ARDUINO +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC +// P P A A NN N A A S O O NN N I C +// PPPP AAAAA N N N AAAAA SSS O O N N N I C +// P A A N NN A A S O O N NN I C +// P A A N N A A SSSS OOO N N IIIII CCCC + +// Panasonic A/C support heavily influenced by: +// https://github.com/ToniA/ESPEasy/blob/HeatpumpIR/lib/HeatpumpIR/PanasonicHeatpumpIR.cpp + +// Constants +const uint16_t kPanasonicFreq = 36700; +const uint16_t kPanasonicAcExcess = 0; +// Much higher than usual. See issue #540. +const uint16_t kPanasonicAcTolerance = 40; + +const uint8_t kPanasonicAcAuto = 0; // 0b0000 +const uint8_t kPanasonicAcDry = 2; // 0b0010 +const uint8_t kPanasonicAcCool = 3; // 0b0011 +const uint8_t kPanasonicAcHeat = 4; // 0b0010 +const uint8_t kPanasonicAcFan = 6; // 0b0110 +const uint8_t kPanasonicAcFanMin = 0; +const uint8_t kPanasonicAcFanMax = 4; +const uint8_t kPanasonicAcFanAuto = 7; +const uint8_t kPanasonicAcFanOffset = 3; +const uint8_t kPanasonicAcPower = 1; // 0b1 +const uint8_t kPanasonicAcMinTemp = 16; // Celsius +const uint8_t kPanasonicAcMaxTemp = 30; // Celsius +const uint8_t kPanasonicAcFanModeTemp = 27; // Celsius +const uint8_t kPanasonicAcQuiet = 1; // 0b1 +const uint8_t kPanasonicAcPowerful = 0x20; // 0b100000 +// CKP models have Powerful and Quiet bits swapped. +const uint8_t kPanasonicAcQuietCkp = 0x20; // 0b100000 +const uint8_t kPanasonicAcPowerfulCkp = 1; // 0b1 +const uint8_t kPanasonicAcSwingVAuto = 0xF; +const uint8_t kPanasonicAcSwingVUp = 0x1; +const uint8_t kPanasonicAcSwingVDown = 0x5; +const uint8_t kPanasonicAcSwingHAuto = 0xD; +const uint8_t kPanasonicAcSwingHMiddle = 0x6; +const uint8_t kPanasonicAcSwingHFullLeft = 0x9; +const uint8_t kPanasonicAcSwingHLeft = 0xA; +const uint8_t kPanasonicAcSwingHRight = 0xB; +const uint8_t kPanasonicAcSwingHFullRight = 0xC; +const uint8_t kPanasonicAcChecksumInit = 0xF4; +const uint8_t kPanasonicAcOnTimer = 0b00000010; +const uint8_t kPanasonicAcOffTimer = 0b00000100; +const uint16_t kPanasonicAcTimeMax = 23 * 60 + 59; // Mins since midnight. +const uint16_t kPanasonicAcTimeSpecial = 0x600; + +const uint8_t kPanasonicKnownGoodState[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00}; + +enum panasonic_ac_remote_model_t { + kPanasonicUnknown = 0, + kPanasonicLke = 1, + kPanasonicNke = 2, + kPanasonicDke = 3, + kPanasonicJke = 4, + kPanasonicCkp = 5, +}; + +class IRPanasonicAc { + public: + explicit IRPanasonicAc(uint16_t pin); + + void stateReset(); +#if SEND_PANASONIC + void send(); +#endif // SEND_PANASONIC + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp, const bool remember = true); + uint8_t getTemp(); + void setFan(const uint8_t fan); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setRaw(const uint8_t state[]); + uint8_t *getRaw(); + static bool validChecksum(uint8_t *state, + const uint16_t length = kPanasonicAcStateLength); + static uint8_t calcChecksum(uint8_t *state, + const uint16_t length = kPanasonicAcStateLength); + void setQuiet(const bool state); + bool getQuiet(); + void setPowerful(const bool state); + bool getPowerful(); + void setModel(const panasonic_ac_remote_model_t model); + panasonic_ac_remote_model_t getModel(); + void setSwingVertical(const uint8_t elevation); + uint8_t getSwingVertical(); + void setSwingHorizontal(const uint8_t direction); + uint8_t getSwingHorizontal(); + static uint16_t encodeTime(const uint8_t hours, const uint8_t mins); + uint16_t getClock(); + void setClock(const uint16_t mins_since_midnight); + uint16_t getOnTimer(); + void setOnTimer(const uint16_t mins_since_midnight, const bool enable = true); + void cancelOnTimer(); + bool isOnTimerEnabled(); + uint16_t getOffTimer(); + void setOffTimer(const uint16_t mins_since_midnight, + const bool enable = true); + void cancelOffTimer(); + bool isOffTimerEnabled(); +#ifdef ARDUINO + String toString(); + static String timeToString(const uint16_t mins_since_midnight); +#else + std::string toString(); + static std::string timeToString(const uint16_t mins_since_midnight); +#endif +#ifndef UNIT_TEST + + private: +#endif + uint8_t remote_state[kPanasonicAcStateLength]; + uint8_t _swingh; + uint8_t _temp; + void fixChecksum(const uint16_t length = kPanasonicAcStateLength); + static uint8_t calcChecksum(const uint8_t *state, + const uint16_t length = kPanasonicAcStateLength); + IRsend _irsend; +}; + +#endif // IR_PANASONIC_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp new file mode 100644 index 000000000..9134e3696 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp @@ -0,0 +1,143 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017, 2018 David Conran +// Copyright 2018 Kamil Palczewski + +#define __STDC_LIMIT_MACROS +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" +#include "ir_NEC.h" + +// PPPP III OOO N N EEEE EEEE RRRR +// P P I O O NN N E E R R +// PPPP I O O N N N EEE EEE RRRR +// P I O O N NN E E R R +// P III OOO N N EEEE EEEE R RR + +// Ref: +// http://adrian-kingston.com/IRFormatPioneer.htm + +#if SEND_PIONEER +// Send a raw Pioneer formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The number of bits of the message to be sent. +// Typically kPioneerBits. +// repeat: The number of times the command is to be repeated. +// +// Status: BETA / Expected to be working. +// +// Ref: +// http://adrian-kingston.com/IRFormatPioneer.htm +void IRsend::sendPioneer(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + // If nbits is to big, or is odd, abort. + if (nbits > sizeof(data) * 8 || nbits % 2 == 1) return; + + // send 1st part of the code + sendNEC(data >> (nbits / 2), nbits / 2, 0); + // send 2nd part of the code + sendNEC(data & (((uint64_t)1 << (nbits / 2)) - 1), nbits / 2, repeat); +} + +// Calculate the raw Pioneer data code based on two NEC sub-codes +// Args: +// address A 16-bit "published" NEC value. +// command: A 16-bit "published" NEC value. +// Returns: +// A raw 64-bit Pioneer message code. +// +// Status: BETA / Expected to work. +// +// Note: +// Address & Command can be take from a decode result OR from the spreadsheets +// located at: +// https://www.pioneerelectronics.com/PUSA/Support/Home-Entertainment-Custom-Install/IR+Codes/A+V+Receivers +// where the first part is considered the address, +// and the second the command. +// e.g. +// "A556+AF20" is an Address of 0xA556 & a Command of 0xAF20. +uint64_t IRsend::encodePioneer(const uint16_t address, const uint16_t command) { + return (((uint64_t)encodeNEC(address >> 8, address & 0xFF)) << 32) | + encodeNEC(command >> 8, command & 0xFF); +} +#endif // SEND_PIONEER + +#if DECODE_PIONEER +// Decode the supplied Pioneer message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kPioneerBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should be working. (Self decodes & real examples) +// +bool IRrecv::decodePioneer(decode_results *results, const uint16_t nbits, + const bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1) + return false; // Can't possibly be a valid Pioneer message. + if (strict && nbits != kPioneerBits) + return false; // Not strictly an Pioneer message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + for (uint16_t section = 0; section < 2; section++) { + // Header + if (!matchMark(results->rawbuf[offset], kNecHdrMark)) return false; + // Calculate how long the lowest tick time is based on the header mark. + uint32_t mark_tick = + results->rawbuf[offset++] * kRawTick / kNecHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kNecHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t space_tick = + results->rawbuf[offset++] * kRawTick / kNecHdrSpaceTicks; + // + // Data + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits / 2, kNecBitMarkTicks * mark_tick, + kNecOneSpaceTicks * space_tick, kNecBitMarkTicks * mark_tick, + kNecZeroSpaceTicks * space_tick); + if (data_result.success == false) return false; + uint8_t command = data_result.data >> 8; + uint8_t command_inverted = data_result.data; + uint8_t address = data_result.data >> 24; + uint8_t address_inverted = data_result.data >> 16; + // Compliance + if (strict) { + if (command != (command_inverted ^ 0xFF)) + return false; // Command integrity failed. + if (address != (address_inverted ^ 0xFF)) + return false; // Address integrity failed. + } + data = (data << (nbits / 2)) + data_result.data; + offset += data_result.used; + // NEC-like commands and addresses are technically in LSB first order so the + // final versions have to be reversed. + uint16_t code = reverseBits((command << 8) + address, 16); + if (section) + results->command = code; + else + results->address = code; + + // Footer + if (!matchMark(results->rawbuf[offset++], kNecBitMarkTicks * mark_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kNecMinGapTicks * space_tick)) + return false; + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = PIONEER; + return true; +} +#endif // DECODE_PIONEER diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Pronto.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Pronto.cpp similarity index 81% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Pronto.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Pronto.cpp index ca76f0848..9ab5c76d0 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Pronto.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Pronto.cpp @@ -2,7 +2,6 @@ #include #include "IRsend.h" -#include "IRtimer.h" // PPPPPP tt // PP PP rr rr oooo nn nnn tt oooo @@ -11,12 +10,12 @@ // PP rr oooo nn nn tttt oooo // Constants -#define PRONTO_FREQ_FACTOR 0.241246 -#define PRONTO_TYPE_OFFSET 0U -#define PRONTO_FREQ_OFFSET 1U -#define PRONTO_SEQ_1_LEN_OFFSET 2U -#define PRONTO_SEQ_2_LEN_OFFSET 3U -#define PRONTO_DATA_OFFSET 4U +const float kProntoFreqFactor = 0.241246; +const uint16_t kProntoTypeOffset = 0; +const uint16_t kProntoFreqOffset = 1; +const uint16_t kProntoSeq1LenOffset = 2; +const uint16_t kProntoSeq2LenOffset = 3; +const uint16_t kProntoDataOffset = 4; #if SEND_PRONTO // Send a Pronto Code formatted message. @@ -50,29 +49,29 @@ // 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, // 0x0018, 0x03f6}; // // Send the Pronto(Sony) code. Repeat twice as Sony's require that. -// sendPronto(prontoCode, 46, SONY_MIN_REPEAT); +// sendPronto(prontoCode, 46, kSonyMinRepeat); // // Ref: // http://www.etcwiki.org/wiki/Pronto_Infrared_Format // http://www.remotecentral.com/features/irdisp2.htm void IRsend::sendPronto(uint16_t data[], uint16_t len, uint16_t repeat) { // Check we have enough data to work out what to send. - if (len < PRONTO_MIN_LENGTH) return; + if (len < kProntoMinLength) return; // We only know how to deal with 'raw' pronto codes types. Reject all others. - if (data[PRONTO_TYPE_OFFSET] != 0) return; + if (data[kProntoTypeOffset] != 0) return; // Pronto frequency is in Hz. - uint16_t hz = (uint16_t) (1000000U / (data[PRONTO_FREQ_OFFSET] * - PRONTO_FREQ_FACTOR)); + uint16_t hz = + (uint16_t)(1000000U / (data[kProntoFreqOffset] * kProntoFreqFactor)); enableIROut(hz); // Grab the length of the two sequences. - uint16_t seq_1_len = data[PRONTO_SEQ_1_LEN_OFFSET] * 2; - uint16_t seq_2_len = data[PRONTO_SEQ_2_LEN_OFFSET] * 2; + uint16_t seq_1_len = data[kProntoSeq1LenOffset] * 2; + uint16_t seq_2_len = data[kProntoSeq2LenOffset] * 2; // Calculate where each sequence starts in the buffer. - uint16_t seq_1_start = PRONTO_DATA_OFFSET; - uint16_t seq_2_start = PRONTO_DATA_OFFSET + seq_1_len; + uint16_t seq_1_start = kProntoDataOffset; + uint16_t seq_2_start = kProntoDataOffset + seq_1_len; uint32_t periodic_time = calcUSecPeriod(hz, false); diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_RC5_RC6.cpp similarity index 70% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_RC5_RC6.cpp index 65aaf88d7..ef1500d60 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_RC5_RC6.cpp @@ -21,30 +21,31 @@ // Ref: // https://en.wikipedia.org/wiki/RC-5 // http://www.sbprojects.com/knowledge/ir/rc5.php -#define MIN_RC5_SAMPLES 11U -#define MIN_RC6_SAMPLES 1U -#define RC5_T1 889U -#define RC5_MIN_COMMAND_LENGTH 113778UL -#define RC5_MIN_GAP (RC5_MIN_COMMAND_LENGTH - RC5_RAW_BITS * (2 * RC5_T1)) -#define RC5_TOGGLE_MASK 0x800U // (The 12th bit) + +const uint16_t kRc5T1 = 889; +const uint32_t kRc5MinCommandLength = 113778; +const uint32_t kRc5MinGap = kRc5MinCommandLength - kRC5RawBits * (2 * kRc5T1); +const uint16_t kRc5ToggleMask = 0x800; // The 12th bit. +const uint16_t kRc5SamplesMin = 11; + // RC-6 // Ref: // https://en.wikipedia.org/wiki/RC-6 // http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/ -#define RC6_TICK 444U -#define RC6_HDR_MARK_TICKS 6U -#define RC6_HDR_MARK (RC6_HDR_MARK_TICKS * RC6_TICK) -#define RC6_HDR_SPACE_TICKS 2U -#define RC6_HDR_SPACE (RC6_HDR_SPACE_TICKS * RC6_TICK) -#define RC6_RPT_LENGTH_TICKS 187U -#define RC6_RPT_LENGTH (RC6_RPT_LENGTH_TICKS * RC6_TICK) -#define RC6_TOGGLE_MASK 0x10000UL // (The 17th bit) -#define RC6_36_TOGGLE_MASK 0x8000U // (The 16th bit) + +const uint16_t kRc6Tick = 444; +const uint16_t kRc6HdrMarkTicks = 6; +const uint16_t kRc6HdrMark = kRc6HdrMarkTicks * kRc6Tick; +const uint16_t kRc6HdrSpaceTicks = 2; +const uint16_t kRc6HdrSpace = kRc6HdrSpaceTicks * kRc6Tick; +const uint16_t kRc6RptLengthTicks = 187; +const uint32_t kRc6RptLength = kRc6RptLengthTicks * kRc6Tick; +const uint32_t kRc6ToggleMask = 0x10000UL; // The 17th bit. +const uint16_t kRc6_36ToggleMask = 0x8000; // The 16th bit. // Common (getRClevel()) -#define MARK 0U -#define SPACE 1U - +const int16_t kMark = 0; +const int16_t kSpace = 1; #if SEND_RC5 // Send a Philips RC-5/RC-5X packet. @@ -68,14 +69,13 @@ // TODO(anyone): // Testing of the RC-5X components. void IRsend::sendRC5(uint64_t data, uint16_t nbits, uint16_t repeat) { - if (nbits > sizeof(data) * 8) - return; // We can't send something that big. + if (nbits > sizeof(data) * 8) return; // We can't send something that big. bool skipSpace = true; bool field_bit = true; // Set 36kHz IR carrier frequency & a 1/4 (25%) duty cycle. enableIROut(36, 25); - if (nbits >= RC5X_BITS) { // Is this a RC-5X message? + if (nbits >= kRC5XBits) { // Is this a RC-5X message? // field bit is the inverted MSB of RC-5X data. field_bit = ((data >> (nbits - 1)) ^ 1) & 1; nbits--; @@ -90,28 +90,28 @@ void IRsend::sendRC5(uint64_t data, uint16_t nbits, uint16_t repeat) { if (skipSpace) skipSpace = false; // First time through, we assume the leading space(). else - space(RC5_T1); - mark(RC5_T1); + space(kRc5T1); + mark(kRc5T1); // Field/Second start bit. if (field_bit) { // Send a 1. Normal for RC-5. - space(RC5_T1); - mark(RC5_T1); + space(kRc5T1); + mark(kRc5T1); } else { // Send a 0. Special case for RC-5X. Means 7th command bit is 1. - mark(RC5_T1); - space(RC5_T1); + mark(kRc5T1); + space(kRc5T1); } // Data for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) if (data & mask) { // 1 - space(RC5_T1); // 1 is space, then mark. - mark(RC5_T1); - } else { // 0 - mark(RC5_T1); // 0 is mark, then space. - space(RC5_T1); + space(kRc5T1); // 1 is space, then mark. + mark(kRc5T1); + } else { // 0 + mark(kRc5T1); // 0 is mark, then space. + space(kRc5T1); } // Footer - space(std::max(RC5_MIN_GAP, RC5_MIN_COMMAND_LENGTH - usecTimer.elapsed())); + space(std::max(kRc5MinGap, kRc5MinCommandLength - usecTimer.elapsed())); } } @@ -132,8 +132,7 @@ void IRsend::sendRC5(uint64_t data, uint16_t nbits, uint16_t repeat) { // https://en.wikipedia.org/wiki/RC-5 uint16_t IRsend::encodeRC5(uint8_t address, uint8_t command, bool key_released) { - return (key_released << (RC5_BITS - 1)) | - ((address & 0x1f) << 6) | + return (key_released << (kRC5Bits - 1)) | ((address & 0x1f) << 6) | (command & 0x3F); } @@ -157,8 +156,8 @@ uint16_t IRsend::encodeRC5X(uint8_t address, uint8_t command, // The 2nd start/field bit (MSB of the return value) is the value of the 7th // command bit. bool s2 = (command >> 6) & 1; - return ((uint16_t) s2 << (RC5X_BITS - 1)) | - encodeRC5(address, command, key_released); + return ((uint16_t)s2 << (kRC5XBits - 1)) | + encodeRC5(address, command, key_released); } // Flip the toggle bit of a Philips RC-5/RC-5X data message. @@ -175,9 +174,7 @@ uint16_t IRsend::encodeRC5X(uint8_t address, uint8_t command, // Ref: // http://www.sbprojects.com/knowledge/ir/rc5.php // https://en.wikipedia.org/wiki/RC-5 -uint64_t IRsend::toggleRC5(uint64_t data) { - return data ^ RC5_TOGGLE_MASK; -} +uint64_t IRsend::toggleRC5(uint64_t data) { return data ^ kRc5ToggleMask; } #endif // SEND_RC5 #if SEND_RC6 @@ -199,9 +196,8 @@ uint64_t IRsend::toggleRC5(uint64_t data) { // http://www.sbprojects.com/knowledge/ir/rc6.php // http://www.righto.com/2010/12/64-bit-rc6-codes-arduino-and-xbox.html uint64_t IRsend::toggleRC6(uint64_t data, uint16_t nbits) { - if (nbits == RC6_36_BITS) - return data ^ RC6_36_TOGGLE_MASK; - return data ^ RC6_TOGGLE_MASK; + if (nbits == kRC6_36Bits) return data ^ kRc6_36ToggleMask; + return data ^ kRc6ToggleMask; } // Encode a Philips RC-6 data message. @@ -221,13 +217,12 @@ uint64_t IRsend::toggleRC6(uint64_t data, uint16_t nbits) { // http://www.sbprojects.com/knowledge/ir/rc6.php // http://www.righto.com/2010/12/64-bit-rc6-codes-arduino-and-xbox.html // http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/ -uint64_t IRsend::encodeRC6(uint32_t address, uint8_t command, - uint16_t mode) { +uint64_t IRsend::encodeRC6(uint32_t address, uint8_t command, uint16_t mode) { switch (mode) { - case RC6_MODE0_BITS: + case kRC6Mode0Bits: return ((address & 0xFFF) << 8) | (command & 0xFF); - case RC6_36_BITS: - return ((uint64_t) (address & 0xFFFFFFF) << 8) | (command & 0xFF); + case kRC6_36Bits: + return ((uint64_t)(address & 0xFFFFFFF) << 8) | (command & 0xFF); default: return 0; } @@ -250,25 +245,24 @@ uint64_t IRsend::encodeRC6(uint32_t address, uint8_t command, // https://en.wikipedia.org/wiki/Manchester_code void IRsend::sendRC6(uint64_t data, uint16_t nbits, uint16_t repeat) { // Check we can send the number of bits requested. - if (nbits > sizeof(data) * 8) - return; + if (nbits > sizeof(data) * 8) return; // Set 36kHz IR carrier frequency & a 1/3 (33%) duty cycle. enableIROut(36, 33); for (uint16_t r = 0; r <= repeat; r++) { // Header - mark(RC6_HDR_MARK); - space(RC6_HDR_SPACE); + mark(kRc6HdrMark); + space(kRc6HdrSpace); // Start bit. - mark(RC6_TICK); // mark, then space == 0x1. - space(RC6_TICK); + mark(kRc6Tick); // mark, then space == 0x1. + space(kRc6Tick); // Data uint16_t bitTime; for (uint64_t i = 1, mask = 1ULL << (nbits - 1); mask; i++, mask >>= 1) { if (i == 4) // The fourth bit we send is a "double width trailer bit". - bitTime = 2 * RC6_TICK; // double-wide trailer bit + bitTime = 2 * kRc6Tick; // double-wide trailer bit else - bitTime = RC6_TICK; // Normal bit - if (data & mask) { // 1 + bitTime = kRc6Tick; // Normal bit + if (data & mask) { // 1 mark(bitTime); space(bitTime); } else { // 0 @@ -277,12 +271,12 @@ void IRsend::sendRC6(uint64_t data, uint16_t nbits, uint16_t repeat) { } } // Footer - space(RC6_RPT_LENGTH); + space(kRc6RptLength); } } #endif // SEND_RC6 -#if (DECODE_RC5 || DECODE_RC6) +#if (DECODE_RC5 || DECODE_RC6 || DECODE_LASERTAG) // Gets one undecoded level at a time from the raw buffer. // The RC5/6 decoding is easier if the data is broken into time intervals. // E.g. if the buffer has MARK for 2 time intervals and SPACE for 1, @@ -294,47 +288,65 @@ void IRsend::sendRC6(uint64_t data, uint16_t nbits, uint16_t repeat) { // offset: Ptr to the currect offset to the rawbuf. // used: Ptr to the current used counter. // bitTime: Time interval of single bit in microseconds. +// maxwidth: Maximum number of successive levels to find in a single level +// (default 3) // Returns: // int: MARK, SPACE, or -1 for error (The measured time interval is not a // multiple of t1.) // Ref: // https://en.wikipedia.org/wiki/Manchester_code -int16_t IRrecv::getRClevel(decode_results *results, uint16_t *offset, - uint16_t *used, uint16_t bitTime) { - if (*offset >= results->rawlen) - return SPACE; // After end of recorded buffer, assume SPACE. +int16_t IRrecv::getRClevel(decode_results *results, uint16_t *offset, + uint16_t *used, uint16_t bitTime, uint8_t tolerance, + int16_t excess, uint16_t delta, uint8_t maxwidth) { + DPRINT("DEBUG: getRClevel: offset = "); + DPRINTLN(uint64ToString(*offset)); + DPRINT("DEBUG: getRClevel: rawlen = "); + DPRINTLN(uint64ToString(results->rawlen)); + if (*offset >= results->rawlen) { + DPRINTLN("DEBUG: getRClevel: SPACE, past end of rawbuf"); + return kSpace; // After end of recorded buffer, assume SPACE. + } uint16_t width = results->rawbuf[*offset]; // If the value of offset is odd, it's a MARK. Even, it's a SPACE. - uint16_t val = ((*offset) % 2) ? MARK : SPACE; + uint16_t val = ((*offset) % 2) ? kMark : kSpace; // Check to see if we have hit an inter-message gap (> 20ms). - if (val == SPACE && width > 20000) - return SPACE; - int16_t correction = (val == MARK) ? MARK_EXCESS : -MARK_EXCESS; + if (val == kSpace && + (width > 20000 - delta || width > maxwidth * bitTime + delta)) { + DPRINTLN("DEBUG: getRClevel: SPACE, hit end of mesg gap."); + return kSpace; + } + int16_t correction = (val == kMark) ? excess : -excess; // Calculate the look-ahead for our current position in the buffer. uint16_t avail; // Note: We want to match in greedy order as the other way leads to // mismatches due to overlaps induced by the correction and tolerance // values. - if (match(width, 3 * bitTime + correction)) - avail = 3; - else if (match(width, 2 * bitTime + correction)) - avail = 2; - else if (match(width, bitTime + correction)) - avail = 1; - else + for (avail = maxwidth; avail > 0; avail--) { + if (match(width, avail * bitTime + correction, tolerance, delta)) { + break; + } + } + if (!avail) { + DPRINTLN("DEBUG: getRClevel: Unexpected width. Exiting."); return -1; // The width is not what we expected. + } - (*used)++; // Count another one of the avail slots as used. + (*used)++; // Count another one of the avail slots as used. if (*used >= avail) { // Are we out of look-ahead/avail slots? // Yes, so reset the used counter, and move the offset ahead. *used = 0; (*offset)++; } + if (val == kMark) { + DPRINTLN("DEBUG: getRClevel: MARK"); + } else { + DPRINTLN("DEBUG: getRClevel: SPACE"); + } return val; } -#endif // (DECODE_RC5 || DECODE_RC6) +#endif // (DECODE_RC5 || DECODE_RC6 || DECODE_LASERTAG) #if DECODE_RC5 // Decode the supplied RC-5/RC5X message. @@ -358,28 +370,28 @@ int16_t IRrecv::getRClevel(decode_results *results, uint16_t *offset, // TODO(anyone): // Serious testing of the RC-5X and strict aspects needs to be done. bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < MIN_RC5_SAMPLES + HEADER - 1) return false; + if (results->rawlen < kRc5SamplesMin + kHeader - 1) return false; // Compliance - if (strict && nbits != RC5_BITS && nbits != RC5X_BITS) + if (strict && nbits != kRC5Bits && nbits != kRC5XBits) return false; // It's neither RC-5 or RC-5X. - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; uint16_t used = 0; bool is_rc5x = false; uint64_t data = 0; // Header // Get start bit #1. - if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false; + if (getRClevel(results, &offset, &used, kRc5T1) != kMark) return false; // Get field/start bit #2 (inverted bit-7 of the command if RC-5X protocol) uint16_t actual_bits = 1; - int16_t levelA = getRClevel(results, &offset, &used, RC5_T1); - int16_t levelB = getRClevel(results, &offset, &used, RC5_T1); - if (levelA == SPACE && levelB == MARK) { // Matched a 1. + int16_t levelA = getRClevel(results, &offset, &used, kRc5T1); + int16_t levelB = getRClevel(results, &offset, &used, kRc5T1); + if (levelA == kSpace && levelB == kMark) { // Matched a 1. is_rc5x = false; - } else if (levelA == MARK && levelB == SPACE) { // Matched a 0. - if (nbits <= RC5_BITS) return false; // Field bit must be '1' for RC5. + } else if (levelA == kMark && levelB == kSpace) { // Matched a 0. + if (nbits <= kRC5Bits) return false; // Field bit must be '1' for RC5. is_rc5x = true; data = 1; } else { @@ -388,11 +400,11 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { // Data for (; offset < results->rawlen; actual_bits++) { - int16_t levelA = getRClevel(results, &offset, &used, RC5_T1); - int16_t levelB = getRClevel(results, &offset, &used, RC5_T1); - if (levelA == SPACE && levelB == MARK) + int16_t levelA = getRClevel(results, &offset, &used, kRc5T1); + int16_t levelB = getRClevel(results, &offset, &used, kRc5T1); + if (levelA == kSpace && levelB == kMark) data = (data << 1) | 1; // 1 - else if (levelA == MARK && levelB == SPACE) + else if (levelA == kMark && levelB == kSpace) data <<= 1; // 0 else break; @@ -401,8 +413,8 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { // Compliance if (actual_bits < nbits) return false; // Less data than we expected. - if (strict && actual_bits != RC5_BITS && - actual_bits != RC5X_BITS) return false; + if (strict && actual_bits != kRC5Bits && actual_bits != kRC5XBits) + return false; // Success results->value = data; @@ -411,7 +423,7 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { results->repeat = false; if (is_rc5x) { results->decode_type = RC5X; - results->command |= ((uint32_t) is_rc5x) << 6; + results->command |= ((uint32_t)is_rc5x) << 6; } else { results->decode_type = RC5; actual_bits--; // RC5 doesn't count the field bit as data. @@ -439,7 +451,7 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { // TODO(anyone): // Testing of the strict compliance aspects. bool IRrecv::decodeRC6(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < HEADER + 2 + 4) // Up to the double-wide T bit. + if (results->rawlen < kHeader + 2 + 4) // Up to the double-wide T bit. return false; // Smaller than absolute smallest possible RC6 message. if (strict) { // Compliance @@ -449,31 +461,31 @@ bool IRrecv::decodeRC6(decode_results *results, uint16_t nbits, bool strict) { // Also due to potential melding with the start bit, we can only count // the start bit as 1, instead of a more typical 2 value. The header still // remains as normal. - if (results->rawlen < nbits + HEADER + 1) + if (results->rawlen < nbits + kHeader + 1) return false; // Don't have enough entries/samples to be valid. switch (nbits) { - case RC6_MODE0_BITS: - case RC6_36_BITS: + case kRC6Mode0Bits: + case kRC6_36Bits: break; default: return false; // Asking for the wrong number of bits. } } - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // Header - if (!matchMark(results->rawbuf[offset], RC6_HDR_MARK)) return false; + if (!matchMark(results->rawbuf[offset], kRc6HdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t tick = results->rawbuf[offset++] * RAWTICK / RC6_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset++], RC6_HDR_SPACE_TICKS * tick)) + uint32_t tick = results->rawbuf[offset++] * kRawTick / kRc6HdrMarkTicks; + if (!matchSpace(results->rawbuf[offset++], kRc6HdrSpaceTicks * tick)) return false; uint16_t used = 0; // Get the start bit. e.g. 1. - if (getRClevel(results, &offset, &used, tick) != MARK) return false; - if (getRClevel(results, &offset, &used, tick) != SPACE) return false; + if (getRClevel(results, &offset, &used, tick) != kMark) return false; + if (getRClevel(results, &offset, &used, tick) != kSpace) return false; uint16_t actual_bits; uint64_t data = 0; @@ -483,17 +495,15 @@ bool IRrecv::decodeRC6(decode_results *results, uint16_t nbits, bool strict) { int16_t levelA, levelB; // Next two levels levelA = getRClevel(results, &offset, &used, tick); // T bit is double wide; make sure second half matches - if (actual_bits == 3 && - levelA != getRClevel(results, &offset, &used, tick)) + if (actual_bits == 3 && levelA != getRClevel(results, &offset, &used, tick)) return false; levelB = getRClevel(results, &offset, &used, tick); // T bit is double wide; make sure second half matches - if (actual_bits == 3 && - levelB != getRClevel(results, &offset, &used, tick)) + if (actual_bits == 3 && levelB != getRClevel(results, &offset, &used, tick)) return false; - if (levelA == MARK && levelB == SPACE) // reversed compared to RC5 - data = (data << 1) | 1; // 1 - else if (levelA == SPACE && levelB == MARK) + if (levelA == kMark && levelB == kSpace) // reversed compared to RC5 + data = (data << 1) | 1; // 1 + else if (levelA == kSpace && levelB == kMark) data <<= 1; // 0 else break; diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_RCMM.cpp similarity index 58% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_RCMM.cpp index 362702b66..1b03d2c07 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_RCMM.cpp @@ -17,28 +17,28 @@ // Constants // Ref: // http://www.sbprojects.com/knowledge/ir/rcmm.php -#define RCMM_TICK 28U // Technically it would be 27.777* -#define RCMM_HDR_MARK_TICKS 15U -#define RCMM_HDR_MARK 416U -#define RCMM_HDR_SPACE_TICKS 10U -#define RCMM_HDR_SPACE 277U -#define RCMM_BIT_MARK_TICKS 6U -#define RCMM_BIT_MARK 166U -#define RCMM_BIT_SPACE_0_TICKS 10U -#define RCMM_BIT_SPACE_0 277U -#define RCMM_BIT_SPACE_1_TICKS 16U -#define RCMM_BIT_SPACE_1 444U -#define RCMM_BIT_SPACE_2_TICKS 22U -#define RCMM_BIT_SPACE_2 611U -#define RCMM_BIT_SPACE_3_TICKS 28U -#define RCMM_BIT_SPACE_3 777U -#define RCMM_RPT_LENGTH_TICKS 992U -#define RCMM_RPT_LENGTH 27778U -#define RCMM_MIN_GAP_TICKS 120U -#define RCMM_MIN_GAP 3360U +const uint16_t kRcmmTick = 28; // Technically it would be 27.777* +const uint16_t kRcmmHdrMarkTicks = 15; +const uint16_t kRcmmHdrMark = 416; +const uint16_t kRcmmHdrSpaceTicks = 10; +const uint16_t kRcmmHdrSpace = 277; +const uint16_t kRcmmBitMarkTicks = 6; +const uint16_t kRcmmBitMark = 166; +const uint16_t kRcmmBitSpace0Ticks = 10; +const uint16_t kRcmmBitSpace0 = 277; +const uint16_t kRcmmBitSpace1Ticks = 16; +const uint16_t kRcmmBitSpace1 = 444; +const uint16_t kRcmmBitSpace2Ticks = 22; +const uint16_t kRcmmBitSpace2 = 611; +const uint16_t kRcmmBitSpace3Ticks = 28; +const uint16_t kRcmmBitSpace3 = 777; +const uint16_t kRcmmRptLengthTicks = 992; +const uint32_t kRcmmRptLength = 27778; +const uint16_t kRcmmMinGapTicks = 120; +const uint32_t kRcmmMinGap = 3360; // Use a tolerance of +/-10% when matching some data spaces. -#define RCMM_TOLERANCE 10U -#define RCMM_EXCESS 50U +const uint8_t kRcmmTolerance = 10; +const uint16_t kRcmmExcess = 50; #if SEND_RCMM // Send a Philips RC-MM packet. @@ -60,27 +60,35 @@ void IRsend::sendRCMM(uint64_t data, uint16_t nbits, uint16_t repeat) { for (uint16_t r = 0; r <= repeat; r++) { usecs.reset(); // Header - mark(RCMM_HDR_MARK); - space(RCMM_HDR_SPACE); + mark(kRcmmHdrMark); + space(kRcmmHdrSpace); // Data uint64_t mask = 0b11ULL << (nbits - 2); // RC-MM sends data 2 bits at a time. for (int32_t i = nbits; i > 0; i -= 2) { - mark(RCMM_BIT_MARK); + mark(kRcmmBitMark); // Grab the next Most Significant Bits to send. switch ((data & mask) >> (i - 2)) { - case 0b00: space(RCMM_BIT_SPACE_0); break; - case 0b01: space(RCMM_BIT_SPACE_1); break; - case 0b10: space(RCMM_BIT_SPACE_2); break; - case 0b11: space(RCMM_BIT_SPACE_3); break; + case 0b00: + space(kRcmmBitSpace0); + break; + case 0b01: + space(kRcmmBitSpace1); + break; + case 0b10: + space(kRcmmBitSpace2); + break; + case 0b11: + space(kRcmmBitSpace3); + break; } mask >>= 2; } // Footer - mark(RCMM_BIT_MARK); - // Protocol requires us to wait at least RCMM_RPT_LENGTH usecs from the - // start or RCMM_MIN_GAP usecs. - space(std::max(RCMM_RPT_LENGTH - usecs.elapsed(), RCMM_MIN_GAP)); + mark(kRcmmBitMark); + // Protocol requires us to wait at least kRcmmRptLength usecs from the + // start or kRcmmMinGap usecs. + space(std::max(kRcmmRptLength - usecs.elapsed(), kRcmmMinGap)); } } #endif @@ -90,7 +98,7 @@ void IRsend::sendRCMM(uint64_t data, uint16_t nbits, uint16_t repeat) { // Places successful decode information in the results pointer. // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. Typically RCMM_BITS. +// nbits: Nr. of bits to expect in the data portion. Typically kRCMMBits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: // boolean: True if it can decode it, false if it can't. @@ -101,67 +109,65 @@ void IRsend::sendRCMM(uint64_t data, uint16_t nbits, uint16_t repeat) { // http://www.sbprojects.com/knowledge/ir/rcmm.php bool IRrecv::decodeRCMM(decode_results *results, uint16_t nbits, bool strict) { uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; if (results->rawlen <= 4) return false; // Not enough entries to ever be RCMM. // Calc the maximum size in bits, the message can be, or that we can accept. - int16_t maxBitSize = std::min((uint16_t) results->rawlen - 4, - (uint16_t) sizeof(data) * 8); + int16_t maxBitSize = + std::min((uint16_t)results->rawlen - 5, (uint16_t)sizeof(data) * 8); // Compliance if (strict) { // Technically the spec says bit sizes should be 12 xor 24. however // 32 bits has been seen from a device. We are going to assume // 12 <= bits <= 32 is the 'required' bit length for the spec. - if (maxBitSize < 12 || maxBitSize > 32) - return false; + if (maxBitSize < 12 || maxBitSize > 32) return false; if (maxBitSize < nbits) return false; // Short cut, we can never reach the expected nr. of bits. } // Header decode - if (!matchMark(results->rawbuf[offset], RCMM_HDR_MARK)) return false; + if (!matchMark(results->rawbuf[offset], kRcmmHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / RCMM_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], RCMM_HDR_SPACE)) return false; + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kRcmmHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kRcmmHdrSpace)) return false; // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / RCMM_HDR_SPACE_TICKS; + uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kRcmmHdrSpaceTicks; // Data decode // RC-MM has two bits of data per mark/space pair. uint16_t actualBits; for (actualBits = 0; actualBits < maxBitSize; actualBits += 2, offset++) { - if (!match(results->rawbuf[offset++], RCMM_BIT_MARK_TICKS * m_tick)) + if (!match(results->rawbuf[offset++], kRcmmBitMarkTicks * m_tick)) return false; data <<= 2; // Use non-default tolerance & excess for matching some of the spaces as the // defaults are too generous and causes mis-matches in some cases. - if (match(results->rawbuf[offset], RCMM_BIT_SPACE_0_TICKS * s_tick, - TOLERANCE)) + if (match(results->rawbuf[offset], kRcmmBitSpace0Ticks * s_tick, + kTolerance)) data += 0; - else if (match(results->rawbuf[offset], RCMM_BIT_SPACE_1_TICKS * s_tick, - TOLERANCE)) + else if (match(results->rawbuf[offset], kRcmmBitSpace1Ticks * s_tick, + kTolerance)) data += 1; - else if (match(results->rawbuf[offset], RCMM_BIT_SPACE_2_TICKS * s_tick, - RCMM_TOLERANCE)) + else if (match(results->rawbuf[offset], kRcmmBitSpace2Ticks * s_tick, + kRcmmTolerance)) data += 2; - else if (match(results->rawbuf[offset], RCMM_BIT_SPACE_3_TICKS * s_tick, - RCMM_TOLERANCE)) + else if (match(results->rawbuf[offset], kRcmmBitSpace3Ticks * s_tick, + kRcmmTolerance)) data += 3; else return false; } // Footer decode - if (!match(results->rawbuf[offset++], RCMM_BIT_MARK_TICKS * m_tick)) + if (!match(results->rawbuf[offset++], kRcmmBitMarkTicks * m_tick)) return false; if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], RCMM_MIN_GAP_TICKS * s_tick)) + !matchAtLeast(results->rawbuf[offset], kRcmmMinGapTicks * s_tick)) return false; // Compliance - if (strict && actualBits != nbits) - return false; + if (strict && actualBits != nbits) return false; // Success results->value = data; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp new file mode 100644 index 000000000..d943f8cf9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp @@ -0,0 +1,590 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran + +#include "ir_Samsung.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// SSSS AAA MMM SSSS U U N N GGGG +// S A A M M M S U U NN N G +// SSS AAAAA M M M SSS U U N N N G GG +// S A A M M S U U N NN G G +// SSSS A A M M SSSS UUU N N GGG + +// Samsung originally added from https://github.com/shirriff/Arduino-IRremote/ + +// Constants +// Ref: +// http://elektrolab.wz.cz/katalog/samsung_protocol.pdf +const uint16_t kSamsungTick = 560; +const uint16_t kSamsungHdrMarkTicks = 8; +const uint16_t kSamsungHdrMark = kSamsungHdrMarkTicks * kSamsungTick; +const uint16_t kSamsungHdrSpaceTicks = 8; +const uint16_t kSamsungHdrSpace = kSamsungHdrSpaceTicks * kSamsungTick; +const uint16_t kSamsungBitMarkTicks = 1; +const uint16_t kSamsungBitMark = kSamsungBitMarkTicks * kSamsungTick; +const uint16_t kSamsungOneSpaceTicks = 3; +const uint16_t kSamsungOneSpace = kSamsungOneSpaceTicks * kSamsungTick; +const uint16_t kSamsungZeroSpaceTicks = 1; +const uint16_t kSamsungZeroSpace = kSamsungZeroSpaceTicks * kSamsungTick; +const uint16_t kSamsungRptSpaceTicks = 4; +const uint16_t kSamsungRptSpace = kSamsungRptSpaceTicks * kSamsungTick; +const uint16_t kSamsungMinMessageLengthTicks = 193; +const uint32_t kSamsungMinMessageLength = + kSamsungMinMessageLengthTicks * kSamsungTick; +const uint16_t kSamsungMinGapTicks = + kSamsungMinMessageLengthTicks - + (kSamsungHdrMarkTicks + kSamsungHdrSpaceTicks + + kSamsungBits * (kSamsungBitMarkTicks + kSamsungOneSpaceTicks) + + kSamsungBitMarkTicks); +const uint32_t kSamsungMinGap = kSamsungMinGapTicks * kSamsungTick; + +const uint16_t kSamsungAcHdrMark = 690; +const uint16_t kSamsungAcHdrSpace = 17844; +const uint8_t kSamsungAcSections = 2; +const uint16_t kSamsungAcSectionMark = 3086; +const uint16_t kSamsungAcSectionSpace = 8864; +const uint16_t kSamsungAcSectionGap = 2886; +const uint16_t kSamsungAcBitMark = 586; +const uint16_t kSamsungAcOneSpace = 1432; +const uint16_t kSamsungAcZeroSpace = 436; + +#if SEND_SAMSUNG +// Send a Samsung formatted message. +// Samsung has a separate message to indicate a repeat, like NEC does. +// TODO(crankyoldgit): Confirm that is actually how Samsung sends a repeat. +// The refdoc doesn't indicate it is true. +// +// Args: +// data: The message to be sent. +// nbits: The bit size of the message being sent. typically kSamsungBits. +// repeat: The number of times the message is to be repeated. +// +// Status: BETA / Should be working. +// +// Ref: http://elektrolab.wz.cz/katalog/samsung_protocol.pdf +void IRsend::sendSAMSUNG(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kSamsungHdrMark, kSamsungHdrSpace, kSamsungBitMark, + kSamsungOneSpace, kSamsungBitMark, kSamsungZeroSpace, + kSamsungBitMark, kSamsungMinGap, kSamsungMinMessageLength, data, + nbits, 38, true, repeat, 33); +} + +// Construct a raw Samsung message from the supplied customer(address) & +// command. +// +// Args: +// customer: The customer code. (aka. Address) +// command: The command code. +// Returns: +// A raw 32-bit Samsung message suitable for sendSAMSUNG(). +// +// Status: BETA / Should be working. +uint32_t IRsend::encodeSAMSUNG(uint8_t customer, uint8_t command) { + customer = reverseBits(customer, sizeof(customer) * 8); + command = reverseBits(command, sizeof(command) * 8); + return ((command ^ 0xFF) | (command << 8) | (customer << 16) | + (customer << 24)); +} +#endif + +#if DECODE_SAMSUNG +// Decode the supplied Samsung message. +// Samsung messages whilst 32 bits in size, only contain 16 bits of distinct +// data. e.g. In transmition order: +// customer_byte + customer_byte(same) + address_byte + invert(address_byte) +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. Typically kSamsungBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE +// +// Note: +// LG 32bit protocol appears near identical to the Samsung protocol. +// They differ on their compliance criteria and how they repeat. +// Ref: +// http://elektrolab.wz.cz/katalog/samsung_protocol.pdf +bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid Samsung message. + if (strict && nbits != kSamsungBits) + return false; // We expect Samsung to be 32 bits of message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset], kSamsungHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kSamsungHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kSamsungHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kSamsungHdrSpaceTicks; + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, + kSamsungBitMarkTicks * m_tick, kSamsungOneSpaceTicks * s_tick, + kSamsungBitMarkTicks * m_tick, kSamsungZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + // Footer + if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kSamsungMinGapTicks * s_tick)) + return false; + + // Compliance + + // According to the spec, the customer (address) code is the first 8 + // transmitted bits. It's then repeated. Check for that. + uint8_t address = data >> 24; + if (strict && address != ((data >> 16) & 0xFF)) return false; + // Spec says the command code is the 3rd block of transmitted 8-bits, + // followed by the inverted command code. + uint8_t command = (data & 0xFF00) >> 8; + if (strict && command != ((data & 0xFF) ^ 0xFF)) return false; + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = SAMSUNG; + // command & address need to be reversed as they are transmitted LSB first, + results->command = reverseBits(command, sizeof(command) * 8); + results->address = reverseBits(address, sizeof(address) * 8); + return true; +} +#endif + +#if SEND_SAMSUNG_AC +// Send a Samsung A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kSamsungAcStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/505 +void IRsend::sendSamsungAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) { + if (nbytes < kSamsungAcStateLength && nbytes % kSamsungACSectionLength) + return; // Not an appropriate number of bytes to send a proper message. + + enableIROut(38); + for (uint16_t r = 0; r <= repeat; r++) { + // Header + mark(kSamsungAcHdrMark); + space(kSamsungAcHdrSpace); + // Send in 7 byte sections. + for (uint16_t offset = 0; offset < nbytes; + offset += kSamsungACSectionLength) { + sendGeneric(kSamsungAcSectionMark, kSamsungAcSectionSpace, + kSamsungAcBitMark, kSamsungAcOneSpace, kSamsungAcBitMark, + kSamsungAcZeroSpace, kSamsungAcBitMark, kSamsungAcSectionGap, + data + offset, kSamsungACSectionLength, // 7 bytes == 56 bits + 38000, false, 0, 50); // Send in LSBF order + } + // Complete made up guess at inter-message gap. + space(100000 - kSamsungAcSectionGap); + } +} +#endif // SEND_SAMSUNG_AC + +IRSamsungAc::IRSamsungAc(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRSamsungAc::stateReset() { + for (uint8_t i = 0; i < kSamsungAcExtendedStateLength; i++) + remote_state[i] = 0x0; + remote_state[0] = 0x02; + remote_state[1] = 0x92; + remote_state[2] = 0x0F; + remote_state[6] = 0xF0; + remote_state[7] = 0x01; + remote_state[8] = 0x02; + remote_state[9] = 0xAE; + remote_state[10] = 0x71; + remote_state[12] = 0x15; + remote_state[13] = 0xF0; +} + +void IRSamsungAc::begin() { _irsend.begin(); } + +uint8_t IRSamsungAc::calcChecksum(const uint8_t state[], + const uint16_t length) { + uint8_t sum = 0; + uint8_t currentbyte; + // Safety check so we don't go outside the array. + if (length <= 5) return 255; + // Shamelessly inspired by: + // https://github.com/adafruit/Raw-IR-decoder-for-Arduino/pull/3/files + // Count most of the '1' bits after the checksum location. + for (uint8_t i = length - 5; i < length - 1; i++) { + currentbyte = state[i]; + if (i == length - 5) currentbyte = state[length - 5] & 0b11111110; + for (; currentbyte; currentbyte >>= 1) + if (currentbyte & 1) sum++; + } + return (28 - sum) & 0xF; +} + +bool IRSamsungAc::validChecksum(const uint8_t state[], const uint16_t length) { + if (length <= 5) return true; // No checksum to compare with. Assume okay. + return (state[length - 6] >> 4) == calcChecksum(state, length); +} + +// Update the checksum for the internal state. +void IRSamsungAc::checksum(uint16_t length) { + if (length < 9) return; + remote_state[length - 6] &= 0x0F; + remote_state[length - 6] |= (calcChecksum(remote_state, length) << 4); +} + +#if SEND_SAMSUNG_AC +void IRSamsungAc::send(const bool calcchecksum) { + if (calcchecksum) checksum(); + _irsend.sendSamsungAC(remote_state); +} +#endif // SEND_SAMSUNG_AC + +#if SEND_SAMSUNG_AC +void IRSamsungAc::sendExtended(const bool calcchecksum) { + if (calcchecksum) checksum(); + uint8_t extended_state[kSamsungAcExtendedStateLength] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + // Copy/convert the internal state to an extended state. + for (uint16_t i = 0; i < kSamsungACSectionLength; i++) + extended_state[i] = remote_state[i]; + for (uint16_t i = kSamsungACSectionLength; i < kSamsungAcStateLength; i++) + extended_state[i + kSamsungACSectionLength] = remote_state[i]; + // Send it. + _irsend.sendSamsungAC(extended_state, kSamsungAcExtendedStateLength); +} +#endif // SEND_SAMSUNG_AC + +uint8_t *IRSamsungAc::getRaw() { + checksum(); + return remote_state; +} + +void IRSamsungAc::setRaw(const uint8_t new_code[], const uint16_t length) { + for (uint8_t i = 0; i < length && i < kSamsungAcExtendedStateLength; i++) { + remote_state[i] = new_code[i]; + } + // Shrink the extended state into a normal state. + if (length > kSamsungAcStateLength) { + for (uint8_t i = kSamsungAcStateLength; i < length; i++) + remote_state[i - kSamsungACSectionLength] = remote_state[i]; + } +} + +void IRSamsungAc::on() { + remote_state[1] &= ~kSamsungAcPowerMask1; + remote_state[6] |= kSamsungAcPowerMask2; +} + +void IRSamsungAc::off() { + remote_state[1] |= kSamsungAcPowerMask1; + remote_state[6] &= ~kSamsungAcPowerMask2; +} + +void IRSamsungAc::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +bool IRSamsungAc::getPower() { + return ((remote_state[6] & kSamsungAcPowerMask2) != 0) && + ((remote_state[1] & kSamsungAcPowerMask1) == 0); +} + +// Set the temp. in deg C +void IRSamsungAc::setTemp(const uint8_t temp) { + uint8_t newtemp = std::max(kSamsungAcMinTemp, temp); + newtemp = std::min(kSamsungAcMaxTemp, newtemp); + remote_state[11] = (remote_state[11] & ~kSamsungAcTempMask) | + ((newtemp - kSamsungAcMinTemp) << 4); +} + +// Return the set temp. in deg C +uint8_t IRSamsungAc::getTemp() { + return ((remote_state[11] & kSamsungAcTempMask) >> 4) + kSamsungAcMinTemp; +} + +void IRSamsungAc::setMode(const uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + uint8_t newmode = mode; + if (newmode > kSamsungAcHeat) newmode = kSamsungAcAuto; + remote_state[12] = (remote_state[12] & ~kSamsungAcModeMask) | (newmode << 4); + + // Auto mode has a special fan setting valid only in auto mode. + if (newmode == kSamsungAcAuto) { + setFan(kSamsungAcFanAuto2); + } else { + if (getFan() == kSamsungAcFanAuto2) // Non-Auto can't have this fan setting + setFan(kSamsungAcFanAuto); // Default to something safe. + } +} + +uint8_t IRSamsungAc::getMode() { + return (remote_state[12] & kSamsungAcModeMask) >> 4; +} + +void IRSamsungAc::setFan(const uint8_t speed) { + switch (speed) { + case kSamsungAcFanAuto: + case kSamsungAcFanLow: + case kSamsungAcFanMed: + case kSamsungAcFanHigh: + case kSamsungAcFanTurbo: + if (getMode() == kSamsungAcAuto) return; // Not valid in Auto mode. + break; + case kSamsungAcFanAuto2: // Special fan setting for when in Auto mode. + if (getMode() != kSamsungAcAuto) return; + break; + default: + return; + } + remote_state[12] = (remote_state[12] & ~kSamsungAcFanMask) | (speed << 1); +} + +uint8_t IRSamsungAc::getFan() { + return ((remote_state[12] & kSamsungAcFanMask) >> 1); +} + +bool IRSamsungAc::getSwing() { + // TODO(Hollako): Explain why sometimes the LSB of remote_state[9] is a 1. + // e.g. 0xAE or 0XAF for swing move. + return ((remote_state[9] & kSamsungAcSwingMask) >> 4) == kSamsungAcSwingMove; +} + +void IRSamsungAc::setSwing(const bool state) { + // TODO(Hollako): Explain why sometimes the LSB of remote_state[9] is a 1. + // e.g. 0xAE or 0XAF for swing move. + remote_state[9] &= ~kSamsungAcSwingMask; // Clear the previous swing state. + if (state) + remote_state[9] |= (kSamsungAcSwingMove << 4); + else + remote_state[9] |= (kSamsungAcSwingStop << 4); +} + +bool IRSamsungAc::getBeep() { return remote_state[13] & kSamsungAcBeepMask; } + +void IRSamsungAc::setBeep(const bool state) { + if (state) + remote_state[13] |= kSamsungAcBeepMask; + else + remote_state[13] &= ~kSamsungAcBeepMask; +} + +bool IRSamsungAc::getClean() { + return (remote_state[10] & kSamsungAcCleanMask10) && + (remote_state[11] & kSamsungAcCleanMask11); +} + +void IRSamsungAc::setClean(const bool state) { + if (state) { + remote_state[10] |= kSamsungAcCleanMask10; + remote_state[11] |= kSamsungAcCleanMask11; + } else { + remote_state[10] &= ~kSamsungAcCleanMask10; + remote_state[11] &= ~kSamsungAcCleanMask11; + } +} + +// Very unsure this is correct. +bool IRSamsungAc::getQuiet() { + return remote_state[11] & kSamsungAcQuietMask11; +} + +// Very unsure this is correct. +void IRSamsungAc::setQuiet(const bool state) { + if (state) { + remote_state[11] |= kSamsungAcQuietMask11; + setFan(kSamsungAcFanAuto); // Quiet mode seems to set fan speed to auto. + } else { + remote_state[11] &= ~kSamsungAcQuietMask11; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRSamsungAc::toString() { + String result = ""; +#else +std::string IRSamsungAc::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kSamsungAcAuto: + result += " (AUTO)"; + break; + case kSamsungAcCool: + result += " (COOL)"; + break; + case kSamsungAcHeat: + result += " (HEAT)"; + break; + case kSamsungAcDry: + result += " (DRY)"; + break; + case kSamsungAcFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kSamsungAcFanAuto: + case kSamsungAcFanAuto2: + result += " (AUTO)"; + break; + case kSamsungAcFanLow: + result += " (LOW)"; + break; + case kSamsungAcFanMed: + result += " (MED)"; + break; + case kSamsungAcFanHigh: + result += " (HIGH)"; + break; + case kSamsungAcFanTurbo: + result += " (TURBO)"; + break; + default: + result += " (UNKNOWN)"; + break; + } + result += ", Swing: "; + if (getSwing()) + result += "On"; + else + result += "Off"; + result += ", Beep: "; + if (getBeep()) + result += "On"; + else + result += "Off"; + result += ", Clean: "; + if (getBeep()) + result += "On"; + else + result += "Off"; + result += ", Quiet: "; + if (getQuiet()) + result += "On"; + else + result += "Off"; + return result; +} + +#if DECODE_SAMSUNG_AC +// Decode the supplied Samsung A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kSamsungAcBits +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to mostly work. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/505 +bool IRrecv::decodeSamsungAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kHeader * 3 + kFooter * 2 - 1) + return false; // Can't possibly be a valid Samsung A/C message. + if (nbits != kSamsungAcBits && nbits != kSamsungAcExtendedBits) return false; + + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + match_result_t data_result; + + // Message Header + if (!matchMark(results->rawbuf[offset++], kSamsungAcBitMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kSamsungAcHdrSpace)) return false; + // Section(s) + for (uint16_t pos = kSamsungACSectionLength, i = 0; pos <= nbits / 8; + pos += kSamsungACSectionLength) { + uint64_t sectiondata = 0; + // Section Header + if (!matchMark(results->rawbuf[offset++], kSamsungAcSectionMark)) + return false; + if (!matchSpace(results->rawbuf[offset++], kSamsungAcSectionSpace)) + return false; + // Section Data + // Keep reading bytes until we either run out of section or state to fill. + for (; offset <= results->rawlen - 16 && i < pos; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData(&(results->rawbuf[offset]), 8, kSamsungAcBitMark, + kSamsungAcOneSpace, kSamsungAcBitMark, + kSamsungAcZeroSpace, kTolerance, 0, false); + if (data_result.success == false) { + DPRINT("DEBUG: offset = "); + DPRINTLN(offset + data_result.used); + return false; // Fail + } + results->state[i] = data_result.data; + sectiondata = (sectiondata << 8) + data_result.data; + } + DPRINTLN("DEBUG: sectiondata = 0x" + uint64ToString(sectiondata, 16)); + // Section Footer + if (!matchMark(results->rawbuf[offset++], kSamsungAcBitMark)) return false; + if (pos < nbits / 8) { // Inter-section gap. + if (!matchSpace(results->rawbuf[offset++], kSamsungAcSectionGap)) + return false; + } else { // Last section / End of message gap. + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kSamsungAcSectionGap)) + return false; + } + } + // Compliance + // Re-check we got the correct size/length due to the way we read the data. + if (dataBitsSoFar != nbits) return false; + // Is the signature correct? + DPRINTLN("DEBUG: Checking signature."); + if (results->state[0] != 0x02 || results->state[2] != 0x0F) return false; + if (results->state[1] != 0x92 && results->state[1] != 0xB2) return false; + if (strict) { + // Is the checksum valid? + if (!IRSamsungAc::validChecksum(results->state, nbits / 8)) { + DPRINTLN("DEBUG: Checksum failed!"); + return false; + } + } + // Success + results->decode_type = SAMSUNG_AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_SAMSUNG_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h new file mode 100644 index 000000000..f80b47d20 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h @@ -0,0 +1,107 @@ +// Samsung A/C +// +// Copyright 2018 David Conran + +#ifndef IR_SAMSUNG_H_ +#define IR_SAMSUNG_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// SSSS AAA MMM SSSS U U N N GGGG +// S A A M M M S U U NN N G +// SSS AAAAA M M M SSS U U N N N G GG +// S A A M M S U U N NN G G +// SSSS A A M M SSSS UUU N N GGG + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/505 + +// Constants +const uint8_t kSamsungAcAuto = 0; +const uint8_t kSamsungAcCool = 1; +const uint8_t kSamsungAcDry = 2; +const uint8_t kSamsungAcFan = 3; +const uint8_t kSamsungAcHeat = 4; +const uint8_t kSamsungAcModeMask = 0x70; +const uint8_t kSamsungAcFanAuto = 0; +const uint8_t kSamsungAcFanLow = 2; +const uint8_t kSamsungAcFanMed = 4; +const uint8_t kSamsungAcFanHigh = 5; +const uint8_t kSamsungAcFanAuto2 = 6; +const uint8_t kSamsungAcFanTurbo = 7; +const uint8_t kSamsungAcMinTemp = 16; // 16C +const uint8_t kSamsungAcMaxTemp = 30; // 30C +const uint8_t kSamsungAcAutoTemp = 25; // 25C +const uint8_t kSamsungAcTempMask = 0xF0; +const uint8_t kSamsungAcPowerMask1 = 0x20; +const uint8_t kSamsungAcPowerMask2 = 0x30; +const uint8_t kSamsungAcFanMask = 0x0E; +const uint8_t kSamsungAcSwingMask = 0x70; +const uint8_t kSamsungAcSwingMove = 0b010; +const uint8_t kSamsungAcSwingStop = 0b111; +const uint8_t kSamsungAcBeepMask = 0x02; +const uint8_t kSamsungAcCleanMask10 = 0x80; +const uint8_t kSamsungAcCleanMask11 = 0x02; +const uint8_t kSamsungAcQuietMask11 = 0x01; + +const uint16_t kSamsungACSectionLength = 7; +const uint64_t kSamsungAcPowerSection = 0x1D20F00000000; + +// Classes +class IRSamsungAc { + public: + explicit IRSamsungAc(uint16_t pin); + + void stateReset(); +#if SEND_SAMSUNG_AC + void send(const bool calcchecksum = true); + void sendExtended(const bool calcchecksum = true); +#endif // SEND_SAMSUNG_AC + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t speed); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setSwing(const bool state); + bool getSwing(); + void setBeep(const bool state); + bool getBeep(); + void setClean(const bool state); + bool getClean(); + void setQuiet(const bool state); + bool getQuiet(); + uint8_t* getRaw(); + void setRaw(const uint8_t new_code[], + const uint16_t length = kSamsungAcStateLength); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kSamsungAcStateLength); + static uint8_t calcChecksum(const uint8_t state[], + const uint16_t length = kSamsungAcStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + // The state of the IR remote in IR code form. + uint8_t remote_state[kSamsungAcExtendedStateLength]; + void checksum(const uint16_t length = kSamsungAcStateLength); + IRsend _irsend; +}; + +#endif // IR_SAMSUNG_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sanyo.cpp similarity index 70% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Sanyo.cpp index cbb13a329..b2b4d7830 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sanyo.cpp @@ -5,7 +5,6 @@ #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" // SSSS AAA N N Y Y OOO // S A A NN N Y Y O O @@ -21,31 +20,35 @@ // Sanyo SA 8650B // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Sanyo.cpp -#define SANYO_SA8650B_HDR_MARK 3500U // seen range 3500 -#define SANYO_SA8650B_HDR_SPACE 950U // seen 950 -#define SANYO_SA8650B_ONE_MARK 2400U // seen 2400 -#define SANYO_SA8650B_ZERO_MARK 700U // seen 700 + +const uint16_t kSanyoSa8650bHdrMark = 3500; // seen range 3500 +const uint16_t kSanyoSa8650bHdrSpace = 950; // seen 950 +const uint16_t kSanyoSa8650bOneMark = 2400; // seen 2400 +const uint16_t kSanyoSa8650bZeroMark = 700; // seen 700 // usually see 713 - not using ticks as get number wrapround -#define SANYO_SA8650B_DOUBLE_SPACE_USECS 800U -#define SANYO_SA8650B_RPT_LENGTH 45000U +const uint16_t kSanyoSa8650bDoubleSpaceUsecs = 800; +const uint16_t kSanyoSa8650bRptLength = 45000; // Sanyo LC7461 // Ref: // https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Sanyo.cpp // http://slydiman.narod.ru/scr/kb/sanyo.htm // http://pdf.datasheetcatalog.com/datasheet/sanyo/LC7461.pdf -#define SANYO_LC7461_ADDRESS_MASK ((1 << SANYO_LC7461_ADDRESS_BITS) - 1) -#define SANYO_LC7461_COMMAND_MASK ((1 << SANYO_LC7461_COMMAND_BITS) - 1) -#define SANYO_LC7461_HDR_MARK 9000U -#define SANYO_LC7461_HDR_SPACE 4500U -#define SANYO_LC7461_BIT_MARK 560U // 1T -#define SANYO_LC7461_ONE_SPACE 1690U // 3T -#define SANYO_LC7461_ZERO_SPACE 560U // 1T -#define SANYO_LC7461_MIN_COMMAND_LENGTH 108000UL -#define SANYO_LC7461_MIN_GAP SANYO_LC7461_MIN_COMMAND_LENGTH - \ - (SANYO_LC7461_HDR_MARK + SANYO_LC7461_HDR_SPACE + SANYO_LC7461_BITS * \ - (SANYO_LC7461_BIT_MARK + (SANYO_LC7461_ONE_SPACE + \ - SANYO_LC7461_ZERO_SPACE) / 2) \ - + SANYO_LC7461_BIT_MARK) + +const uint16_t kSanyoLc7461AddressMask = (1 << kSanyoLC7461AddressBits) - 1; +const uint16_t kSanyoLc7461CommandMask = (1 << kSanyoLC7461CommandBits) - 1; +const uint16_t kSanyoLc7461HdrMark = 9000; +const uint16_t kSanyoLc7461HdrSpace = 4500; +const uint16_t kSanyoLc7461BitMark = 560; // 1T +const uint16_t kSanyoLc7461OneSpace = 1690; // 3T +const uint16_t kSanyoLc7461ZeroSpace = 560; // 1T +const uint32_t kSanyoLc7461MinCommandLength = 108000; + +const uint16_t kSanyoLc7461MinGap = + kSanyoLc7461MinCommandLength - + (kSanyoLc7461HdrMark + kSanyoLc7461HdrSpace + + kSanyoLC7461Bits * (kSanyoLc7461BitMark + + (kSanyoLc7461OneSpace + kSanyoLc7461ZeroSpace) / 2) + + kSanyoLc7461BitMark); #if SEND_SANYO // Construct a Sanyo LC7461 message. @@ -62,18 +65,18 @@ // According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon uint64_t IRsend::encodeSanyoLC7461(uint16_t address, uint8_t command) { // Mask our input values to ensure the correct bit sizes. - address &= SANYO_LC7461_ADDRESS_MASK; - command &= SANYO_LC7461_COMMAND_MASK; + address &= kSanyoLc7461AddressMask; + command &= kSanyoLc7461CommandMask; uint64_t data = address; - address ^= SANYO_LC7461_ADDRESS_MASK; // Invert the 13 LSBs. + address ^= kSanyoLc7461AddressMask; // Invert the 13 LSBs. // Append the now inverted address. - data = (data << SANYO_LC7461_ADDRESS_BITS) | address; + data = (data << kSanyoLC7461AddressBits) | address; // Append the command. - data = (data << SANYO_LC7461_COMMAND_BITS) | command; - command ^= SANYO_LC7461_COMMAND_MASK; // Invert the command. + data = (data << kSanyoLC7461CommandBits) | command; + command ^= kSanyoLc7461CommandMask; // Invert the command. // Append the now inverted command. - data = (data << SANYO_LC7461_COMMAND_BITS) | command; + data = (data << kSanyoLC7461CommandBits) | command; return data; } @@ -128,31 +131,30 @@ void IRsend::sendSanyoLC7461(uint64_t data, uint16_t nbits, uint16_t repeat) { // http://pdf.datasheetcatalog.com/datasheet/sanyo/LC7461.pdf bool IRrecv::decodeSanyoLC7461(decode_results *results, uint16_t nbits, bool strict) { - if (strict && nbits != SANYO_LC7461_BITS) + if (strict && nbits != kSanyoLC7461Bits) return false; // Not strictly in spec. // This protocol is basically a 42-bit variant of the NEC protocol. if (!decodeNEC(results, nbits, false)) return false; // Didn't match a NEC format (without strict) // Bits 30 to 42+. - uint16_t address = results->value >> (SANYO_LC7461_BITS - - SANYO_LC7461_ADDRESS_BITS); + uint16_t address = + results->value >> (kSanyoLC7461Bits - kSanyoLC7461AddressBits); // Bits 9 to 16. - uint8_t command = (results->value >> SANYO_LC7461_COMMAND_BITS) & - SANYO_LC7461_COMMAND_MASK; + uint8_t command = + (results->value >> kSanyoLC7461CommandBits) & kSanyoLc7461CommandMask; // Compliance if (strict) { - if (results->bits != nbits) - return false; + if (results->bits != nbits) return false; // Bits 17 to 29. uint16_t inverted_address = - (results->value >> (SANYO_LC7461_COMMAND_BITS * 2)) & - SANYO_LC7461_ADDRESS_MASK; + (results->value >> (kSanyoLC7461CommandBits * 2)) & + kSanyoLc7461AddressMask; // Bits 1-8. - uint8_t inverted_command = results->value & SANYO_LC7461_COMMAND_MASK; - if ((address ^ SANYO_LC7461_ADDRESS_MASK) != inverted_address) + uint8_t inverted_command = results->value & kSanyoLc7461CommandMask; + if ((address ^ kSanyoLc7461AddressMask) != inverted_address) return false; // Address integrity check failed. - if ((command ^ SANYO_LC7461_COMMAND_MASK) != inverted_command) + if ((command ^ kSanyoLc7461CommandMask) != inverted_command) return false; // Command integrity check failed. } @@ -183,9 +185,9 @@ bool IRrecv::decodeSanyoLC7461(decode_results *results, uint16_t nbits, // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Sanyo.cpp bool IRrecv::decodeSanyo(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER - 1) + if (results->rawlen < 2 * nbits + kHeader - 1) return false; // Shorter than shortest possible. - if (strict && nbits != SANYO_SA8650B_BITS) + if (strict && nbits != kSanyoSA8650BBits) return false; // Doesn't match the spec. uint16_t offset = 0; @@ -193,9 +195,9 @@ bool IRrecv::decodeSanyo(decode_results *results, uint16_t nbits, bool strict) { // TODO(crankyoldgit): This repeat code looks like garbage, it should never // match or if it does, it won't be reliable. We should probably just // remove it. - if (results->rawbuf[offset++] < SANYO_SA8650B_DOUBLE_SPACE_USECS) { + if (results->rawbuf[offset++] < kSanyoSa8650bDoubleSpaceUsecs) { results->bits = 0; - results->value = REPEAT; + results->value = kRepeat; results->decode_type = SANYO; results->address = 0; results->command = 0; @@ -204,27 +206,27 @@ bool IRrecv::decodeSanyo(decode_results *results, uint16_t nbits, bool strict) { } // Header - if (!matchMark(results->rawbuf[offset++], SANYO_SA8650B_HDR_MARK)) + if (!matchMark(results->rawbuf[offset++], kSanyoSa8650bHdrMark)) return false; // NOTE: These next two lines look very wrong. Treat as suspect. - if (!matchMark(results->rawbuf[offset++], SANYO_SA8650B_HDR_MARK)) + if (!matchMark(results->rawbuf[offset++], kSanyoSa8650bHdrMark)) return false; // Data uint64_t data = 0; while (offset + 1 < results->rawlen) { - if (!matchSpace(results->rawbuf[offset], SANYO_SA8650B_HDR_SPACE)) + if (!matchSpace(results->rawbuf[offset], kSanyoSa8650bHdrSpace)) break; offset++; - if (matchMark(results->rawbuf[offset], SANYO_SA8650B_ONE_MARK)) + if (matchMark(results->rawbuf[offset], kSanyoSa8650bOneMark)) data = (data << 1) | 1; // 1 - else if (matchMark(results->rawbuf[offset], SANYO_SA8650B_ZERO_MARK)) + else if (matchMark(results->rawbuf[offset], kSanyoSa8650bZeroMark)) data <<= 1; // 0 else return false; offset++; } - if (strict && SANYO_SA8650B_BITS > (offset - 1U) / 2U) + if (strict && kSanyoSA8650BBits > (offset - 1U) / 2U) return false; // Success diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sharp.cpp similarity index 68% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Sharp.cpp index 1a0bb3556..ae1b59c74 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sharp.cpp @@ -4,7 +4,6 @@ #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // SSSS H H AAA RRRR PPPP @@ -13,32 +12,37 @@ // S H H A A R R P // SSSS H H A A R R P +// Equipment it seems compatible with: +// * Sharp LC-52D62U +// * +// + // Constants // period time = 1/38000Hz = 26.316 microseconds. // Ref: // GlobalCache's IR Control Tower data. // http://www.sbprojects.com/knowledge/ir/sharp.php -#define SHARP_TICK 26U -#define SHARP_BIT_MARK_TICKS 10U -#define SHARP_BIT_MARK (SHARP_BIT_MARK_TICKS * SHARP_TICK) -#define SHARP_ONE_SPACE_TICKS 70U -#define SHARP_ONE_SPACE (SHARP_ONE_SPACE_TICKS * SHARP_TICK) -#define SHARP_ZERO_SPACE_TICKS 30U -#define SHARP_ZERO_SPACE (SHARP_ZERO_SPACE_TICKS * SHARP_TICK) -#define SHARP_GAP_TICKS 1677U -#define SHARP_GAP (SHARP_GAP_TICKS * SHARP_TICK) - +const uint16_t kSharpTick = 26; +const uint16_t kSharpBitMarkTicks = 10; +const uint16_t kSharpBitMark = kSharpBitMarkTicks * kSharpTick; +const uint16_t kSharpOneSpaceTicks = 70; +const uint16_t kSharpOneSpace = kSharpOneSpaceTicks * kSharpTick; +const uint16_t kSharpZeroSpaceTicks = 30; +const uint16_t kSharpZeroSpace = kSharpZeroSpaceTicks * kSharpTick; +const uint16_t kSharpGapTicks = 1677; +const uint16_t kSharpGap = kSharpGapTicks * kSharpTick; // Address(5) + Command(8) + Expansion(1) + Check(1) -#define SHARP_TOGGLE_MASK ((1 << (SHARP_BITS - SHARP_ADDRESS_BITS)) - 1) -#define SHARP_ADDRESS_MASK ((1 << SHARP_ADDRESS_BITS) - 1) -#define SHARP_COMMAND_MASK ((1 << SHARP_COMMAND_BITS) - 1) +const uint64_t kSharpToggleMask = + ((uint64_t)1 << (kSharpBits - kSharpAddressBits)) - 1; +const uint64_t kSharpAddressMask = ((uint64_t)1 << kSharpAddressBits) - 1; +const uint64_t kSharpCommandMask = ((uint64_t)1 << kSharpCommandBits) - 1; #if (SEND_SHARP || SEND_DENON) // Send a (raw) Sharp message // // Args: // data: Contents of the message to be sent. -// nbits: Nr. of bits of data to be sent. Typically SHARP_BITS. +// nbits: Nr. of bits of data to be sent. Typically kSharpBits. // repeat: Nr. of additional times the message is to be sent. // // Status: BETA / Previously working fine. @@ -56,28 +60,20 @@ // http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf // http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp void IRsend::sendSharpRaw(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 38kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(38, 33); - for (uint16_t i = 0; i <= repeat; i++) { // Protocol demands that the data be sent twice; once normally, // then with all but the address bits inverted. // Note: Previously this used to be performed 3 times (normal, inverted, // normal), however all data points to that being incorrect. for (uint8_t n = 0; n < 2; n++) { - // No Header - - // Data - sendData(SHARP_BIT_MARK, SHARP_ONE_SPACE, - SHARP_BIT_MARK, SHARP_ZERO_SPACE, - data, nbits, true); - // Footer - mark(SHARP_BIT_MARK); - space(SHARP_GAP); - + sendGeneric(0, 0, // No Header + kSharpBitMark, kSharpOneSpace, kSharpBitMark, kSharpZeroSpace, + kSharpBitMark, kSharpGap, data, nbits, 38, true, + 0, // Repeats are handled already. + 33); // Invert the data per protocol. This is always called twice, so it's // retured to original upon exiting the inner loop. - data ^= SHARP_TOGGLE_MASK; + data ^= kSharpToggleMask; } } } @@ -110,17 +106,17 @@ uint32_t IRsend::encodeSharp(uint16_t address, uint16_t command, uint16_t expansion, uint16_t check, bool MSBfirst) { // Mask any unexpected bits. - address &= ((1 << SHARP_ADDRESS_BITS) - 1); - command &= ((1 << SHARP_COMMAND_BITS) - 1); + address &= ((1 << kSharpAddressBits) - 1); + command &= ((1 << kSharpCommandBits) - 1); expansion &= 1; check &= 1; if (!MSBfirst) { // Correct bit order if needed. - address = reverseBits(address, SHARP_ADDRESS_BITS); - command = reverseBits(command, SHARP_COMMAND_BITS); + address = reverseBits(address, kSharpAddressBits); + command = reverseBits(command, kSharpCommandBits); } // Concatinate all the bits. - return (address << (SHARP_COMMAND_BITS + 2)) | (command << 2) | + return (address << (kSharpCommandBits + 2)) | (command << 2) | (expansion << 1) | check; } @@ -129,7 +125,7 @@ uint32_t IRsend::encodeSharp(uint16_t address, uint16_t command, // Args: // address: Address value to be sent. // command: Command value to be sent. -// nbits: Nr. of bits of data to be sent. Typically SHARP_BITS. +// nbits: Nr. of bits of data to be sent. Typically kSharpBits. // repeat: Nr. of additional times the message is to be sent. // // Status: DEPRICATED / Previously working fine. @@ -159,13 +155,13 @@ void IRsend::sendSharp(uint16_t address, uint16_t command, uint16_t nbits, // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. Typically SHARP_BITS. +// nbits: Nr. of data bits to expect. Typically kSharpBits. // strict: Flag indicating if we should perform strict matching. // expansion: Should we expect the expansion bit to be set. Default is true. // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: BETA / Should work okay. +// Status: STABLE / Working fine. // // Note: // This procedure returns a value suitable for use in sendSharpRaw(). @@ -178,90 +174,83 @@ void IRsend::sendSharp(uint16_t address, uint16_t command, uint16_t nbits, // http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp bool IRrecv::decodeSharp(decode_results *results, uint16_t nbits, bool strict, bool expansion) { - if (results->rawlen < 2 * nbits + FOOTER - 1) + if (results->rawlen < 2 * nbits + kFooter - 1) return false; // Not enough entries to be a Sharp message. // Compliance if (strict) { - if (nbits != SHARP_BITS) - return false; // Request is out of spec. + if (nbits != kSharpBits) return false; // Request is out of spec. // DISABLED - See TODO #ifdef UNIT_TEST // An in spec message has the data sent normally, then inverted. So we // expect twice as many entries than to just get the results. - if (results->rawlen < 2 * (2 * nbits + FOOTER)) - return false; + if (results->rawlen < 2 * (2 * nbits + kFooter)) return false; #endif } uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // No header // But try to auto-calibrate off the initial mark signal. - if (!matchMark(results->rawbuf[offset], SHARP_BIT_MARK, 35)) return false; + if (!matchMark(results->rawbuf[offset], kSharpBitMark, 35)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t tick = results->rawbuf[offset] * RAWTICK / SHARP_BIT_MARK_TICKS; + uint32_t tick = results->rawbuf[offset] * kRawTick / kSharpBitMarkTicks; // Data for (uint16_t i = 0; i < nbits; i++, offset++) { - // Use a higher tolerance value for SHARP_BIT_MARK as it is quite small. - if (!matchMark(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick, 35)) + // Use a higher tolerance value for kSharpBitMark as it is quite small. + if (!matchMark(results->rawbuf[offset++], kSharpBitMarkTicks * tick, 35)) return false; - if (matchSpace(results->rawbuf[offset], SHARP_ONE_SPACE_TICKS * tick)) + if (matchSpace(results->rawbuf[offset], kSharpOneSpaceTicks * tick)) data = (data << 1) | 1; // 1 - else if (matchSpace(results->rawbuf[offset], SHARP_ZERO_SPACE_TICKS * tick)) + else if (matchSpace(results->rawbuf[offset], kSharpZeroSpaceTicks * tick)) data <<= 1; // 0 else return false; } // Footer - if (!match(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick)) + if (!match(results->rawbuf[offset++], kSharpBitMarkTicks * tick)) return false; if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], SHARP_GAP_TICKS * tick)) + !matchAtLeast(results->rawbuf[offset], kSharpGapTicks * tick)) return false; // Compliance if (strict) { // Check the state of the expansion bit is what we expect. - if ((data & 0b10) >> 1 != expansion) - return false; + if ((data & 0b10) >> 1 != expansion) return false; // The check bit should be cleared in a normal message. - if (data & 0b1) - return false; - // DISABLED - See TODO + if (data & 0b1) return false; + // DISABLED - See TODO #ifdef UNIT_TEST // Grab the second copy of the data (i.e. inverted) // Header // i.e. The inter-data/command repeat gap. - if (!matchSpace(results->rawbuf[offset++], SHARP_GAP_TICKS * tick)) + if (!matchSpace(results->rawbuf[offset++], kSharpGapTicks * tick)) return false; // Data uint64_t second_data = 0; for (uint16_t i = 0; i < nbits; i++, offset++) { - // Use a higher tolerance value for SHARP_BIT_MARK as it is quite small. - if (!matchMark(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick, - 35)) + // Use a higher tolerance value for kSharpBitMark as it is quite small. + if (!matchMark(results->rawbuf[offset++], kSharpBitMarkTicks * tick, 35)) return false; - if (matchSpace(results->rawbuf[offset], SHARP_ONE_SPACE_TICKS * tick)) + if (matchSpace(results->rawbuf[offset], kSharpOneSpaceTicks * tick)) second_data = (second_data << 1) | 1; // 1 - else if (matchSpace(results->rawbuf[offset], - SHARP_ZERO_SPACE_TICKS * tick)) + else if (matchSpace(results->rawbuf[offset], kSharpZeroSpaceTicks * tick)) second_data <<= 1; // 0 else return false; } // Footer - if (!match(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick)) + if (!match(results->rawbuf[offset++], kSharpBitMarkTicks * tick)) return false; if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], SHARP_GAP_TICKS * tick)) + !matchAtLeast(results->rawbuf[offset], kSharpGapTicks * tick)) return false; // Check that second_data has been inverted correctly. - if (data != (second_data ^ SHARP_TOGGLE_MASK)) - return false; + if (data != (second_data ^ kSharpToggleMask)) return false; #endif // UNIT_TEST } @@ -270,9 +259,9 @@ bool IRrecv::decodeSharp(decode_results *results, uint16_t nbits, bool strict, results->bits = nbits; results->value = data; // Address & command are actually transmitted in LSB first order. - results->address = reverseBits(data, nbits) & SHARP_ADDRESS_MASK; - results->command = reverseBits((data >> 2) & SHARP_COMMAND_MASK, - SHARP_COMMAND_BITS); + results->address = reverseBits(data, nbits) & kSharpAddressMask; + results->command = + reverseBits((data >> 2) & kSharpCommandMask, kSharpCommandBits); return true; } #endif // (DECODE_SHARP || DECODE_DENON) diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sherwood.cpp similarity index 71% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Sherwood.cpp index 97e75067a..8af7dfb34 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sherwood.cpp @@ -14,16 +14,15 @@ // // Args: // data: The contents of the command you want to send. -// nbits: The bit size of the command being sent. (SHERWOOD_BITS) +// nbits: The bit size of the command being sent. (kSherwoodBits) // repeat: The nr. of times you want the command to be repeated. (Default: 1) // // Status: STABLE / Known working. // // Note: // Sherwood remote codes appear to be NEC codes with a manditory repeat code. -// i.e. repeat should be >= SHERWOOD_MIN_REPEAT (1). -void IRsend::sendSherwood(uint64_t data, uint16_t nbits, - uint16_t repeat) { - sendNEC(data, nbits, std::max((uint16_t) SHERWOOD_MIN_REPEAT, repeat)); +// i.e. repeat should be >= kSherwoodMinRepeat (1). +void IRsend::sendSherwood(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendNEC(data, nbits, std::max((uint16_t)kSherwoodMinRepeat, repeat)); } #endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sony.cpp similarity index 62% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Sony.cpp index fd2652d1d..efa6e6a46 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sony.cpp @@ -5,7 +5,6 @@ #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // SSSS OOO N N Y Y @@ -20,19 +19,19 @@ // Constants // Ref: // http://www.sbprojects.com/knowledge/ir/sirc.php -#define SONY_TICK 200U -#define SONY_HDR_MARK_TICKS 12U -#define SONY_HDR_MARK (SONY_HDR_MARK_TICKS * SONY_TICK) -#define SONY_SPACE_TICKS 3U -#define SONY_SPACE (SONY_SPACE_TICKS * SONY_TICK) -#define SONY_ONE_MARK_TICKS 6U -#define SONY_ONE_MARK (SONY_ONE_MARK_TICKS * SONY_TICK) -#define SONY_ZERO_MARK_TICKS 3U -#define SONY_ZERO_MARK (SONY_ZERO_MARK_TICKS * SONY_TICK) -#define SONY_RPT_LENGTH_TICKS 225U -#define SONY_RPT_LENGTH (SONY_RPT_LENGTH_TICKS * SONY_TICK) -#define SONY_MIN_GAP_TICKS 50U -#define SONY_MIN_GAP (SONY_MIN_GAP_TICKS * SONY_TICK) +const uint16_t kSonyTick = 200; +const uint16_t kSonyHdrMarkTicks = 12; +const uint16_t kSonyHdrMark = kSonyHdrMarkTicks * kSonyTick; +const uint16_t kSonySpaceTicks = 3; +const uint16_t kSonySpace = kSonySpaceTicks * kSonyTick; +const uint16_t kSonyOneMarkTicks = 6; +const uint16_t kSonyOneMark = kSonyOneMarkTicks * kSonyTick; +const uint16_t kSonyZeroMarkTicks = 3; +const uint16_t kSonyZeroMark = kSonyZeroMarkTicks * kSonyTick; +const uint16_t kSonyRptLengthTicks = 225; +const uint16_t kSonyRptLength = kSonyRptLengthTicks * kSonyTick; +const uint16_t kSonyMinGapTicks = 50; +const uint16_t kSonyMinGap = kSonyMinGapTicks * kSonyTick; #if SEND_SONY // Send a Sony/SIRC(Serial Infra-Red Control) message. @@ -51,24 +50,10 @@ // Ref: // http://www.sbprojects.com/knowledge/ir/sirc.php void IRsend::sendSony(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Sony devices use a 40kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(40, 33); - IRtimer usecs = IRtimer(); - - for (uint16_t i = 0; i <= repeat; i++) { // Typically loop 3 or more times. - usecs.reset(); - // Header - mark(SONY_HDR_MARK); - space(SONY_SPACE); - // Data - sendData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, - data, nbits, true); - // Footer - // The Sony protocol requires us to wait 45ms from start of a code to the - // start of the next one. A 10ms minimum gap is also required. - space(std::max(SONY_MIN_GAP, SONY_RPT_LENGTH - usecs.elapsed())); - } - // A space() is always performed last, so no need to turn off the LED. + sendGeneric(kSonyHdrMark, kSonySpace, kSonyOneMark, kSonySpace, kSonyZeroMark, + kSonySpace, + 0, // No Footer mark. + kSonyMinGap, kSonyRptLength, data, nbits, 40, true, repeat, 33); } // Convert Sony/SIRC command, address, & extended bits into sendSony format. @@ -81,8 +66,8 @@ void IRsend::sendSony(uint64_t data, uint16_t nbits, uint16_t repeat) { // A sendSony compatible data message. // // Status: BETA / Should be working. -uint32_t IRsend::encodeSony(uint16_t nbits, uint16_t command, - uint16_t address, uint16_t extended) { +uint32_t IRsend::encodeSony(uint16_t nbits, uint16_t command, uint16_t address, + uint16_t extended) { uint32_t result = 0; switch (nbits) { case 12: // 5 address bits. @@ -120,7 +105,7 @@ uint32_t IRsend::encodeSony(uint16_t nbits, uint16_t command, // Ref: // http://www.sbprojects.com/knowledge/ir/sirc.php bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER - 1) + if (results->rawlen < 2 * nbits + kHeader - 1) return false; // Message is smaller than we expected. // Compliance @@ -136,31 +121,30 @@ bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) { } uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; uint16_t actualBits; uint32_t timeSoFar = 0; // Time in uSecs of the message length. // Header - timeSoFar += results->rawbuf[offset] * RAWTICK; - if (!matchMark(results->rawbuf[offset], SONY_HDR_MARK)) - return false; + timeSoFar += results->rawbuf[offset] * kRawTick; + if (!matchMark(results->rawbuf[offset], kSonyHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t tick = results->rawbuf[offset++] * RAWTICK / SONY_HDR_MARK_TICKS; + uint32_t tick = results->rawbuf[offset++] * kRawTick / kSonyHdrMarkTicks; // Data for (actualBits = 0; offset < results->rawlen - 1; actualBits++, offset++) { - // The gap after a Sony packet for a repeat should be SONY_MIN_GAP or - // (SONY_RPT_LENGTH - timeSoFar) according to the spec. - if (matchSpace(results->rawbuf[offset], SONY_MIN_GAP_TICKS * tick) || - matchAtLeast(results->rawbuf[offset], SONY_RPT_LENGTH - timeSoFar)) + // The gap after a Sony packet for a repeat should be kSonyMinGap or + // (kSonyRptLength - timeSoFar) according to the spec. + if (matchSpace(results->rawbuf[offset], kSonyMinGapTicks * tick) || + matchAtLeast(results->rawbuf[offset], kSonyRptLength - timeSoFar)) break; // Found a repeat space. - timeSoFar += results->rawbuf[offset] * RAWTICK; - if (!matchSpace(results->rawbuf[offset++], SONY_SPACE_TICKS * tick)) + timeSoFar += results->rawbuf[offset] * kRawTick; + if (!matchSpace(results->rawbuf[offset++], kSonySpaceTicks * tick)) return false; - timeSoFar += results->rawbuf[offset] * RAWTICK; - if (matchMark(results->rawbuf[offset], SONY_ONE_MARK_TICKS * tick)) + timeSoFar += results->rawbuf[offset] * kRawTick; + if (matchMark(results->rawbuf[offset], kSonyOneMarkTicks * tick)) data = (data << 1) | 1; - else if (matchMark(results->rawbuf[offset], SONY_ZERO_MARK_TICKS * tick)) + else if (matchMark(results->rawbuf[offset], kSonyZeroMarkTicks * tick)) data <<= 1; else return false; @@ -179,14 +163,14 @@ bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) { data = reverseBits(data, actualBits); // Decode the address & command from raw decode value. switch (actualBits) { - case 12: // 7 command bits, 5 address bits. - case 15: // 7 command bits, 8 address bits. + case 12: // 7 command bits, 5 address bits. + case 15: // 7 command bits, 8 address bits. results->command = data & 0x7F; // Bits 0-6 - results->address = data >> 7; // Bits 7-14 + results->address = data >> 7; // Bits 7-14 break; case 20: // 7 command bits, 5 address bits, 8 extended (command) bits. results->command = (data & 0x7F) + ((data >> 12) << 7); // Bits 0-6,12-19 - results->address = (data >> 7) & 0x1F; // Bits 7-11 + results->address = (data >> 7) & 0x1F; // Bits 7-11 break; default: // Shouldn't happen, but just in case. results->address = 0; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp new file mode 100644 index 000000000..817b5fbaa --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp @@ -0,0 +1,340 @@ +// Copyright 2017 David Conran + +#include "ir_Toshiba.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// TTTTTTT OOOOO SSSSS HH HH IIIII BBBBB AAA +// TTT OO OO SS HH HH III BB B AAAAA +// TTT OO OO SSSSS HHHHHHH III BBBBBB AA AA +// TTT OO OO SS HH HH III BB BB AAAAAAA +// TTT OOOO0 SSSSS HH HH IIIII BBBBBB AA AA + +// Toshiba A/C support added by David Conran +// +// Equipment it seems compatible with: +// * Toshiba RAS-B13N3KV2 / Akita EVO II +// * Toshiba RAS-B13N3KVP-E, RAS 18SKP-ES +// * Toshiba WH-TA04NE, WC-L03SE +// * + +// Constants + +// Toshiba A/C +// Ref: +// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266T.ino#L77 +const uint16_t kToshibaAcHdrMark = 4400; +const uint16_t kToshibaAcHdrSpace = 4300; +const uint16_t kToshibaAcBitMark = 543; +const uint16_t kToshibaAcOneSpace = 1623; +const uint16_t kToshibaAcZeroSpace = 472; +const uint16_t kToshibaAcMinGap = 7048; + +#if SEND_TOSHIBA_AC +// Send a Toshiba A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kToshibaACStateLength) +// repeat: Nr. of times the message is to be repeated. +// (Default = kToshibaACMinRepeat). +// +// Status: StABLE / Working. +// +void IRsend::sendToshibaAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kToshibaACStateLength) + return; // Not enough bytes to send a proper message. + sendGeneric(kToshibaAcHdrMark, kToshibaAcHdrSpace, kToshibaAcBitMark, + kToshibaAcOneSpace, kToshibaAcBitMark, kToshibaAcZeroSpace, + kToshibaAcBitMark, kToshibaAcMinGap, data, nbytes, 38, true, + repeat, 50); +} +#endif // SEND_TOSHIBA_AC + +// Code to emulate Toshiba A/C IR remote control unit. +// Inspired and derived from the work done at: +// https://github.com/r45635/HVAC-IR-Control +// +// Status: STABLE / Working. +// +// Initialise the object. +IRToshibaAC::IRToshibaAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRToshibaAC::stateReset() { + // The state of the IR remote in IR code form. + // Known good state obtained from: + // https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266T.ino#L103 + // Note: Can't use the following because it requires -std=c++11 + // uint8_t remote_state[kToshibaACStateLength] = { + // 0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00 }; + remote_state[0] = 0xF2; + remote_state[1] = 0x0D; + remote_state[2] = 0x03; + remote_state[3] = 0xFC; + remote_state[4] = 0x01; + for (uint8_t i = 5; i < kToshibaACStateLength; i++) remote_state[i] = 0; + mode_state = remote_state[6] & 0b00000011; + checksum(); // Calculate the checksum +} + +// Configure the pin for output. +void IRToshibaAC::begin() { _irsend.begin(); } + +#if SEND_TOSHIBA_AC +// Send the current desired state to the IR LED. +void IRToshibaAC::send() { + checksum(); // Ensure correct checksum before sending. + _irsend.sendToshibaAC(remote_state); +} +#endif // SEND_TOSHIBA_AC + +// Return a pointer to the internal state date of the remote. +uint8_t* IRToshibaAC::getRaw() { + checksum(); + return remote_state; +} + +// Override the internal state with the new state. +void IRToshibaAC::setRaw(uint8_t newState[]) { + for (uint8_t i = 0; i < kToshibaACStateLength; i++) { + remote_state[i] = newState[i]; + } + mode_state = getMode(true); +} + +// Calculate the checksum for a given array. +// Args: +// state: The array to calculate the checksum over. +// length: The size of the array. +// Returns: +// The 8 bit checksum value. +uint8_t IRToshibaAC::calcChecksum(const uint8_t state[], + const uint16_t length) { + uint8_t checksum = 0; + // Only calculate it for valid lengths. + if (length > 1) { + // Checksum is simple XOR of all bytes except the last one. + for (uint8_t i = 0; i < length - 1; i++) checksum ^= state[i]; + } + return checksum; +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRToshibaAC::validChecksum(const uint8_t state[], const uint16_t length) { + return (length > 1 && state[length - 1] == calcChecksum(state, length)); +} + +// Calculate & set the checksum for the current internal state of the remote. +void IRToshibaAC::checksum(const uint16_t length) { + // Stored the checksum value in the last byte. + if (length > 1) remote_state[length - 1] = calcChecksum(remote_state, length); +} + +// Set the requested power state of the A/C to off. +void IRToshibaAC::on() { + // state = ON; + remote_state[6] &= ~kToshibaAcPower; + setMode(mode_state); +} + +// Set the requested power state of the A/C to off. +void IRToshibaAC::off() { + // state = OFF; + remote_state[6] |= (kToshibaAcPower | 0b00000011); +} + +// Set the requested power state of the A/C. +void IRToshibaAC::setPower(bool state) { + if (state) + on(); + else + off(); +} + +// Return the requested power state of the A/C. +bool IRToshibaAC::getPower() { + return ((remote_state[6] & kToshibaAcPower) == 0); +} + +// Set the temp. in deg C +void IRToshibaAC::setTemp(uint8_t temp) { + temp = std::max((uint8_t)kToshibaAcMinTemp, temp); + temp = std::min((uint8_t)kToshibaAcMaxTemp, temp); + remote_state[5] = (temp - kToshibaAcMinTemp) << 4; +} + +// Return the set temp. in deg C +uint8_t IRToshibaAC::getTemp() { + return ((remote_state[5] >> 4) + kToshibaAcMinTemp); +} + +// Set the speed of the fan, 0-5. +// 0 is auto, 1-5 is the speed, 5 is Max. +void IRToshibaAC::setFan(uint8_t fan) { + // Bounds check + if (fan > kToshibaAcFanMax) + fan = kToshibaAcFanMax; // Set the fan to maximum if out of range. + if (fan > kToshibaAcFanAuto) fan++; + remote_state[6] &= 0b00011111; // Clear the previous fan state + remote_state[6] |= (fan << 5); +} + +// Return the requested state of the unit's fan. +uint8_t IRToshibaAC::getFan() { + uint8_t fan = remote_state[6] >> 5; + if (fan == kToshibaAcFanAuto) return kToshibaAcFanAuto; + return --fan; +} + +// Get the requested climate operation mode of the a/c unit. +// Args: +// useRaw: Indicate to get the mode from the state array. (Default: false) +// Returns: +// A uint8_t containing the A/C mode. +uint8_t IRToshibaAC::getMode(bool useRaw) { + if (useRaw) + return (remote_state[6] & 0b00000011); + else + return mode_state; +} + +// Set the requested climate operation mode of the a/c unit. +void IRToshibaAC::setMode(uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + switch (mode) { + case kToshibaAcAuto: + break; + case kToshibaAcCool: + break; + case kToshibaAcDry: + break; + case kToshibaAcHeat: + break; + default: + mode = kToshibaAcAuto; + } + mode_state = mode; + // Only adjust the remote_state if we have power set to on. + if (getPower()) { + remote_state[6] &= 0b11111100; // Clear the previous mode. + remote_state[6] |= mode_state; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRToshibaAC::toString() { + String result = ""; +#else +std::string IRToshibaAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kToshibaAcAuto: + result += " (AUTO)"; + break; + case kToshibaAcCool: + result += " (COOL)"; + break; + case kToshibaAcHeat: + result += " (HEAT)"; + break; + case kToshibaAcDry: + result += " (DRY)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kToshibaAcFanAuto: + result += " (AUTO)"; + break; + case kToshibaAcFanMax: + result += " (MAX)"; + break; + } + return result; +} + +#if DECODE_TOSHIBA_AC +// Decode a Toshiba AC IR message if possible. +// Places successful decode information in the results pointer. +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kToshibaACBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Working. +// +// Ref: +// +bool IRrecv::decodeToshibaAC(decode_results* results, uint16_t nbits, + bool strict) { + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + + // Have we got enough data to successfully decode? + if (results->rawlen < kToshibaACBits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid message. + + // Compliance + if (strict && nbits != kToshibaACBits) + return false; // Must be called with the correct nr. of bytes. + + // Header + if (!matchMark(results->rawbuf[offset++], kToshibaAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kToshibaAcHdrSpace)) return false; + + // Data + for (uint8_t i = 0; i < kToshibaACStateLength; i++) { + // Read a byte's worth of data. + match_result_t data_result = + matchData(&(results->rawbuf[offset]), 8, kToshibaAcBitMark, + kToshibaAcOneSpace, kToshibaAcBitMark, kToshibaAcZeroSpace); + if (data_result.success == false) return false; // Fail + dataBitsSoFar += 8; + results->state[i] = (uint8_t)data_result.data; + offset += data_result.used; + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kToshibaAcBitMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kToshibaAcMinGap)) return false; + + // Compliance + if (strict) { + // Check that the checksum of the message is correct. + if (!IRToshibaAC::validChecksum(results->state)) return false; + } + + // Success + results->decode_type = TOSHIBA_AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_TOSHIBA_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h new file mode 100644 index 000000000..1a1e6cdc8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h @@ -0,0 +1,85 @@ +// Copyright 2017 David Conran +#ifndef IR_TOSHIBA_H_ +#define IR_TOSHIBA_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef ARDUINO +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// TTTTTTT OOOOO SSSSS HH HH IIIII BBBBB AAA +// TTT OO OO SS HH HH III BB B AAAAA +// TTT OO OO SSSSS HHHHHHH III BBBBBB AA AA +// TTT OO OO SS HH HH III BB BB AAAAAAA +// TTT OOOO0 SSSSS HH HH IIIII BBBBBB AA AA + +// Toshiba A/C support added by David Conran + +// Constants +const uint8_t kToshibaAcAuto = 0; +const uint8_t kToshibaAcCool = 1; +const uint8_t kToshibaAcDry = 2; +const uint8_t kToshibaAcHeat = 3; +const uint8_t kToshibaAcPower = 4; +const uint8_t kToshibaAcFanAuto = 0; +const uint8_t kToshibaAcFanMax = 5; +const uint8_t kToshibaAcMinTemp = 17; // 17C +const uint8_t kToshibaAcMaxTemp = 30; // 30C + +// Legacy defines. (Deperecated) +#define TOSHIBA_AC_AUTO kToshibaAcAuto +#define TOSHIBA_AC_COOL kToshibaAcCool +#define TOSHIBA_AC_DRY kToshibaAcDry +#define TOSHIBA_AC_HEAT kToshibaAcHeat +#define TOSHIBA_AC_POWER kToshibaAcPower +#define TOSHIBA_AC_FAN_AUTO kToshibaAcFanAuto +#define TOSHIBA_AC_FAN_MAX kToshibaAcFanMax +#define TOSHIBA_AC_MIN_TEMP kToshibaAcMinTemp +#define TOSHIBA_AC_MAX_TEMP kToshibaAcMaxTemp + +class IRToshibaAC { + public: + explicit IRToshibaAC(uint16_t pin); + + void stateReset(); +#if SEND_TOSHIBA_AC + void send(); +#endif // SEND_TOSHIBA_AC + void begin(); + void on(); + void off(); + void setPower(bool state); + bool getPower(); + void setTemp(uint8_t temp); + uint8_t getTemp(); + void setFan(uint8_t fan); + uint8_t getFan(); + void setMode(uint8_t mode); + uint8_t getMode(bool useRaw = false); + void setRaw(uint8_t newState[]); + uint8_t* getRaw(); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kToshibaACStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif +#ifndef UNIT_TEST + + private: +#endif + uint8_t remote_state[kToshibaACStateLength]; + void checksum(const uint16_t length = kToshibaACStateLength); + static uint8_t calcChecksum(const uint8_t state[], + const uint16_t length = kToshibaACStateLength); + uint8_t mode_state; + IRsend _irsend; +}; + +#endif // IR_TOSHIBA_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp new file mode 100644 index 000000000..0bece2664 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp @@ -0,0 +1,127 @@ +// Copyright 2017 stufisher + +#include "ir_Trotec.h" +#include "IRremoteESP8266.h" +#include "IRutils.h" + +// Constants +const uint16_t kTrotecHdrMark = 5952; +const uint16_t kTrotecHdrSpace = 7364; +const uint16_t kTrotecOneMark = 592; +const uint16_t kTrotecOneSpace = 1560; +const uint16_t kTrotecZeroMark = 592; +const uint16_t kTrotecZeroSpace = 592; +const uint16_t kTrotecGap = 6184; +const uint16_t kTrotecGapEnd = 1500; // made up value + +#if SEND_TROTEC + +void IRsend::sendTrotec(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kTrotecStateLength) return; + + for (uint16_t r = 0; r <= repeat; r++) { + sendGeneric(kTrotecHdrMark, kTrotecHdrSpace, kTrotecOneMark, + kTrotecOneSpace, kTrotecZeroMark, kTrotecZeroSpace, + kTrotecOneMark, kTrotecGap, data, nbytes, 36, false, + 0, // Repeats handled elsewhere + 50); + // More footer + enableIROut(36); + mark(kTrotecOneMark); + space(kTrotecGapEnd); + } +} +#endif // SEND_TROTEC + +IRTrotecESP::IRTrotecESP(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRTrotecESP::begin() { _irsend.begin(); } + +#if SEND_TROTEC +void IRTrotecESP::send() { + checksum(); + _irsend.sendTrotec(trotec); +} +#endif // SEND_TROTEC + +void IRTrotecESP::checksum() { + uint8_t sum = 0; + uint8_t i; + + for (i = 2; i < 8; i++) sum += trotec[i]; + + trotec[8] = sum & 0xFF; +} + +void IRTrotecESP::stateReset() { + for (uint8_t i = 2; i < kTrotecStateLength; i++) trotec[i] = 0x0; + + trotec[0] = kTrotecIntro1; + trotec[1] = kTrotecIntro2; + + setPower(false); + setTemp(kTrotecDefTemp); + setSpeed(kTrotecFanMed); + setMode(kTrotecAuto); +} + +uint8_t* IRTrotecESP::getRaw() { + checksum(); + return trotec; +} + +void IRTrotecESP::setPower(bool state) { + if (state) + trotec[2] |= (kTrotecOn << 3); + else + trotec[2] &= ~(kTrotecOn << 3); +} + +uint8_t IRTrotecESP::getPower() { return trotec[2] & (kTrotecOn << 3); } + +void IRTrotecESP::setSpeed(uint8_t speed) { + trotec[2] = (trotec[2] & 0xcf) | (speed << 4); +} + +uint8_t IRTrotecESP::getSpeed() { return trotec[2] & 0x30; } + +void IRTrotecESP::setMode(uint8_t mode) { + trotec[2] = (trotec[2] & 0xfc) | mode; +} + +uint8_t IRTrotecESP::getMode() { return trotec[2] & 0x03; } + +void IRTrotecESP::setTemp(uint8_t temp) { + if (temp < kTrotecMinTemp) + temp = kTrotecMinTemp; + else if (temp > kTrotecMaxTemp) + temp = kTrotecMaxTemp; + + trotec[3] = (trotec[3] & 0x80) | (temp - kTrotecMinTemp); +} + +uint8_t IRTrotecESP::getTemp() { return trotec[3] & 0x7f; } + +void IRTrotecESP::setSleep(bool sleep) { + if (sleep) + trotec[3] |= (kTrotecSleepOn << 7); + else + trotec[3] &= ~(kTrotecSleepOn << 7); +} + +bool IRTrotecESP::getSleep(void) { return trotec[3] & (kTrotecSleepOn << 7); } + +void IRTrotecESP::setTimer(uint8_t timer) { + if (timer > kTrotecMaxTimer) timer = kTrotecMaxTimer; + + if (timer) { + trotec[5] |= (kTrotecTimerOn << 6); + trotec[6] = timer; + } else { + trotec[5] &= ~(kTrotecTimerOn << 6); + trotec[6] = 0; + } +} + +uint8_t IRTrotecESP::getTimer() { return trotec[6]; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h new file mode 100644 index 000000000..040d9a722 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h @@ -0,0 +1,92 @@ +// Copyright 2017 stufisher + +#ifndef IR_TROTEC_H_ +#define IR_TROTEC_H_ + +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// Constants +// Byte 0 +const uint8_t kTrotecIntro1 = 0x12; + +// Byte 1 +const uint8_t kTrotecIntro2 = 0x34; + +// Byte 2 +const uint8_t kTrotecAuto = 0; +const uint8_t kTrotecCool = 1; +const uint8_t kTrotecDry = 2; +const uint8_t kTrotecFan = 3; + +const uint8_t kTrotecOn = 1; +const uint8_t kTrotecOff = 0; + +const uint8_t kTrotecFanLow = 1; +const uint8_t kTrotecFanMed = 2; +const uint8_t kTrotecFanHigh = 3; + +// Byte 3 +const uint8_t kTrotecMinTemp = 18; +const uint8_t kTrotecDefTemp = 25; +const uint8_t kTrotecMaxTemp = 32; + +const uint8_t kTrotecSleepOn = 1; + +// Byte 5 +const uint8_t kTrotecTimerOn = 1; + +// Byte 6 +const uint8_t kTrotecMinTimer = 0; +const uint8_t kTrotecMaxTimer = 23; + +// Legacy defines. (Deperecated) +#define TROTEC_AUTO kTrotecAuto +#define TROTEC_COOL kTrotecCool +#define TROTEC_DRY kTrotecDry +#define TROTEC_FAN kTrotecFan +#define TROTEC_FAN_LOW kTrotecFanLow +#define TROTEC_FAN_MED kTrotecFanMed +#define TROTEC_FAN_HIGH kTrotecFanHigh +#define TROTEC_MIN_TEMP kTrotecMinTemp +#define TROTEC_MAX_TEMP kTrotecMaxTemp +#define TROTEC_MIN_TIMER kTrotecMinTimer +#define TROTEC_MAX_TIMER kTrotecMaxTimer + +class IRTrotecESP { + public: + explicit IRTrotecESP(uint16_t pin); + +#if SEND_TROTEC + void send(); +#endif // SEND_TROTEC + void begin(); + + void setPower(bool state); + uint8_t getPower(); + + void setTemp(uint8_t temp); + uint8_t getTemp(); + + void setSpeed(uint8_t fan); + uint8_t getSpeed(); + + uint8_t getMode(); + void setMode(uint8_t mode); + + bool getSleep(); + void setSleep(bool sleep); + + uint8_t getTimer(); + void setTimer(uint8_t timer); + + uint8_t* getRaw(); + + private: + uint8_t trotec[kTrotecStateLength]; + void stateReset(); + void checksum(); + IRsend _irsend; +}; + +#endif // IR_TROTEC_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp new file mode 100644 index 000000000..671513991 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp @@ -0,0 +1,149 @@ +// Copyright 2018 David Conran +// +// Code to emulate Whirlpool protocol compatible devices. +// Should be compatible with: +// * SPIS409L, SPIS412L, SPIW409L, SPIW412L, SPIW418L +// + +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" + +// WW WW HH HH IIIII RRRRRR LL PPPPPP OOOOO OOOOO LL +// WW WW HH HH III RR RR LL PP PP OO OO OO OO LL +// WW W WW HHHHHHH III RRRRRR LL PPPPPP OO OO OO OO LL +// WW WWW WW HH HH III RR RR LL PP OO OO OO OO LL +// WW WW HH HH IIIII RR RR LLLLLLL PP OOOO0 OOOO0 LLLLLLL + +// Constants +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/509 +const uint16_t kWhirlpoolAcHdrMark = 8950; +const uint16_t kWhirlpoolAcHdrSpace = 4484; +const uint16_t kWhirlpoolAcBitMark = 597; +const uint16_t kWhirlpoolAcOneSpace = 1649; +const uint16_t kWhirlpoolAcZeroSpace = 533; +const uint16_t kWhirlpoolAcGap = 7920; +const uint32_t kWhirlpoolAcMinGap = 100000; // Completely made up value. +const uint8_t kWhirlpoolAcSections = 3; + +#if SEND_WHIRLPOOL_AC +// Send a Whirlpool A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kWhirlpoolAcStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/509 +void IRsend::sendWhirlpoolAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kWhirlpoolAcStateLength) + return; // Not enough bytes to send a proper message. + for (uint16_t r = 0; r <= repeat; r++) { + // Section 1 + sendGeneric(kWhirlpoolAcHdrMark, kWhirlpoolAcHdrSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, kWhirlpoolAcGap, + data, 6, // 6 bytes == 48 bits + 38000, // Complete guess of the modulation frequency. + false, 0, 50); + // Section 2 + sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace, + kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcGap, data + 6, 8, // 8 bytes == 64 bits + 38000, // Complete guess of the modulation frequency. + false, 0, 50); + // Section 3 + sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace, + kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcMinGap, data + 14, 7, // 7 bytes == 56 bits + 38000, // Complete guess of the modulation frequency. + false, 0, 50); + } +} +#endif // SEND_WHIRLPOOL_AC + +#if DECODE_WHIRLPOOL_AC +// Decode the supplied Whirlpool A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kWhirlpoolAcBits +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/509 +bool IRrecv::decodeWhirlpoolAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + 4 + kHeader + kFooter - 1) + return false; // Can't possibly be a valid Whirlpool A/C message. + if (strict) { + if (nbits != kWhirlpoolAcBits) return false; + } + + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + uint16_t i = 0; + match_result_t data_result; + uint8_t sectionSize[kWhirlpoolAcSections] = {6, 8, 7}; + + // Header + if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcHdrSpace)) + return false; + + // Data Section + // Keep reading bytes until we either run out of section or state to fill. + for (uint8_t section = 0, pos = 0; section < kWhirlpoolAcSections; + section++) { + pos += sectionSize[section]; + for (; offset <= results->rawlen - 16 && i < pos; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = + matchData(&(results->rawbuf[offset]), 8, kWhirlpoolAcBitMark, + kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) break; // Fail + // Data is in LSB order. We need to reverse it. + results->state[i] = (uint8_t)data_result.data; + } + // Section Footer + if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcBitMark)) + return false; + if (section < kWhirlpoolAcSections - 1) { // Inter-section gaps. + if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcGap)) return false; + } else { // Last section / End of message gap. + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kWhirlpoolAcGap)) + return false; + } + } + + // Compliance + if (strict) { + // Re-check we got the correct size/length due to the way we read the data. + if (dataBitsSoFar != kWhirlpoolAcBits) return false; + } + + // Success + results->decode_type = WHIRLPOOL_AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // WHIRLPOOL_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp new file mode 100644 index 000000000..555c50788 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp @@ -0,0 +1,135 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// W W H H Y Y N N TTTTT EEEEE RRRRR +// W W H H Y Y NN N T E R R +// W W W HHHHH Y N N N T EEE RRRR +// W W W H H Y N NN T E R R +// WWW H H Y N N T EEEEE R R + +// Whynter A/C ARC-110WD added by Francesco Meschia +// Whynter originally added from https://github.com/shirriff/Arduino-IRremote/ + +// Constants + +const uint16_t kWhynterTick = 50; +const uint16_t kWhynterHdrMarkTicks = 57; +const uint16_t kWhynterHdrMark = kWhynterHdrMarkTicks * kWhynterTick; +const uint16_t kWhynterHdrSpaceTicks = 57; +const uint16_t kWhynterHdrSpace = kWhynterHdrSpaceTicks * kWhynterTick; +const uint16_t kWhynterBitMarkTicks = 15; +const uint16_t kWhynterBitMark = kWhynterBitMarkTicks * kWhynterTick; +const uint16_t kWhynterOneSpaceTicks = 43; +const uint16_t kWhynterOneSpace = kWhynterOneSpaceTicks * kWhynterTick; +const uint16_t kWhynterZeroSpaceTicks = 15; +const uint16_t kWhynterZeroSpace = kWhynterZeroSpaceTicks * kWhynterTick; +const uint16_t kWhynterMinCommandLengthTicks = 2160; // Totally made up value. +const uint32_t kWhynterMinCommandLength = + kWhynterMinCommandLengthTicks * kWhynterTick; +const uint16_t kWhynterMinGapTicks = + kWhynterMinCommandLengthTicks - + (2 * (kWhynterBitMarkTicks + kWhynterZeroSpaceTicks) + + kWhynterBits * (kWhynterBitMarkTicks + kWhynterOneSpaceTicks)); +const uint16_t kWhynterMinGap = kWhynterMinGapTicks * kWhynterTick; + +#if SEND_WHYNTER +// Send a Whynter message. +// +// Args: +// data: message to be sent. +// nbits: Nr. of bits of the message to be sent. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: STABLE +// +// Ref: +// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp +void IRsend::sendWhynter(uint64_t data, uint16_t nbits, uint16_t repeat) { + // Set IR carrier frequency + enableIROut(38); + + for (uint16_t i = 0; i <= repeat; i++) { + // (Pre-)Header + mark(kWhynterBitMark); + space(kWhynterZeroSpace); + sendGeneric( + kWhynterHdrMark, kWhynterHdrSpace, kWhynterBitMark, kWhynterOneSpace, + kWhynterBitMark, kWhynterZeroSpace, kWhynterBitMark, kWhynterMinGap, + kWhynterMinCommandLength - (kWhynterBitMark + kWhynterZeroSpace), data, + nbits, 38, true, 0, // Repeats are already handled. + 50); + } +} +#endif + +#if DECODE_WHYNTER +// Decode the supplied Whynter message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA Strict mode is ALPHA. +// +// Ref: +// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp +bool IRrecv::decodeWhynter(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + 2 * kHeader + kFooter - 1) + return false; // We don't have enough entries to possibly match. + + // Compliance + if (strict && nbits != kWhynterBits) + return false; // Incorrect nr. of bits per spec. + + uint16_t offset = kStartOffset; + + // Header + // Sequence begins with a bit mark and a zero space. + // These are typically small, so we'll prefer to do the calibration + // on the much larger header mark & space that are next. + if (!matchMark(results->rawbuf[offset++], kWhynterBitMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kWhynterZeroSpace)) return false; + // Main header mark and space + if (!matchMark(results->rawbuf[offset], kWhynterHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kWhynterHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kWhynterHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kWhynterHdrSpaceTicks; + + // Data + uint64_t data = 0; + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, + kWhynterBitMarkTicks * m_tick, kWhynterOneSpaceTicks * s_tick, + kWhynterBitMarkTicks * m_tick, kWhynterZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Footer + if (!matchMark(results->rawbuf[offset++], kWhynterBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kWhynterMinGapTicks * s_tick)) + return false; + + // Success + results->decode_type = WHYNTER; + results->bits = nbits; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/test/IRrecv_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.cpp similarity index 68% rename from lib/IRremoteESP8266-2.2.1.02/test/IRrecv_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.cpp index 4b22656f6..85b6685f0 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/IRrecv_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.cpp @@ -1,7 +1,8 @@ // Copyright 2017 David Conran -#include "IRremoteESP8266.h" +#include "IRrecv_test.h" #include "IRrecv.h" +#include "IRremoteESP8266.h" #include "IRsend.h" #include "IRsend_test.h" #include "gtest/gtest.h" @@ -9,7 +10,7 @@ // Tests for the IRrecv object. TEST(TestIRrecv, DefaultBufferSize) { IRrecv irrecv_default(1); - EXPECT_EQ(RAWBUF, irrecv_default.getBufSize()); + EXPECT_EQ(kRawBuf, irrecv_default.getBufSize()); } TEST(TestIRrecv, LargeBufferSize) { @@ -29,7 +30,7 @@ TEST(TestIRrecv, MediumBufferSize) { TEST(TestIRrecv, IRrecvDestructor) { IRrecv *irrecv_ptr = new IRrecv(1); - EXPECT_EQ(RAWBUF, irrecv_ptr->getBufSize()); + EXPECT_EQ(kRawBuf, irrecv_ptr->getBufSize()); delete irrecv_ptr; irrecv_ptr = new IRrecv(1, 1234); @@ -119,7 +120,7 @@ TEST(TestDecode, DecodeNEC) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x807F40BF, irsend.capture.value); } @@ -133,7 +134,7 @@ TEST(TestDecode, DecodeJVC) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); } @@ -147,15 +148,15 @@ TEST(TestDecode, DecodeLG) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x4B4AE51, irsend.capture.value); irsend.reset(); - irsend.sendLG(0xB4B4AE51, LG32_BITS); + irsend.sendLG(0xB4B4AE51, kLg32Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0xB4B4AE51, irsend.capture.value); } @@ -167,9 +168,9 @@ TEST(TestDecode, DecodePanasonic) { irsend.reset(); irsend.sendPanasonic64(0x40040190ED7C); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x40040190ED7C, irsend.capture.value); } @@ -183,7 +184,7 @@ TEST(TestDecode, DecodeSamsung) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); EXPECT_EQ(0xE0E09966, irsend.capture.value); } @@ -198,7 +199,7 @@ TEST(TestDecode, DecodeSherwood) { ASSERT_TRUE(irrecv.decode(&irsend.capture)); // Sherwood codes are really NEC codes. EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x807F40BF, irsend.capture.value); } @@ -212,7 +213,7 @@ TEST(TestDecode, DecodeWhynter) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); } @@ -224,30 +225,29 @@ TEST(TestDecode, DecodeSony) { // Synthesised Normal Sony 20-bit message. irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_20_BITS, 0x1, 0x1, 0x1)); + irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1)); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); EXPECT_EQ(0x81080, irsend.capture.value); // Synthesised Normal Sony 15-bit message. irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_15_BITS, 21, 1), SONY_15_BITS); + irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_15_BITS, irsend.capture.bits); + EXPECT_EQ(kSony15Bits, irsend.capture.bits); EXPECT_EQ(0x5480, irsend.capture.value); - // Synthesised Normal Sony 12-bit message. irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_12_BITS, 21, 1), SONY_12_BITS); + irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); EXPECT_EQ(0xA90, irsend.capture.value); } @@ -261,7 +261,7 @@ TEST(TestDecode, DecodeSharp) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x454A, irsend.capture.value); } @@ -275,7 +275,7 @@ TEST(TestDecode, DecodeSanyo) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x2468DCB56A9, irsend.capture.value); } @@ -291,7 +291,7 @@ TEST(TestDecode, DecodeRCMM) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RCMM, irsend.capture.decode_type); - EXPECT_EQ(RCMM_BITS, irsend.capture.bits); + EXPECT_EQ(kRCMMBits, irsend.capture.bits); EXPECT_EQ(0xe0a600, irsend.capture.value); // Normal RCMM 12-bit message. @@ -323,7 +323,7 @@ TEST(TestDecode, DecodeMitsubishi) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); } @@ -338,15 +338,15 @@ TEST(TestDecode, DecodeRC5) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); // Synthesised Normal RC-5X 13-bit message. irsend.reset(); - irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), RC5X_BITS); + irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RC5X, irsend.capture.decode_type); - EXPECT_EQ(RC5X_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5XBits, irsend.capture.bits); EXPECT_EQ(0x1881, irsend.capture.value); } @@ -361,16 +361,16 @@ TEST(TestDecode, DecodeRC6) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); // Normal RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(0xC800F742A, RC6_36_BITS); + irsend.sendRC6(0xC800F742A, kRC6_36Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0xC800F742A, irsend.capture.value); } @@ -384,7 +384,7 @@ TEST(TestDecode, DecodeDish) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); + EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); } @@ -403,7 +403,7 @@ TEST(TestDecode, DecodeDenon) { EXPECT_EQ(0x2278, irsend.capture.value); // Legacy Denon 14-bit message. irsend.reset(); - irsend.sendDenon(0x1278, DENON_LEGACY_BITS); + irsend.sendDenon(0x1278, kDenonLegacyBits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(DENON, irsend.capture.decode_type); @@ -429,7 +429,7 @@ TEST(TestDecode, DecodeCoolix) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); } @@ -443,6 +443,119 @@ TEST(TestDecode, DecodeAiwa) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); } + +// Test matchData() on space encoded data. +TEST(TestMatchData, SpaceEncoded) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint16_t space_encoded_raw[11] = {500, 500, 500, 1500, 499, 499, + 501, 1501, 499, 1490, 500}; + match_result_t result; + + irsend.reset(); + irsend.sendRaw(space_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 500, 1500, 500, 500); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b01011, result.data); + EXPECT_EQ(10, result.used); + + irsend.reset(); + irsend.sendRaw(space_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 500, 1000, 500, 500); + ASSERT_FALSE(result.success); +} + +// Test matchData() on mark encoded data. +TEST(TestMatchData, MarkEncoded) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint16_t mark_encoded_raw[11] = {500, 500, 1500, 500, 499, 499, + 1501, 501, 1499, 490, 500}; + match_result_t result; + + irsend.reset(); + irsend.sendRaw(mark_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + // MSBF order. + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 500); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b01011, result.data); + EXPECT_EQ(10, result.used); + // LSBF order. + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 500, + kTolerance, kMarkExcess, false); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b11010, result.data); // Bits reversed of the previous test. + EXPECT_EQ(10, result.used); + + irsend.reset(); + irsend.sendRaw(mark_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + // MSBF order. + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 500); + ASSERT_FALSE(result.success); + // LSBF order. + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 500, + kTolerance, kMarkExcess, false); + ASSERT_FALSE(result.success); +} + +// Test matchData() on "equal total bit time" encoded data. +TEST(TestMatchData, EqualTotalBitTimeEncoded) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint16_t equal_encoded_raw[11] = {500, 1500, 1500, 500, 499, 1499, + 1501, 501, 1499, 490, 500}; + match_result_t result; + + irsend.reset(); + irsend.sendRaw(equal_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 1500); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b01011, result.data); + EXPECT_EQ(10, result.used); + + irsend.reset(); + irsend.sendRaw(equal_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 1000); + ASSERT_FALSE(result.success); +} + +// Test matchData() on arbitrary encoded data. +TEST(TestMatchData, ArbitraryEncoded) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint16_t arbitrary_encoded_raw[11] = {500, 1500, 3000, 1000, 499, 1499, + 3001, 1001, 2999, 990, 500}; + match_result_t result; + + irsend.reset(); + irsend.sendRaw(arbitrary_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = + irrecv.matchData(irsend.capture.rawbuf + 1, 5, 3000, 1000, 500, 1500); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b01011, result.data); + EXPECT_EQ(10, result.used); + + irsend.reset(); + irsend.sendRaw(arbitrary_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 1000); + ASSERT_FALSE(result.success); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h b/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h new file mode 100644 index 000000000..bb366c1ee --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h @@ -0,0 +1,17 @@ +// Copyright 2017 David Conran + +#ifndef TEST_IRRECV_TEST_H_ +#define TEST_IRRECV_TEST_H_ + +#include +#include +#include +#include "IRutils.h" + +#define EXPECT_STATE_EQ(a, b, c) \ + for (uint8_t i = 0; i < c / 8; ++i) { \ + EXPECT_EQ(a[i], b[i]) << "Expected state " \ + "differs at i = " \ + << uint64ToString(i); \ + } +#endif // TEST_IRRECV_TEST_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp new file mode 100644 index 000000000..353639918 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp @@ -0,0 +1,290 @@ +// Copyright 2017 David Conran + +#include "IRsend_test.h" +#include "IRsend.h" +#include "gtest/gtest.h" + +// Tests sendData(). + +// Test sending zero bits. +TEST(TestSendData, SendZeroBits) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1, 0, true); + EXPECT_EQ("", irsend.outputStr()); +} + +// Test sending zero and one. +TEST(TestSendData, SendSingleBit) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + EXPECT_EQ("m1s2", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b0, 1, true); + EXPECT_EQ("m3s4", irsend.outputStr()); +} + +// Test sending bit order. +TEST(TestSendData, TestingBitSendOrder) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b10, 2, true); + EXPECT_EQ("m1s2m3s4", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b10, 2, false); + EXPECT_EQ("m3s4m1s2", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b0001, 4, false); + EXPECT_EQ("m1s2m3s4m3s4m3s4", irsend.outputStr()); +} + +// Test sending typical data. +TEST(TestSendData, SendTypicalData) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1010110011110000, 16, true); + EXPECT_EQ("m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4m3s4", + irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0x1234567890ABCDEF, 64, true); + EXPECT_EQ( + "m3s4m3s4m3s4m1s2m3s4m3s4m1s2m3s4m3s4m3s4m1s2m1s2m3s4m1s2m3s4m3s4" + "m3s4m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4" + "m1s2m3s4m3s4m1s2m3s4m3s4m3s4m3s4m1s2m3s4m1s2m3s4m1s2m3s4m1s2m1s2" + "m1s2m1s2m3s4m3s4m1s2m1s2m3s4m1s2m1s2m1s2m1s2m3s4m1s2m1s2m1s2m1s2", + irsend.outputStr()); +} + +// Test sending more than expected bits. +TEST(TestSendData, SendOverLargeData) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0xFFFFFFFFFFFFFFFF, 70, true); + EXPECT_EQ( + "m3s4m3s4m3s4m3s4m3s4m3s4" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2", + irsend.outputStr()); +} + +// Test inverting the output. +TEST(TestIRSend, InvertedOutput) { + IRsendTest irsend(4, true); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + EXPECT_EQ("s1m2", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b0, 1, true); + EXPECT_EQ("s3m4", irsend.outputStr()); +} + +// Test typical use of sendRaw(). +TEST(TestSendRaw, GeneralUse) { + IRsendTest irsend(4); + IRrecv irrecv(0); + + irsend.begin(); + // NEC C3E0E0E8 as measured in #204 + uint16_t rawData[67] = { + 8950, 4500, 550, 1650, 600, 1650, 550, 550, 600, 500, 600, 550, + 550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 1650, 550, 1700, + 550, 550, 600, 550, 550, 550, 600, 500, 600, 550, 550, 1650, + 600, 1650, 600, 1650, 550, 550, 600, 500, 600, 500, 600, 550, + 550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 500, 650, 1600, + 600, 500, 600, 550, 550, 550, 600}; + + irsend.sendRaw(rawData, 67, 38); + EXPECT_EQ( + "m8950s4500" + "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" + "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" + "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" + "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" + "m600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendRaw(rawData, 67, 38); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0xC3E0E0E8, irsend.capture.value); + EXPECT_EQ( + "m8950s4500" + "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" + "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" + "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" + "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" + "m600", + irsend.outputStr()); +} + +// Incorrect handling of decodes from Raw. i.e. There is no gap recorded at +// the end of a command when using the interrupt code. sendRaw() best emulates +// this for unit testing purposes. sendGC() and sendXXX() will add the trailing +// gap. Users won't see this in normal use. +TEST(TestSendRaw, NoTrailingGap) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[67] = { + 9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, 600, 1650, + 650, 550, 600, 1650, 650, 1650, 650, 1650, 600, 550, 650, 1650, + 650, 1650, 650, 550, 600, 1650, 650, 1650, 650, 550, 650, 550, + 650, 1650, 650, 550, 650, 550, 650, 550, 600, 550, 650, 550, + 650, 550, 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, + 650, 1650, 650, 1650, 650, 1650, 600}; + irsend.sendRaw(rawData, 67, 38); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); +} + +TEST(TestLowLevelSend, MarkFrequencyModulationAt38kHz) { + IRsendLowLevelTest irsend(0); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(38000, 50); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs" + "[On]10usecs[Off]11usecs[On]10usecs[Off]6usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 33); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs" + "[On]6usecs[Off]15usecs[On]6usecs[Off]10usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 100); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, MarkFrequencyModulationAt36_7kHz) { + IRsendLowLevelTest irsend(0); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(36700, 50); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs" + "[On]11usecs[Off]11usecs[On]11usecs[Off]1usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 33); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs" + "[On]7usecs[Off]15usecs[On]7usecs[Off]5usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 100); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, MarkFrequencyModulationAt40kHz) { + IRsendLowLevelTest irsend(0); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(40000, 50); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs" + "[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 33); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs" + "[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 100); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, MarkNoModulation) { + IRsendLowLevelTest irsend(0, false, false); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(38000, 50); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 25); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 75); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, SpaceFrequencyModulation) { + IRsendLowLevelTest irsend(0); + + irsend.reset(); + irsend.enableIROut(38000); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 75); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 100); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 33); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, SpaceNoModulation) { + IRsendLowLevelTest irsend(0, false, false); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(38000, 50); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 25); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 75); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h b/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h new file mode 100644 index 000000000..6d9fe51b8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h @@ -0,0 +1,135 @@ +// Copyright 2017 David Conran + +#ifndef TEST_IRSEND_TEST_H_ +#define TEST_IRSEND_TEST_H_ + +#define __STDC_LIMIT_MACROS +#include +#include +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" + +#define OUTPUT_BUF 10000U +#define RAW_BUF 10000U + +#ifdef UNIT_TEST +// Used to help simulate elapsed time in unit tests. +uint32_t _IRtimer_unittest_now = 0; +#endif // UNIT_TEST + +class IRsendTest : public IRsend { + public: + uint32_t output[OUTPUT_BUF]; + uint16_t last; + uint16_t rawbuf[RAW_BUF]; + decode_results capture; + + explicit IRsendTest(uint16_t x, bool i = false, bool j = true) + : IRsend(x, i, j) { + reset(); + } + + void reset() { + last = 0; + for (uint16_t i = 0; i < OUTPUT_BUF; i++) output[i] = 0; + for (uint16_t i = 0; i < RAW_BUF; i++) rawbuf[i] = 0; + } + + std::string outputStr() { + std::stringstream result; + if (last == 0 && output[0] == 0) return ""; + for (uint16_t i = 0; i <= last; i++) { + if ((i & 1) != outputOff) // Odd XOR outputOff + result << "s"; + else + result << "m"; + result << output[i]; + } + reset(); + return result.str(); + } + + void makeDecodeResult(uint16_t offset = 0) { + capture.decode_type = UNKNOWN; + capture.bits = 0; + capture.rawlen = last + 2 - offset; + capture.overflow = (last - offset >= (int16_t)RAW_BUF); + capture.repeat = false; + capture.address = 0; + capture.command = 0; + capture.value = 0; + capture.rawbuf = rawbuf; + for (uint16_t i = 0; (i < RAW_BUF - 1) && (offset < OUTPUT_BUF); + i++, offset++) + if (output[offset] / kRawTick > UINT16_MAX) + rawbuf[i + 1] = UINT16_MAX; + else + rawbuf[i + 1] = output[offset] / kRawTick; + } + + void dumpRawResult() { + std::cout << std::dec; + if (capture.rawlen == 0) return; + std::cout << "uint16_t rawbuf[" << capture.rawlen - 1 << "] = {"; + for (uint16_t i = 1; i < capture.rawlen; i++) { + if (i % 8 == 1) std::cout << std::endl << " "; + std::cout << (capture.rawbuf[i] * kRawTick); + // std::cout << "(" << capture.rawbuf[i] << ")"; + if (i < capture.rawlen - 1) std::cout << ", "; + } + std::cout << "};" << std::endl; + } + + void addGap(uint32_t usecs) { space(usecs); } + + uint16_t mark(uint16_t usec) { + IRtimer::add(usec); + if (last >= OUTPUT_BUF) return 0; + if (last & 1) // Is odd? (i.e. last call was a space()) + output[++last] = usec; + else + output[last] += usec; + return 0; + } + + void space(uint32_t time) { + IRtimer::add(time); + if (last >= OUTPUT_BUF) return; + if (last & 1) { // Is odd? (i.e. last call was a space()) + output[last] += time; + } else { + output[++last] = time; + } + } +}; + +#ifdef UNIT_TEST +class IRsendLowLevelTest : public IRsend { + public: + std::string low_level_sequence; + + explicit IRsendLowLevelTest(uint16_t x, bool i = false, bool j = true) + : IRsend(x, i, j) { + reset(); + } + + void reset() { low_level_sequence = ""; } + + protected: + void _delayMicroseconds(uint32_t usec) { + _IRtimer_unittest_now += usec; + std::ostringstream Convert; + Convert << usec; + low_level_sequence += Convert.str() + "usecs"; + } + + void ledOff() { low_level_sequence += "[Off]"; } + + void ledOn() { low_level_sequence += "[On]"; } +}; +#endif // UNIT_TEST + +#endif // TEST_IRSEND_TEST_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp new file mode 100644 index 000000000..91cf4725c --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp @@ -0,0 +1,352 @@ +// Copyright 2017 David Conran + +#include "IRutils.h" +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests reverseBits(). + +// Tests reverseBits for typical use. +TEST(ReverseBitsTest, TypicalUse) { + EXPECT_EQ(0xF, reverseBits(0xF0, 8)); + EXPECT_EQ(0xFFFF, reverseBits(0xFFFF0000, 32)); + EXPECT_EQ(0x555500005555FFFF, reverseBits(0xFFFFAAAA0000AAAA, 64)); + EXPECT_EQ(0, reverseBits(0, 64)); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, reverseBits(0xFFFFFFFFFFFFFFFF, 64)); +} + +// Tests reverseBits for bit size values <= 1 +TEST(ReverseBitsTest, LessThanTwoBitsReversed) { + EXPECT_EQ(0x12345678, reverseBits(0x12345678, 1)); + EXPECT_EQ(1234, reverseBits(1234, 0)); +} + +// Tests reverseBits for bit size larger than a uint64_t. +TEST(ReverseBitsTest, LargerThan64BitsReversed) { + EXPECT_EQ(0, reverseBits(0, 65)); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, reverseBits(0xFFFFFFFFFFFFFFFF, 100)); + EXPECT_EQ(0x555500005555FFFF, reverseBits(0xFFFFAAAA0000AAAA, 3000)); +} + +// Tests reverseBits for bit sizes less than all the data stored. +TEST(ReverseBitsTest, LessBitsReversedThanInputHasSet) { + EXPECT_EQ(0xF8, reverseBits(0xF1, 4)); + EXPECT_EQ(0xF5, reverseBits(0xFA, 4)); + EXPECT_EQ(0x12345678FFFF0000, reverseBits(0x123456780000FFFF, 32)); +} + +// Tests for uint64ToString() + +TEST(TestUint64ToString, TrivialCases) { + EXPECT_EQ("0", uint64ToString(0)); // Default base (10) + EXPECT_EQ("0", uint64ToString(0, 2)); // Base-2 + EXPECT_EQ("0", uint64ToString(0, 8)); // Base-8 + EXPECT_EQ("0", uint64ToString(0, 10)); // Base-10 + EXPECT_EQ("0", uint64ToString(0, 16)); // Base-16 + + EXPECT_EQ("1", uint64ToString(1, 2)); // Base-2 + EXPECT_EQ("2", uint64ToString(2, 8)); // Base-8 + EXPECT_EQ("3", uint64ToString(3, 10)); // Base-10 + EXPECT_EQ("4", uint64ToString(4, 16)); // Base-16 +} + +TEST(TestUint64ToString, NormalUse) { + EXPECT_EQ("12345", uint64ToString(12345)); + EXPECT_EQ("100", uint64ToString(4, 2)); + EXPECT_EQ("3039", uint64ToString(12345, 16)); + EXPECT_EQ("123456", uint64ToString(123456)); + EXPECT_EQ("1E240", uint64ToString(123456, 16)); + EXPECT_EQ("FEEDDEADBEEF", uint64ToString(0xfeeddeadbeef, 16)); +} + +TEST(TestUint64ToString, Max64Bit) { + EXPECT_EQ("18446744073709551615", uint64ToString(UINT64_MAX)); // Default + EXPECT_EQ("1111111111111111111111111111111111111111111111111111111111111111", + uint64ToString(UINT64_MAX, 2)); // Base-2 + EXPECT_EQ("1777777777777777777777", uint64ToString(UINT64_MAX, 8)); // Base-8 + EXPECT_EQ("18446744073709551615", uint64ToString(UINT64_MAX, 10)); // Base-10 + EXPECT_EQ("FFFFFFFFFFFFFFFF", uint64ToString(UINT64_MAX, 16)); // Base-16 +} + +TEST(TestUint64ToString, Max32Bit) { + EXPECT_EQ("4294967295", uint64ToString(UINT32_MAX)); // Default + EXPECT_EQ("37777777777", uint64ToString(UINT32_MAX, 8)); // Base-8 + EXPECT_EQ("4294967295", uint64ToString(UINT32_MAX, 10)); // Base-10 + EXPECT_EQ("FFFFFFFF", uint64ToString(UINT32_MAX, 16)); // Base-16 +} + +TEST(TestUint64ToString, InterestingCases) { + // Previous hacky-code didn't handle leading zeros in the lower 32 bits. + EXPECT_EQ("100000000", uint64ToString(0x100000000, 16)); + EXPECT_EQ("100000001", uint64ToString(0x100000001, 16)); +} + +TEST(TestUint64ToString, SillyBases) { + // If we are given a silly base, we should defer to Base-10. + EXPECT_EQ("12345", uint64ToString(12345, 0)); // Super silly, makes no sense. + EXPECT_EQ("12345", uint64ToString(12345, 1)); // We don't do unary. + EXPECT_EQ("12345", uint64ToString(12345, 100)); // We can't print base-100. + EXPECT_EQ("12345", uint64ToString(12345, 37)); // Base-37 is one to far. + EXPECT_EQ("9IX", uint64ToString(12345, 36)); // But we *can* do base-36. +} + +TEST(TestGetCorrectedRawLength, NoLargeValues) { + IRsendTest irsend(0); + IRrecv irrecv(1); + uint16_t test_data[7] = {1, 2, 3, 4, 5, 6, 7}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(test_data, 7, 38000); + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + EXPECT_EQ(7, getCorrectedRawLength(&irsend.capture)); +} + +TEST(TestGetCorrectedRawLength, WithLargeValues) { + IRsendTest irsend(0); + IRrecv irrecv(1); + uint16_t test_data[7] = {10, 20, 30, 40, 50, 60, 70}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(test_data, 7, 38000); + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + irsend.capture.rawbuf[3] = 60000; + ASSERT_EQ(2, kRawTick); // The following values rely on kRawTick being 2. + EXPECT_EQ(7 + 2, getCorrectedRawLength(&irsend.capture)); + irsend.capture.rawbuf[4] = UINT16_MAX - 1; + EXPECT_EQ(7 + 2 * 2, getCorrectedRawLength(&irsend.capture)); + irsend.capture.rawbuf[4] = UINT16_MAX; + EXPECT_EQ(7 + 2 * 2, getCorrectedRawLength(&irsend.capture)); +} + +TEST(TestResultToSourceCode, SimpleTests) { + IRsendTest irsend(0); + IRrecv irrecv(1); + uint16_t test_data[7] = {10, 20, 30, 40, 50, 60, 70}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(test_data, 7, 38000); + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + EXPECT_EQ( + "uint16_t rawData[7] = {10, 20, 30, 40, 50, 60, 70};" + " // UNKNOWN A5E5F35D\n", + resultToSourceCode(&irsend.capture)); + + // Stick in some large values. + irsend.capture.rawbuf[3] = 60000; + EXPECT_EQ( + "uint16_t rawData[9] = {10, 20, 65535, 0, 54465, 40," + " 50, 60, 70}; // UNKNOWN A5E5F35D\n", + resultToSourceCode(&irsend.capture)); + irsend.capture.rawbuf[5] = UINT16_MAX; + EXPECT_EQ( + "uint16_t rawData[11] = {10, 20, 65535, 0, 54465, 40," + " 65535, 0, 65535, 60, 70}; // UNKNOWN A5E5F35D\n", + resultToSourceCode(&irsend.capture)); + + // Reset and put the large value in a space location. + irsend.reset(); + irsend.sendRaw(test_data, 7, 38000); + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + irsend.capture.rawbuf[4] = UINT16_MAX - 1; + EXPECT_EQ( + "uint16_t rawData[9] = {10, 20, 30, 65535, 0, 65533," + " 50, 60, 70}; // UNKNOWN A5E5F35D\n", + resultToSourceCode(&irsend.capture)); +} + +TEST(TestResultToSourceCode, SimpleProtocols) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + // Generate a code which has address & command values. + irsend.reset(); + irsend.sendNEC(irsend.encodeNEC(0x10, 0x20)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(NEC, irsend.capture.decode_type); + ASSERT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ( + "uint16_t rawData[68] = {8960, 4480, 560, 560, 560, 560, 560, 560, " + "560, 560, 560, 1680, 560, 560, 560, 560, 560, 560, 560, 1680, " + "560, 1680, 560, 1680, 560, 1680, 560, 560, 560, 1680, 560, 1680, " + "560, 1680, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, " + "560, 1680, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 1680, " + "560, 1680, 560, 1680, 560, 560, 560, 1680, 560, 1680, 560, 40320 " + "}; // NEC 8F704FB\n" + "uint32_t address = 0x10;\n" + "uint32_t command = 0x20;\n" + "uint64_t data = 0x8F704FB;\n", + resultToSourceCode(&irsend.capture)); + + // Generate a code which DOESN'T have address & command values. + irsend.reset(); + irsend.sendNikai(0xD0F2F); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(NIKAI, irsend.capture.decode_type); + ASSERT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ( + "uint16_t rawData[52] = {4000, 4000, 500, 2000, 500, 2000, " + "500, 2000, 500, 2000, 500, 1000, 500, 1000, 500, 2000, 500, 1000, " + "500, 2000, 500, 2000, 500, 2000, 500, 2000, 500, 1000, 500, 1000, " + "500, 1000, 500, 1000, 500, 2000, 500, 2000, 500, 1000, 500, 2000, " + "500, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 8500 };" + " // NIKAI D0F2F\n" + "uint64_t data = 0xD0F2F;\n", + resultToSourceCode(&irsend.capture)); +} + +TEST(TestResultToSourceCode, ComplexProtocols) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint8_t state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + + irsend.reset(); + irsend.sendToshibaAC(state); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + EXPECT_EQ( + "uint16_t rawData[296] = {4400, 4300, 542, 1622, 542, 1622, " + "542, 1622, 542, 1622, 542, 472, 542, 472, 542, 1622, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 1622, 542, 1622, " + "542, 472, 542, 1622, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 1622, 542, 1622, 542, 1622, 542, 1622, " + "542, 1622, 542, 1622, 542, 1622, 542, 1622, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 1622, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 1622, 542, 7048, 4400, 4300, " + "542, 1622, 542, 1622, 542, 1622, 542, 1622, 542, 472, 542, 472, " + "542, 1622, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 1622, 542, 1622, 542, 472, 542, 1622, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 1622, 542, 1622, " + "542, 1622, 542, 1622, 542, 1622, 542, 1622, 542, 1622, 542, 1622, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 1622, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 1622, " + "542, 7048 }; // TOSHIBA_AC\n" + "uint8_t state[9] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, " + "0x01};\n", + resultToSourceCode(&irsend.capture)); +} + +TEST(TestResultToTimingInfo, General) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + irsend.reset(); + irsend.sendNEC(irsend.encodeNEC(0x10, 0x20)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(NEC, irsend.capture.decode_type); + ASSERT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ( + "Raw Timing[68]:\n" + " + 8960, - 4480, + 560, - 560, + 560, - 560," + " + 560, - 560, \n" + " + 560, - 560, + 560, - 1680, + 560, - 560," + " + 560, - 560, \n" + " + 560, - 560, + 560, - 1680, + 560, - 1680," + " + 560, - 1680, \n" + " + 560, - 1680, + 560, - 560, + 560, - 1680," + " + 560, - 1680, \n" + " + 560, - 1680, + 560, - 560, + 560, - 560," + " + 560, - 560, \n" + " + 560, - 560, + 560, - 560, + 560, - 1680," + " + 560, - 560, \n" + " + 560, - 560, + 560, - 1680, + 560, - 1680," + " + 560, - 1680, \n" + " + 560, - 1680, + 560, - 1680, + 560, - 560," + " + 560, - 1680, \n" + " + 560, - 1680, + 560, - 40320\n", + resultToTimingInfo(&irsend.capture)); + + irsend.reset(); + uint16_t rawData[9] = {10, 20, 30, 40, 50, 60, 70, 80, 90}; + irsend.sendRaw(rawData, 9, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ( + "Raw Timing[9]:\n" + " + 10, - 20, + 30, - 40, + 50, - 60," + " + 70, - 80, \n" + " + 90\n", + resultToTimingInfo(&irsend.capture)); +} + +TEST(TestResultToHumanReadableBasic, SimpleCodes) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + irsend.reset(); + irsend.sendNEC(irsend.encodeNEC(0x10, 0x20)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(NEC, irsend.capture.decode_type); + ASSERT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ( + "Encoding : NEC\n" + "Code : 8F704FB (32 bits)\n", + resultToHumanReadableBasic(&irsend.capture)); +} + +TEST(TestResultToHumanReadableBasic, ComplexCodes) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint8_t state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + + irsend.reset(); + irsend.sendToshibaAC(state); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + EXPECT_EQ( + "Encoding : TOSHIBA_AC\n" + "Code : F20D03FC0100000001 (72 bits)\n", + resultToHumanReadableBasic(&irsend.capture)); +} + +TEST(TestInvertBits, Normal) { + ASSERT_EQ(0xAAAA5555AAAA5555, invertBits(0x5555AAAA5555AAAA, 64)); + ASSERT_EQ(0xAAAA5555, invertBits(0x5555AAAA, 32)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFF, invertBits(0x0, 64)); + ASSERT_EQ(0x0, invertBits(invertBits(0x0, 64), 64)); + ASSERT_EQ(0x2, invertBits(0x1, 2)); +} + +TEST(TestInvertBits, ZeroBits) { + ASSERT_EQ(0xAAAA5555AAAA5555, invertBits(0xAAAA5555AAAA5555, 0)); + ASSERT_EQ(0x0, invertBits(0x0, 0)); + ASSERT_EQ(0x1, invertBits(0x1, 0)); +} + +TEST(TestInvertBits, MoreThan64Bits) { + ASSERT_EQ(0xAAAA5555AAAA5555, invertBits(0x5555AAAA5555AAAA, 70)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFF, invertBits(0x0, 128)); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/Makefile b/lib/IRremoteESP8266-2.5.2.03/test/Makefile similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/test/Makefile rename to lib/IRremoteESP8266-2.5.2.03/test/Makefile index 7ffd00053..d53014183 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/Makefile +++ b/lib/IRremoteESP8266-2.5.2.03/test/Makefile @@ -1,8 +1,10 @@ # SYNOPSIS: # -# make [all] - makes everything. -# make TARGET - makes the given target. -# make clean - removes all files generated by make. +# make [all] - makes everything. +# make TARGET - makes the given target. +# make run - makes everything and runs all the tests. +# make clean - removes all files generated by make. +# make install-googletest - install the googletest code suite # Please tweak the following variable definitions as needed by your # project, except GTEST_HEADERS, which you can use in your own targets @@ -30,7 +32,11 @@ TESTS = IRutils_test IRsend_test ir_NEC_test ir_GlobalCache_test \ ir_JVC_test ir_RCMM_test ir_LG_test ir_Mitsubishi_test ir_Sharp_test \ ir_RC5_RC6_test ir_Panasonic_test ir_Dish_test ir_Whynter_test \ ir_Aiwa_test ir_Denon_test ir_Sanyo_test ir_Daikin_test ir_Coolix_test \ - ir_Gree_test IRrecv_test ir_Pronto_test ir_Fujitsu_test ir_Nikai_test + ir_Gree_test IRrecv_test ir_Pronto_test ir_Fujitsu_test ir_Nikai_test \ + ir_Toshiba_test ir_Midea_test ir_Magiquest_test ir_Lasertag_test \ + ir_Carrier_test ir_Haier_test ir_Hitachi_test ir_GICable_test \ + ir_Whirlpool_test ir_Lutron_test ir_Electra_test ir_Pioneer_test \ + ir_MWM_test # All Google Test headers. Usually you shouldn't change this # definition. @@ -56,8 +62,10 @@ run : all echo "PASS: \o/ \o/ All unit tests passed. \o/ \o/"; \ fi +run_tests : run + install-googletest : - git clone https://github.com/google/googletest.git ../lib/googletest + git clone -b v1.8.x https://github.com/google/googletest.git ../lib/googletest # Builds gtest.a and gtest_main.a. @@ -67,17 +75,40 @@ GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) # All the IR protocol object files. PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \ - ir_LG.o ir_Mitsubishi.o ir_Fujitsu.o ir_Sharp.o ir_Sanyo.o ir_Denon.o ir_Dish.o \ - ir_Panasonic.o ir_Whynter.o ir_Coolix.o ir_Aiwa.o ir_Sherwood.o \ - ir_Kelvinator.o ir_Daikin.o ir_Gree.o ir_Pronto.o ir_Nikai.o + ir_LG.o ir_Mitsubishi.o ir_Fujitsu.o ir_Sharp.o ir_Sanyo.o ir_Denon.o ir_Dish.o \ + ir_Panasonic.o ir_Whynter.o ir_Coolix.o ir_Aiwa.o ir_Sherwood.o \ + ir_Kelvinator.o ir_Daikin.o ir_Gree.o ir_Pronto.o ir_Nikai.o ir_Toshiba.o \ + ir_Midea.o ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o \ + ir_Hitachi.o ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o \ + ir_Pioneer.o ir_MWM.o + +# All the IR Protocol header files. +PROTOCOLS_H = $(USER_DIR)/ir_Argo.h \ + $(USER_DIR)/ir_Gree.h \ + $(USER_DIR)/ir_Magiquest.h \ + $(USER_DIR)/ir_Coolix.h \ + $(USER_DIR)/ir_Haier.h \ + $(USER_DIR)/ir_Midea.h \ + $(USER_DIR)/ir_Toshiba.h \ + $(USER_DIR)/ir_Daikin.h \ + $(USER_DIR)/ir_Kelvinator.h \ + $(USER_DIR)/ir_Mitsubishi.h \ + $(USER_DIR)/ir_NEC.h \ + $(USER_DIR)/ir_Samsung.h \ + $(USER_DIR)/ir_Trotec.h \ + $(USER_DIR)/ir_Fujitsu.h \ + $(USER_DIR)/ir_LG.h \ + $(USER_DIR)/ir_Panasonic.h # Common object files COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o ir_GlobalCache.o \ $(PROTOCOLS) gtest_main.a # Common dependencies COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \ - $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h + $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h \ + $(PROTOCOLS_H) + # Common test dependencies -COMMON_TEST_DEPS = $(COMMON_DEPS) IRsend_test.h +COMMON_TEST_DEPS = $(COMMON_DEPS) IRrecv_test.h IRsend_test.h # For simplicity and to avoid depending on Google Test's # implementation details, the dependencies specified below are @@ -97,17 +128,17 @@ gtest.a : gtest-all.o gtest_main.a : gtest-all.o gtest_main.o $(AR) $(ARFLAGS) $@ $^ -# Builds a our test. A test should link with either gtest.a or +# Builds our test. A test should link with either gtest.a or # gtest_main.a, depending on whether it defines its own main() # function. -IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h +IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp -IRutils_test.o : IRutils_test.cpp $(USER_DIR)/IRutils.h $(GTEST_HEADERS) +IRutils_test.o : IRutils_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c IRutils_test.cpp -IRutils_test : IRutils.o IRutils_test.o gtest_main.a +IRutils_test : IRutils_test.o ir_NEC.o ir_Nikai.o ir_Toshiba.o $(COMMON_OBJ) gtest_main.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h @@ -131,7 +162,7 @@ IRrecv_test.o : IRrecv_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend IRrecv_test : IRrecv_test.o $(COMMON_OBJ) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ -ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(COMMON_DEPS) +ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(USER_DIR)/ir_NEC.h $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_NEC.cpp ir_NEC_test.o : ir_NEC_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) @@ -167,10 +198,10 @@ ir_Sony_test.o : ir_Sony_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) ir_Sony_test : $(COMMON_OBJ) ir_Sony_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ -ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(COMMON_DEPS) +ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp -ir_Samsung_test.o : ir_Samsung_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) +ir_Samsung_test.o : ir_Samsung_test.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Samsung_test.cpp ir_Samsung_test : $(COMMON_OBJ) ir_Samsung_test.o @@ -278,7 +309,7 @@ ir_Whynter_test : $(COMMON_OBJ) ir_Whynter_test.o ir_Coolix.o : $(USER_DIR)/ir_Coolix.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Coolix.cpp -ir_Coolix_test.o : ir_Coolix_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) +ir_Coolix_test.o : ir_Coolix_test.cpp $(USER_DIR)/ir_Coolix.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Coolix_test.cpp ir_Coolix_test : $(COMMON_OBJ) ir_Coolix_test.o @@ -326,7 +357,7 @@ ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS) ir_Gree_test.o : ir_Gree_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Gree_test.cpp -ir_Gree_test : $(COMMON_OBJ) ir_Gree_test.o +ir_Gree_test : $(COMMON_OBJ) ir_Gree_test.o ir_Kelvinator.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS) @@ -346,3 +377,120 @@ ir_Nikai_test.o : ir_Nikai_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) ir_Nikai_test : $(COMMON_OBJ) ir_Nikai_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Toshiba.o : $(USER_DIR)/ir_Toshiba.cpp $(USER_DIR)/ir_Toshiba.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Toshiba.cpp + +ir_Toshiba_test.o : ir_Toshiba_test.cpp $(USER_DIR)/ir_Toshiba.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Toshiba_test.cpp + +ir_Toshiba_test : $(COMMON_OBJ) ir_Toshiba_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Midea.o : $(USER_DIR)/ir_Midea.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Midea.cpp + +ir_Midea_test.o : ir_Midea_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Midea_test.cpp + +ir_Midea_test : $(COMMON_OBJ) ir_Midea_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Magiquest.o : $(USER_DIR)/ir_Magiquest.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Magiquest.cpp + +ir_Magiquest_test.o : ir_Magiquest_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Magiquest_test.cpp + +ir_Magiquest_test : $(COMMON_OBJ) ir_Magiquest_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Lasertag.o : $(USER_DIR)/ir_Lasertag.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lasertag.cpp + +ir_Lasertag_test.o : ir_Lasertag_test.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Lasertag_test.cpp + +ir_Lasertag_test : $(COMMON_OBJ) ir_Lasertag_test.o ir_RC5_RC6.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Carrier.o : $(USER_DIR)/ir_Carrier.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Carrier.cpp + +ir_Carrier_test.o : ir_Carrier_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Carrier_test.cpp + +ir_Carrier_test : $(COMMON_OBJ) ir_Carrier_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Haier.o : $(USER_DIR)/ir_Haier.cpp $(USER_DIR)/ir_Haier.h $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Haier.cpp + +ir_Haier_test.o : ir_Haier_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Haier_test.cpp + +ir_Haier_test : $(COMMON_OBJ) ir_Haier_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Hitachi.o : $(USER_DIR)/ir_Hitachi.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Hitachi.cpp + +ir_Hitachi_test.o : ir_Hitachi_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Hitachi_test.cpp + +ir_Hitachi_test : $(COMMON_OBJ) ir_Hitachi_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_GICable.o : $(USER_DIR)/ir_GICable.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GICable.cpp + +ir_GICable_test.o : ir_GICable_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_GICable_test.cpp + +ir_GICable_test : $(COMMON_OBJ) ir_GICable_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Whirlpool.o : $(USER_DIR)/ir_Whirlpool.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whirlpool.cpp + +ir_Whirlpool_test.o : ir_Whirlpool_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Whirlpool_test.cpp + +ir_Whirlpool_test : $(COMMON_OBJ) ir_Whirlpool_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Lutron.o : $(USER_DIR)/ir_Lutron.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lutron.cpp + +ir_Lutron_test.o : ir_Lutron_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Lutron_test.cpp + +ir_Lutron_test : $(COMMON_OBJ) ir_Lutron_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Electra.o : $(USER_DIR)/ir_Electra.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Electra.cpp + +ir_Electra_test.o : ir_Electra_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Electra_test.cpp + +ir_Electra_test : $(COMMON_OBJ) ir_Electra_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Pioneer.o : $(USER_DIR)/ir_Pioneer.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pioneer.cpp + +ir_Pioneer_test.o : ir_Pioneer_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Pioneer_test.cpp + +ir_Pioneer_test : $(COMMON_OBJ) ir_Pioneer_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_MWM.o : $(USER_DIR)/ir_MWM.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_MWM.cpp + +ir_MWM_test.o : ir_MWM_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_MWM_test.cpp + +ir_MWM_test : $(COMMON_OBJ) ir_MWM_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Aiwa_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Aiwa_test.cpp similarity index 70% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Aiwa_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Aiwa_test.cpp index a0bb12f86..c5469d4a5 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Aiwa_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Aiwa_test.cpp @@ -20,8 +20,9 @@ TEST(TestSendAiwa, SendDataOnly) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520" + "m8960s2240m560s96320", + irsend.outputStr()); } // Test sending oversized data. @@ -40,7 +41,7 @@ TEST(TestSendAiwa, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 0); // No repeats. + irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 0); // No repeats. EXPECT_EQ( "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" @@ -48,9 +49,10 @@ TEST(TestSendAiwa, SendWithRepeats) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520", + irsend.outputStr()); irsend.reset(); - irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 1); // 1 repeat. + irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 1); // 1 repeat. EXPECT_EQ( "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" @@ -58,10 +60,11 @@ TEST(TestSendAiwa, SendWithRepeats) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520" + "m8960s2240m560s96320", + irsend.outputStr()); irsend.reset(); - irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 2); // 2 repeats. + irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 2); // 2 repeats. EXPECT_EQ( "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" @@ -69,13 +72,14 @@ TEST(TestSendAiwa, SendWithRepeats) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080" - "m8960s2240m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520" + "m8960s2240m560s96320" + "m8960s2240m560s96320", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendAiwa, SendUsualSize) { +TEST(TestSendAiwa, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); @@ -87,8 +91,9 @@ TEST(TestSendAiwa, SendUsualSize) { "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s1680m560s560m560s560" - "m560s1680m560s560m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s560m560s1680m560s36960" + "m8960s2240m560s96320", + irsend.outputStr()); irsend.reset(); irsend.sendAiwaRCT501(0x1234567890, 37); @@ -102,8 +107,9 @@ TEST(TestSendAiwa, SendUsualSize) { "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s1680" "m560s560m560s560m560s1680m560s560m560s560m560s560m560s560m560s1680" - "m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s22400" + "m8960s2240m560s96320", + irsend.outputStr()); } // Tests for decodeAiwaRCT501(). @@ -118,10 +124,9 @@ TEST(TestDecodeAiwa, NormalDecodeWithStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x7F); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -131,10 +136,9 @@ TEST(TestDecodeAiwa, NormalDecodeWithStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -144,10 +148,9 @@ TEST(TestDecodeAiwa, NormalDecodeWithStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x7FFF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7FFF, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -162,12 +165,11 @@ TEST(TestDecodeAiwa, NormalDecodeWithRepeatAndStrict) { // Normal Aiwa 15-bit(42bit) message with 2 repeats. irsend.reset(); - irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 2); + irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -182,48 +184,44 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictValues) { irsend.reset(); // Confirm using sendNEC(data, 42, 1) can make a legal Aiwa message. - irsend.sendNEC(0x1D8113F00FF, 42, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x1D8113F00FF, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // MUST pass with strict on. - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); ASSERT_EQ(0x7F, irsend.capture.value); irsend.reset(); // Use sendNEC(data, 42) to make/send an illegal value Aiwa message. // Value is illegal due to bad pre & post data. - irsend.sendNEC(0x1234567890A, 42, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x1234567890A, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should fail if strict off too. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); irsend.reset(); // Use sendNEC(data, 42) to make/send an illegal value Aiwa message. // Value is illegal due to bad post data only. - irsend.sendNEC(0x1D8113F00FE, 42, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x1D8113F00FE, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should fail if strict off too. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); irsend.reset(); // Use sendNEC(data, 42) to make/send an illegal value Aiwa message. // Value is illegal due to bad pre data only. - irsend.sendNEC(0x0D8113F00FF, 42, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x0D8113F00FF, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should fail if strict off too. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); } // Decode unsupported Aiwa messages. @@ -236,8 +234,7 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictSizes) { irsend.sendAiwaRCT501(0x0, 8); // Illegal size Aiwa 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 8, false)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); @@ -248,8 +245,7 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictSizes) { irsend.sendAiwaRCT501(0x12345678, 32); // Illegal size Aiwa 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should fail with strict when we ask for the wrong bit size. ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, 32, true)); @@ -278,7 +274,7 @@ TEST(TestDecodeAiwa, Decode64BitMessages) { // Reconfirm it by sending a true 64bit NEC message with the Aiwa prefix. irsend.reset(); - irsend.sendNEC(0x76044FFFFFFFFFFF, 64, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x76044FFFFFFFFFFF, 64, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 37, false)); @@ -295,20 +291,19 @@ TEST(TestDecodeAiwa, DecodeGlobalCacheExample) { irsend.reset(); // Aiwa Power Toggle from Global Cache. - uint16_t gc_test[95] = {38000, 1, 89, 342, 171, 21, 21, 21, 64, 21, 64, - 21, 64, 21, 21, 21, 64, 21, 64, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, - 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, - 21, 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 64, 21, 64, 21, 64, 21, 64, 21, 64, - 21, 64, 21, 64, 21, 64, 21, 875, 342, 171, 21, 3565}; + uint16_t gc_test[95] = { + 38000, 1, 89, 342, 171, 21, 21, 21, 64, 21, 64, 21, 64, 21, 21, 21, + 64, 21, 64, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, 21, + 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 64, 21, 64, 21, + 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 875, 342, 171, 21, 3565}; irsend.sendGC(gc_test, 95); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -326,13 +321,14 @@ TEST(TestDecodeAiwa, FailToDecodeNonAiwaExample) { irsend.begin(); irsend.reset(); - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp new file mode 100644 index 000000000..24bdc232a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp @@ -0,0 +1,225 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendCarrierAC() + +// Test sending typical data only. +TEST(TestSendCarrierAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendCarrierAC(0x0); + EXPECT_EQ( + "m8532s4228" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320" + "m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320" + "m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320" + "m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s20000", + irsend.outputStr()); + irsend.reset(); + irsend.sendCarrierAC(0x12345678); + EXPECT_EQ( + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s532m628s1320m628s1320m628s532m628s1320" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532m628s1320" + "m628s1320m628s532m628s532m628s532m628s532m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000", + irsend.outputStr()); + + irsend.reset(); + irsend.sendCarrierAC(0x4CCA541D); + EXPECT_EQ( + "m8532s4228" + "m628s532m628s1320m628s532m628s532m628s1320m628s1320m628s532m628s532" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s532m628s532m628s1320m628s1320m628s1320m628s532m628s1320" + "m628s20000" + "m8532s4228" + "m628s1320m628s532m628s1320m628s1320m628s532m628s532m628s1320m628s1320" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s1320m628s1320m628s532m628s532m628s532m628s1320m628s532" + "m628s20000" + "m8532s4228" + "m628s532m628s1320m628s532m628s532m628s1320m628s1320m628s532m628s532" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s532m628s532m628s1320m628s1320m628s1320m628s532m628s1320" + "m628s20000", + irsend.outputStr()); +} + +// Test sending typical data only. +TEST(TestSendCarrierAC, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendCarrierAC(0x12345678, kCarrierAcBits, 2); // two repeats. + EXPECT_EQ( + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s532m628s1320m628s1320m628s532m628s1320" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532m628s1320" + "m628s1320m628s532m628s532m628s532m628s532m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s532m628s1320m628s1320m628s532m628s1320" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532m628s1320" + "m628s1320m628s532m628s532m628s532m628s532m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s532m628s1320m628s1320m628s532m628s1320" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532m628s1320" + "m628s1320m628s532m628s532m628s532m628s532m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000", + irsend.outputStr()); +} + +// Tests for decodeCarrierAC(). + +// Decode normal "synthetic" messages. +TEST(TestDecodeCarrierAC, NormalDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendCarrierAC(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeCarrierAC(&irsend.capture, kCarrierAcBits, true)); + EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendCarrierAC(0xB335ABE2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeCarrierAC(&irsend.capture, kCarrierAcBits, true)); + EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); + EXPECT_EQ(0xB335ABE2, irsend.capture.value); + EXPECT_EQ(0xB335, irsend.capture.address); + EXPECT_EQ(0xABE2, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Do the last one again, & use the full decoder, not just protocol specific. + irsend.reset(); + irsend.sendCarrierAC(0xB335ABE2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); + EXPECT_EQ(0xB335ABE2, irsend.capture.value); +} + +// Decode a "real" example message. +TEST(TestDecodeCarrierAC, RealExamples) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #385 captured by gnkarn + uint16_t rawData[203] = { + 8532, 4216, 628, 1312, 628, 528, 628, 1312, 628, 1312, 628, 528, + 628, 524, 628, 1316, 624, 1316, 628, 524, 628, 528, 628, 1312, + 628, 1316, 624, 528, 628, 1312, 628, 528, 628, 1312, 628, 1312, + 628, 528, 628, 1316, 624, 528, 628, 1312, 628, 528, 628, 1312, + 628, 1316, 624, 1316, 628, 1312, 628, 1316, 628, 524, 628, 528, + 628, 528, 624, 1316, 628, 528, 628, 20064, 8504, 4228, 628, 528, + 628, 1312, 628, 528, 628, 528, 628, 1312, 628, 1316, 624, 532, + 624, 528, 628, 1316, 628, 1312, 628, 528, 628, 528, 628, 1312, + 628, 528, 628, 1316, 628, 528, 624, 528, 628, 1316, 628, 528, + 628, 1316, 624, 528, 628, 1316, 628, 528, 624, 532, 624, 528, + 628, 528, 628, 528, 628, 1316, 624, 1316, 628, 1316, 628, 528, + 624, 1316, 628, 20076, 8528, 4212, 624, 1316, 628, 528, 628, 1316, + 628, 1316, 624, 528, 628, 528, 628, 1316, 628, 1316, 628, 528, + 624, 532, 624, 1316, 628, 1316, 628, 528, 628, 1316, 624, 528, + 628, 1316, 628, 1316, 628, 528, 628, 1316, 624, 532, 624, 1316, + 628, 532, 624, 1316, 628, 1316, 624, 1320, 624, 1316, 628, 1316, + 628, 528, 628, 528, 628, 528, 628, 1316, 624, 532, 624}; + + irsend.sendRaw(rawData, 203, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); + EXPECT_EQ(0xB335ABE2, irsend.capture.value); + EXPECT_EQ(0xB335, irsend.capture.address); + EXPECT_EQ(0xABE2, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Coolix_test.cpp similarity index 60% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Coolix_test.cpp index 14eb8d661..8b096ffca 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Coolix_test.cpp @@ -1,5 +1,6 @@ -// Copyright 2017 David Conran +// Copyright 2017-2018 David Conran +#include "ir_Coolix.h" #include "IRsend.h" #include "IRsend_test.h" #include "gtest/gtest.h" @@ -21,7 +22,8 @@ TEST(TestSendCoolix, SendDataOnly) { "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); irsend.reset(); irsend.sendCOOLIX(0xAA55AA); @@ -33,7 +35,8 @@ TEST(TestSendCoolix, SendDataOnly) { "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); irsend.reset(); irsend.sendCOOLIX(0xFFFFFF); @@ -45,7 +48,8 @@ TEST(TestSendCoolix, SendDataOnly) { "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); } // Test sending with different repeats. @@ -54,7 +58,7 @@ TEST(TestSendCoolix, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendCOOLIX(0xAA55AA, COOLIX_BITS, 1); // 1 repeat. + irsend.sendCOOLIX(0xAA55AA, kCoolixBits, 1); // 1 repeat. EXPECT_EQ( "m4480s4480" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" @@ -71,8 +75,9 @@ TEST(TestSendCoolix, SendWithRepeats) { "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040", irsend.outputStr()); - irsend.sendCOOLIX(0xAA55AA, COOLIX_BITS, 2); // 2 repeats. + "m560s5040", + irsend.outputStr()); + irsend.sendCOOLIX(0xAA55AA, kCoolixBits, 2); // 2 repeats. EXPECT_EQ( "m4480s4480" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" @@ -97,11 +102,12 @@ TEST(TestSendCoolix, SendWithRepeats) { "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendCoolix, SendUsualSize) { +TEST(TestSendCoolix, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); @@ -111,7 +117,8 @@ TEST(TestSendCoolix, SendUsualSize) { "m4480s4480" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); irsend.reset(); irsend.sendCOOLIX(0x1234567890ABCDEF, 64); @@ -133,12 +140,13 @@ TEST(TestSendCoolix, SendUsualSize) { "m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" "m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); // Bit sizes must be a multiple of 8. irsend.reset(); irsend.sendCOOLIX(0x0, 17); - EXPECT_EQ("" , irsend.outputStr()); + EXPECT_EQ("", irsend.outputStr()); } // Tests for decodeCOOLIX(). @@ -153,9 +161,9 @@ TEST(TestDecodeCoolix, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCOOLIX(0x123456); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -165,9 +173,9 @@ TEST(TestDecodeCoolix, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCOOLIX(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -177,9 +185,9 @@ TEST(TestDecodeCoolix, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCOOLIX(0xFFFFFF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0xFFFFFF, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -194,24 +202,24 @@ TEST(TestDecodeCoolix, NormalDecodeWithRepeatAndStrict) { // Normal Coolix 16-bit message with 2 repeats. irsend.reset(); - irsend.sendCOOLIX(0x123456, COOLIX_BITS, 2); + irsend.sendCOOLIX(0x123456, kCoolixBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); EXPECT_FALSE(irsend.capture.repeat); - irsend.makeDecodeResult(4 * COOLIX_BITS + 4); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + irsend.makeDecodeResult(4 * kCoolixBits + 4); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); - irsend.makeDecodeResult(2 * (4 * COOLIX_BITS + 4)); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + irsend.makeDecodeResult(2 * (4 * kCoolixBits + 4)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); } @@ -225,7 +233,7 @@ TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { irsend.sendCOOLIX(0x12, 8); // Illegal value Coolix 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, 8, false)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); @@ -236,7 +244,7 @@ TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { irsend.sendCOOLIX(0x12345678, 32); // Illegal value Coolix 32-bit message. irsend.makeDecodeResult(); // Shouldn't pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -249,7 +257,7 @@ TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { // Decode should fail if asked to decode non-multiples of 8 bits. irsend.reset(); - irsend.sendCOOLIX(0x123456, COOLIX_BITS, 2); + irsend.sendCOOLIX(0x123456, kCoolixBits, 2); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, 9, false)); } @@ -279,12 +287,159 @@ TEST(TestDecodeCoolix, FailToDecodeNonCoolixExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, false)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, false)); +} + +// Tests for the IRCoolixAC class. + +TEST(TestCoolixACClass, SetAndGetRaw) { + IRCoolixAC ircoolix(0); + + ircoolix.setRaw(kCoolixOff); + EXPECT_EQ(kCoolixOff, ircoolix.getRaw()); + ircoolix.setRaw(kCoolixDefaultState); + EXPECT_EQ(kCoolixDefaultState, ircoolix.getRaw()); +} + +TEST(TestCoolixACClass, SetAndGetTemp) { + IRCoolixAC ircoolix(0); + + ircoolix.setTemp(25); + EXPECT_EQ(25, ircoolix.getTemp()); + ircoolix.setTemp(kCoolixTempMin); + EXPECT_EQ(kCoolixTempMin, ircoolix.getTemp()); + ircoolix.setTemp(kCoolixTempMax); + EXPECT_EQ(kCoolixTempMax, ircoolix.getTemp()); + ircoolix.setTemp(kCoolixTempMin - 1); + EXPECT_EQ(kCoolixTempMin, ircoolix.getTemp()); + ircoolix.setTemp(kCoolixTempMax + 1); + EXPECT_EQ(kCoolixTempMax, ircoolix.getTemp()); +} + +TEST(TestCoolixACClass, SetAndGetMode) { + IRCoolixAC ircoolix(0); + + ircoolix.setMode(kCoolixHeat); + EXPECT_EQ(kCoolixHeat, ircoolix.getMode()); + ircoolix.setMode(kCoolixCool); + EXPECT_EQ(kCoolixCool, ircoolix.getMode()); + ircoolix.setMode(kCoolixDry); + EXPECT_EQ(kCoolixDry, ircoolix.getMode()); + ircoolix.setMode(kCoolixAuto); + EXPECT_EQ(kCoolixAuto, ircoolix.getMode()); + ircoolix.setMode(kCoolixFan); + EXPECT_EQ(kCoolixFan, ircoolix.getMode()); +} + +TEST(TestCoolixACClass, SetAndGetFan) { + IRCoolixAC ircoolix(0); + + ircoolix.setFan(kCoolixFanMax); + EXPECT_EQ(kCoolixFanMax, ircoolix.getFan()); + ircoolix.setFan(kCoolixFanMin); + EXPECT_EQ(kCoolixFanMin, ircoolix.getFan()); + ircoolix.setFan(kCoolixFanZoneFollow); + EXPECT_EQ(kCoolixFanZoneFollow, ircoolix.getFan()); + ircoolix.setFan(kCoolixFanAuto); + EXPECT_EQ(kCoolixFanAuto, ircoolix.getFan()); + ircoolix.setFan(kCoolixFanMax); + EXPECT_EQ(kCoolixFanMax, ircoolix.getFan()); + ASSERT_NE(3, kCoolixFanAuto); + // Now try some unexpected value. + ircoolix.setFan(3); + EXPECT_EQ(kCoolixFanAuto, ircoolix.getFan()); +} + +TEST(TestCoolixACClass, SetGetClearSensorTempAndZoneFollow) { + IRCoolixAC ircoolix(0); + + ircoolix.setRaw(kCoolixDefaultState); + EXPECT_FALSE(ircoolix.getZoneFollow()); + EXPECT_LT(kCoolixSensorTempMax, ircoolix.getSensorTemp()); + + ircoolix.setSensorTemp(25); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(25, ircoolix.getSensorTemp()); + + // Lower bounds + ircoolix.setSensorTemp(kCoolixSensorTempMin); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(kCoolixSensorTempMin, ircoolix.getSensorTemp()); + ircoolix.setSensorTemp(kCoolixSensorTempMin - 1); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(kCoolixSensorTempMin, ircoolix.getSensorTemp()); + // Upper bounds + ircoolix.setSensorTemp(kCoolixSensorTempMax); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(kCoolixSensorTempMax, ircoolix.getSensorTemp()); + ircoolix.setSensorTemp(kCoolixSensorTempMax + 1); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(kCoolixSensorTempMax, ircoolix.getSensorTemp()); + // Clearing + ircoolix.clearSensorTemp(); + EXPECT_FALSE(ircoolix.getZoneFollow()); + EXPECT_LT(kCoolixSensorTempMax, ircoolix.getSensorTemp()); +} + +TEST(TestCoolixACClass, SpecialModesAndReset) { + IRCoolixAC ircoolix(0); + ASSERT_NE(kCoolixSwing, ircoolix.getRaw()); + ircoolix.setSwing(); + ASSERT_EQ(kCoolixSwing, ircoolix.getRaw()); + ircoolix.setTurbo(); + ASSERT_EQ(kCoolixTurbo, ircoolix.getRaw()); + ircoolix.setSleep(); + ASSERT_EQ(kCoolixSleep, ircoolix.getRaw()); + ircoolix.setLed(); + ASSERT_EQ(kCoolixLed, ircoolix.getRaw()); + ircoolix.setClean(); + ASSERT_EQ(kCoolixClean, ircoolix.getRaw()); + ircoolix.stateReset(); + ASSERT_NE(kCoolixClean, ircoolix.getRaw()); +} + +TEST(TestCoolixACClass, HumanReadable) { + IRCoolixAC ircoolix(0); + + // Initial starting point. + EXPECT_EQ( + "Power: On, Fan: 5 (AUTO), Mode: 2 (AUTO), Temp: 25C, " + "Zone Follow: Off, Sensor Temp: Ignored", + ircoolix.toString()); + + ircoolix.setSensorTemp(24); + ircoolix.setTemp(22); + ircoolix.setMode(kCoolixCool); + ircoolix.setFan(kCoolixFanMin); + EXPECT_EQ( + "Power: On, Fan: 4 (MIN), Mode: 0 (COOL), Temp: 22C, " + "Zone Follow: On, Sensor Temp: 24C", + ircoolix.toString()); + ircoolix.setSwing(); + EXPECT_EQ("Power: On, Fan: 3 (UNKNOWN), Swing: Toggle", ircoolix.toString()); + ircoolix.setPower(false); + EXPECT_EQ("Power: Off", ircoolix.toString()); +} + +TEST(TestCoolixACClass, KnownExamples) { + IRCoolixAC ircoolix(0); + + ircoolix.setRaw(0b101100101011111111100100); + EXPECT_EQ( + "Power: On, Fan: 5 (AUTO), Mode: 4 (FAN), Zone Follow: Off, " + "Sensor Temp: Ignored", + ircoolix.toString()); + ircoolix.setRaw(0b101100101001111100000000); + EXPECT_EQ( + "Power: On, Fan: 4 (MIN), Mode: 0 (COOL), Temp: 17C, " + "Zone Follow: Off, Sensor Temp: Ignored", + ircoolix.toString()); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp new file mode 100644 index 000000000..c8192fc82 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp @@ -0,0 +1,838 @@ +// Copyright 2017 David Conran +#include "ir_Daikin.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendDaikin(). + +// Test sending typical data only. +TEST(TestSendDaikin, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t daikin_code[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; + + irsend.reset(); + irsend.sendDaikin(daikin_code); + EXPECT_EQ( + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendDaikin, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t daikin_code[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; + irsend.reset(); + + irsend.sendDaikin(daikin_code, kDaikinStateLength, 1); + EXPECT_EQ( + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428" + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendDaikin, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t daikin_short_code[kDaikinStateLength - 1] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00}; + + irsend.reset(); + irsend.sendDaikin(daikin_short_code, kDaikinStateLength - 1); + ASSERT_EQ("", irsend.outputStr()); + + uint8_t daikin_long_code[kDaikinStateLength + 1] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, 0xDA, + 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3, 0x11}; + irsend.reset(); + irsend.sendDaikin(daikin_long_code, kDaikinStateLength + 1); + ASSERT_EQ( + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s29428", + irsend.outputStr()); +} + +// Tests for IRDaikinESP class. + +TEST(TestDaikinClass, Power) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.on(); + EXPECT_TRUE(irdaikin.getPower()); + + irdaikin.off(); + EXPECT_FALSE(irdaikin.getPower()); + + irdaikin.setPower(true); + EXPECT_TRUE(irdaikin.getPower()); + + irdaikin.setPower(false); + EXPECT_FALSE(irdaikin.getPower()); +} + +TEST(TestDaikinClass, Temperature) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setTemp(0); + EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp()); + + irdaikin.setTemp(255); + EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMinTemp); + EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMaxTemp); + EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMinTemp - 1); + EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMaxTemp + 1); + EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMinTemp + 1); + EXPECT_EQ(kDaikinMinTemp + 1, irdaikin.getTemp()); + + irdaikin.setTemp(21); + EXPECT_EQ(21, irdaikin.getTemp()); + + irdaikin.setTemp(25); + EXPECT_EQ(25, irdaikin.getTemp()); + + irdaikin.setTemp(29); + EXPECT_EQ(29, irdaikin.getTemp()); +} + +TEST(TestDaikinClass, OperatingMode) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setMode(kDaikinAuto); + EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); + + irdaikin.setMode(kDaikinCool); + EXPECT_EQ(kDaikinCool, irdaikin.getMode()); + + irdaikin.setMode(kDaikinHeat); + EXPECT_EQ(kDaikinHeat, irdaikin.getMode()); + + irdaikin.setMode(kDaikinDry); + EXPECT_EQ(kDaikinDry, irdaikin.getMode()); + + irdaikin.setMode(kDaikinFan); + EXPECT_EQ(kDaikinFan, irdaikin.getMode()); + + irdaikin.setMode(kDaikinFan + 1); + EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); + + irdaikin.setMode(kDaikinAuto + 1); + EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); + + irdaikin.setMode(255); + EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); +} + +TEST(TestDaikinClass, VaneSwing) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setSwingHorizontal(true); + irdaikin.setSwingVertical(false); + + irdaikin.setSwingHorizontal(true); + EXPECT_TRUE(irdaikin.getSwingHorizontal()); + EXPECT_FALSE(irdaikin.getSwingVertical()); + + irdaikin.setSwingVertical(true); + EXPECT_TRUE(irdaikin.getSwingHorizontal()); + EXPECT_TRUE(irdaikin.getSwingVertical()); + + irdaikin.setSwingHorizontal(false); + EXPECT_FALSE(irdaikin.getSwingHorizontal()); + EXPECT_TRUE(irdaikin.getSwingVertical()); + + irdaikin.setSwingVertical(false); + EXPECT_FALSE(irdaikin.getSwingHorizontal()); + EXPECT_FALSE(irdaikin.getSwingVertical()); +} + +TEST(TestDaikinClass, QuietMode) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setQuiet(true); + EXPECT_TRUE(irdaikin.getQuiet()); + + irdaikin.setQuiet(false); + EXPECT_FALSE(irdaikin.getQuiet()); + + irdaikin.setQuiet(true); + EXPECT_TRUE(irdaikin.getQuiet()); + + // Setting Econo mode should NOT change out of quiet mode. + irdaikin.setEcono(true); + EXPECT_TRUE(irdaikin.getQuiet()); + irdaikin.setEcono(false); + EXPECT_TRUE(irdaikin.getQuiet()); + + // But setting Powerful mode should exit out of quiet mode. + irdaikin.setPowerful(true); + EXPECT_FALSE(irdaikin.getQuiet()); +} + +TEST(TestDaikinClass, PowerfulMode) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setPowerful(true); + EXPECT_TRUE(irdaikin.getPowerful()); + + irdaikin.setPowerful(false); + EXPECT_FALSE(irdaikin.getPowerful()); + + irdaikin.setPowerful(true); + EXPECT_TRUE(irdaikin.getPowerful()); + + irdaikin.setQuiet(true); + EXPECT_FALSE(irdaikin.getPowerful()); + + irdaikin.setPowerful(true); + irdaikin.setEcono(true); + EXPECT_FALSE(irdaikin.getPowerful()); +} + +TEST(TestDaikinClass, EconoMode) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setEcono(true); + EXPECT_TRUE(irdaikin.getEcono()); + + irdaikin.setEcono(false); + EXPECT_FALSE(irdaikin.getEcono()); + + irdaikin.setEcono(true); + EXPECT_TRUE(irdaikin.getEcono()); + + // Setting Quiet mode should NOT change out of Econo mode. + irdaikin.setQuiet(true); + EXPECT_TRUE(irdaikin.getEcono()); + irdaikin.setQuiet(false); + EXPECT_TRUE(irdaikin.getEcono()); + + // But setting Powerful mode should exit out of Econo mode. + irdaikin.setPowerful(true); + EXPECT_FALSE(irdaikin.getEcono()); +} + +TEST(TestDaikinClass, FanSpeed) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + // Unexpected value should default to Auto. + irdaikin.setFan(0); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + // Unexpected value should default to Auto. + irdaikin.setFan(255); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanMax); + EXPECT_EQ(kDaikinFanMax, irdaikin.getFan()); + + // Beyond Max should default to Auto. + irdaikin.setFan(kDaikinFanMax + 1); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanMax - 1); + EXPECT_EQ(kDaikinFanMax - 1, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanMin); + EXPECT_EQ(kDaikinFanMin, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanMin + 1); + EXPECT_EQ(kDaikinFanMin + 1, irdaikin.getFan()); + + // Beyond Min should default to Auto. + irdaikin.setFan(kDaikinFanMin - 1); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + irdaikin.setFan(3); + EXPECT_EQ(3, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanAuto); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanQuiet); + EXPECT_EQ(kDaikinFanQuiet, irdaikin.getFan()); +} + +TEST(TestDaikinClass, CurrentTime) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setCurrentTime(0); // 00:00 + EXPECT_EQ(0, irdaikin.getCurrentTime()); + + irdaikin.setCurrentTime(754); // 12:34 + EXPECT_EQ(754, irdaikin.getCurrentTime()); + + irdaikin.setCurrentTime(1439); // 23:59 + EXPECT_EQ(1439, irdaikin.getCurrentTime()); +} + +TEST(TestDaikinClass, OnOffTimers) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + // Both timers turned off. + irdaikin.disableOnTimer(); + irdaikin.disableOffTimer(); + EXPECT_FALSE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOnTime()); + EXPECT_FALSE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOffTime()); + + // Turn on just the On Timer. + irdaikin.enableOnTimer(123); + EXPECT_TRUE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(123, irdaikin.getOnTime()); + EXPECT_FALSE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOffTime()); + + // Now turn on the Off Timer. + irdaikin.enableOffTimer(754); + EXPECT_TRUE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(754, irdaikin.getOffTime()); + EXPECT_TRUE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(123, irdaikin.getOnTime()); + + // Turn off the just the On Timer. + irdaikin.disableOnTimer(); + EXPECT_FALSE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOnTime()); + EXPECT_TRUE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(754, irdaikin.getOffTime()); + + // Now turn off the Off Timer. + irdaikin.disableOffTimer(); + EXPECT_FALSE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOffTime()); + EXPECT_FALSE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOnTime()); + + // Use some canary values around the timers to ensure no accidental + // bit flips happen. i.e. Neighbouring bytes in the state. + // (Found some during testing on systems with different endian-ness) + // Tests here to make sure it never happens again. + irdaikin.setSwingHorizontal(true); + irdaikin.setPowerful(true); + irdaikin.disableOffTimer(); + irdaikin.disableOnTimer(); + ASSERT_TRUE(irdaikin.getSwingHorizontal()); + ASSERT_TRUE(irdaikin.getPowerful()); + irdaikin.enableOnTimer(123); + irdaikin.enableOffTimer(456); + ASSERT_TRUE(irdaikin.getSwingHorizontal()); + ASSERT_TRUE(irdaikin.getPowerful()); + irdaikin.disableOffTimer(); + irdaikin.disableOnTimer(); + ASSERT_TRUE(irdaikin.getSwingHorizontal()); + ASSERT_TRUE(irdaikin.getPowerful()); + + irdaikin.setSwingHorizontal(false); + irdaikin.setPowerful(false); + irdaikin.disableOffTimer(); + irdaikin.disableOnTimer(); + ASSERT_FALSE(irdaikin.getSwingHorizontal()); + ASSERT_FALSE(irdaikin.getPowerful()); + irdaikin.enableOnTimer(123); + irdaikin.enableOffTimer(456); + ASSERT_FALSE(irdaikin.getSwingHorizontal()); + ASSERT_FALSE(irdaikin.getPowerful()); + irdaikin.disableOffTimer(); + irdaikin.disableOnTimer(); + ASSERT_FALSE(irdaikin.getSwingHorizontal()); + ASSERT_FALSE(irdaikin.getPowerful()); +} + +// Test Eye mode. +TEST(TestDaikinClass, EyeSetting) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + // The Eye setting is stored in the same byte as Econo mode. + // Econo mode tests are there to make sure it isn't harmed and vice-versa. + irdaikin.setEcono(false); + irdaikin.setEye(false); + ASSERT_FALSE(irdaikin.getEye()); + EXPECT_FALSE(irdaikin.getEcono()); + + irdaikin.setEye(true); + ASSERT_TRUE(irdaikin.getEye()); + EXPECT_FALSE(irdaikin.getEcono()); + + irdaikin.setEcono(false); + ASSERT_TRUE(irdaikin.getEye()); + EXPECT_FALSE(irdaikin.getEcono()); + + irdaikin.setEcono(true); + ASSERT_TRUE(irdaikin.getEye()); + EXPECT_TRUE(irdaikin.getEcono()); + + irdaikin.setEye(false); + ASSERT_FALSE(irdaikin.getEye()); + EXPECT_TRUE(irdaikin.getEcono()); +} + +// Test Mold mode. +TEST(TestDaikinClass, MoldSetting) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setMold(false); + ASSERT_FALSE(irdaikin.getMold()); + + irdaikin.setMold(true); + ASSERT_TRUE(irdaikin.getMold()); + + irdaikin.setMold(false); + ASSERT_FALSE(irdaikin.getMold()); +} + +// Test Sensor mode. +TEST(TestDaikinClass, SensorSetting) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setSensor(false); + ASSERT_FALSE(irdaikin.getSensor()); + + irdaikin.setSensor(true); + ASSERT_TRUE(irdaikin.getSensor()); + + irdaikin.setSensor(false); + ASSERT_FALSE(irdaikin.getSensor()); +} + +TEST(TestDaikinClass, RenderTime) { + EXPECT_EQ("0:00", IRDaikinESP::renderTime(0)); + EXPECT_EQ("0:10", IRDaikinESP::renderTime(10)); + EXPECT_EQ("1:00", IRDaikinESP::renderTime(1 * 60 + 0)); + EXPECT_EQ("23:59", IRDaikinESP::renderTime(23 * 60 + 59)); +} + +TEST(TestDaikinClass, SetAndGetRaw) { + IRDaikinESP irdaikin(0); + uint8_t initialState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x49, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x4F}; + uint8_t expectedState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x48, 0x2A, 0x00, 0xB0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x02, 0x5A}; + + EXPECT_STATE_EQ(initialState, irdaikin.getRaw(), kDaikinBits); + // toggle the power state. + irdaikin.setPower(!irdaikin.getPower()); + irdaikin.setTemp(21); + irdaikin.setMold(true); + EXPECT_STATE_EQ(expectedState, irdaikin.getRaw(), kDaikinBits); + irdaikin.setRaw(initialState); + EXPECT_STATE_EQ(initialState, irdaikin.getRaw(), kDaikinBits); +} + +TEST(TestDaikinClass, ChecksumValidation) { + uint8_t daikin_code[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE1}; + + EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code)); + // Change the array so the checksum is invalid. + daikin_code[0] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + // Restore the previous change, and change another byte. + daikin_code[0] ^= 0xFF; + daikin_code[4] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + daikin_code[4] ^= 0xFF; + // Change something in the 2nd block. + daikin_code[10] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + daikin_code[10] ^= 0xFF; + EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code)); +} + +// Test human readable output. +TEST(TestDaikinClass, HumanReadable) { + IRDaikinESP irdaikin(0); + + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 15C, Fan: 11 (QUIET), " + "Powerful: Off, Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, " + "Swing (Horizontal): Off, Swing (Vertical): Off, " + "Current Time: 0:00, On Time: Off, Off Time: Off", + irdaikin.toString()); + irdaikin.setMode(kDaikinAuto); + irdaikin.setTemp(25); + irdaikin.setFan(kDaikinFanAuto); + irdaikin.setQuiet(true); + irdaikin.setSensor(true); + irdaikin.setEye(true); + irdaikin.setMold(true); + irdaikin.setSwingVertical(true); + irdaikin.setSwingHorizontal(true); + irdaikin.setCurrentTime(9 * 60 + 15); + irdaikin.enableOnTimer(8 * 60 + 0); + irdaikin.enableOffTimer(17 * 60 + 30); + irdaikin.off(); + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 10 (AUTO), " + "Powerful: Off, Quiet: On, Sensor: On, Eye: On, Mold: On, " + "Swing (Horizontal): On, Swing (Vertical): On, " + "Current Time: 9:15, On Time: 8:00, Off Time: 17:30", + irdaikin.toString()); +} + +// Test general message construction after tweaking some settings. +TEST(TestDaikinClass, MessageConstuction) { + IRDaikinESP irdaikin(0); + IRsendTest irsend(4); + irdaikin.begin(); + irsend.begin(); + + irdaikin.setFan(kDaikinFanMin); + irdaikin.setMode(kDaikinCool); + irdaikin.setTemp(27); + irdaikin.setSwingVertical(false); + irdaikin.setSwingHorizontal(true); + irdaikin.setQuiet(false); + irdaikin.setPower(true); + + // Check everything for kicks. + EXPECT_EQ(kDaikinFanMin, irdaikin.getFan()); + EXPECT_EQ(kDaikinCool, irdaikin.getMode()); + EXPECT_EQ(27, irdaikin.getTemp()); + EXPECT_FALSE(irdaikin.getSwingVertical()); + EXPECT_TRUE(irdaikin.getSwingHorizontal()); + EXPECT_FALSE(irdaikin.getQuiet()); + EXPECT_TRUE(irdaikin.getPower()); + + irsend.reset(); + irsend.sendDaikin(irdaikin.getRaw()); + EXPECT_EQ( + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s1280m428s428m428s1280m428s428m428s1280m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s1280m428s1280m428s1280m428s428m428s428" + "m428s428m428s1280m428s1280m428s428m428s1280m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s428" + "m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s1280m428s1280m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s1280m428s1280m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428", + irsend.outputStr()); +} + +// Tests for decodeDaikin(). + +// Test decoding a message captured from a real IR remote. +TEST(TestDecodeDaikin, RealExample) { + IRDaikinESP irdaikin(0); + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t expectedState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, + 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; + uint16_t rawData[kDaikinRawBits] = { + 416, 446, 416, 446, 416, 446, 418, 446, 416, 446, 416, 25434, + 3436, 1768, 390, 1336, 390, 446, 416, 446, 416, 446, 416, 1336, + 390, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 448, + 416, 1336, 390, 1336, 390, 448, 416, 1336, 390, 1336, 390, 1338, + 388, 1338, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448, + 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, 416, 1336, + 390, 448, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 448, 416, 446, 416, 446, 416, 446, + 416, 448, 414, 448, 416, 448, 416, 1336, 390, 1336, 390, 1336, + 390, 446, 414, 1336, 390, 448, 414, 1336, 390, 1336, 390, 34878, + 3436, 1768, 390, 1336, 390, 446, 416, 448, 416, 446, 416, 1336, + 390, 446, 416, 448, 416, 446, 416, 446, 416, 1336, 390, 446, + 416, 1336, 390, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336, + 390, 1336, 390, 1336, 392, 446, 414, 448, 416, 1336, 390, 446, + 416, 446, 416, 446, 416, 446, 414, 448, 416, 446, 416, 448, + 414, 448, 416, 446, 416, 446, 416, 446, 414, 1336, 390, 448, + 416, 446, 416, 446, 416, 448, 416, 1336, 390, 446, 416, 446, + 416, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336, 390, 446, + 416, 446, 414, 1338, 390, 446, 416, 1336, 390, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446, + 416, 446, 416, 1336, 390, 446, 416, 446, 416, 1336, 390, 34876, + 3436, 1768, 388, 1336, 390, 446, 416, 446, 416, 448, 416, 1336, + 390, 446, 416, 446, 416, 446, 416, 448, 416, 1336, 390, 448, + 414, 1336, 390, 1336, 390, 446, 416, 1336, 388, 1338, 388, 1336, + 390, 1336, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446, + 420, 442, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448, + 416, 446, 416, 448, 416, 446, 416, 448, 416, 446, 416, 1336, + 390, 1336, 390, 1336, 388, 1338, 390, 1336, 390, 1336, 392, 446, + 416, 446, 416, 448, 416, 1334, 390, 446, 416, 1338, 388, 1336, + 390, 1336, 390, 446, 416, 446, 416, 448, 414, 446, 416, 446, + 416, 446, 416, 448, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, + 416, 1336, 390, 446, 414, 448, 416, 446, 416, 446, 416, 446, + 416, 448, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, + 416, 1336, 390, 446, 416, 446, 416, 446, 416, 448, 416, 1338, + 390, 444, 418, 1336, 390, 448, 416, 446, 416, 1336, 390, 446, + 416, 446, 416, 1336, 390, 1336, 388, 1336, 390, 446, 416, 1336, + 390, 448, 414, 448, 414, 448, 416, 1334, 390, 446, 416, 446, + 416, 446, 416, 448, 416, 446, 416, 446, 416, 448, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 448, 416, 1336, 390, 1336, 390, 446, 416, 446, 416, 446, + 416, 446, 414, 446, 416, 448, 416, 446, 416, 448, 414, 446, + 418, 446, 416, 446, 416, 448, 416, 446, 416, 448, 416, 446, + 416, 448, 416, 446, 416, 1336, 390, 446, 416, 446, 416, 1338, + 390, 1336, 390, 446, 416, 446, 416}; // Captured by @sillyfrog + + irsend.reset(); + irsend.sendRaw(rawData, kDaikinRawBits, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN, irsend.capture.decode_type); + ASSERT_EQ(kDaikinBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeDaikin, SyntheticExample) { + IRDaikinESP irdaikin(0); + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t expectedState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, + 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; + + irsend.reset(); + irsend.sendDaikin(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN, irsend.capture.decode_type); + ASSERT_EQ(kDaikinBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Denon_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Denon_test.cpp similarity index 82% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Denon_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Denon_test.cpp index 32de11b46..911fd7528 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Denon_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Denon_test.cpp @@ -19,7 +19,8 @@ TEST(TestSendDenon, SendDataOnly) { "m260s43602" "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.reset(); // Denon Eco Mode On. (Panasonic/Kaseikyo) @@ -32,7 +33,8 @@ TEST(TestSendDenon, SendDataOnly) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600", irsend.outputStr()); + "m432s98928", + irsend.outputStr()); } // Test sending with different repeats. @@ -54,7 +56,8 @@ TEST(TestSendDenon, SendNormalWithRepeats) { "m260s43602" "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.sendDenon(0x2278, DENON_BITS, 2); // 2 repeats. EXPECT_EQ( "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" @@ -74,7 +77,8 @@ TEST(TestSendDenon, SendNormalWithRepeats) { "m260s43602" "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } TEST(TestSendDenon, Send48BitWithRepeats) { @@ -91,7 +95,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600" + "m432s98928" "m3456s1728" "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" @@ -99,7 +103,8 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600", irsend.outputStr()); + "m432s98928", + irsend.outputStr()); irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS, 2); // 2 repeats. EXPECT_EQ( "m3456s1728" @@ -109,7 +114,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600" + "m432s98928" "m3456s1728" "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" @@ -117,7 +122,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600" + "m432s98928" "m3456s1728" "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" @@ -125,7 +130,8 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600", irsend.outputStr()); + "m432s98928", + irsend.outputStr()); } // Test sending an atypical data size. @@ -139,7 +145,8 @@ TEST(TestSendDenon, SendUnusualSize) { "m260s780m260s780m260s780m260s1820m260s780m260s780m260s1820m260s780" "m260s43602" "m260s1820m260s1820m260s1820m260s780m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.reset(); irsend.sendDenon(0x1234567890ABCDEF, 64); @@ -153,7 +160,8 @@ TEST(TestSendDenon, SendUnusualSize) { "m432s1296m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296" "m432s1296m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s1296m432s1296" - "m432s129600", irsend.outputStr()); + "m432s74736", + irsend.outputStr()); } // Tests for decodeDenon(). @@ -179,12 +187,12 @@ TEST(TestDecodeDenon, NormalDecodeWithStrict) { // Legacy Denon 14-bit message. irsend.reset(); - irsend.sendDenon(0x1278, DENON_LEGACY_BITS); + irsend.sendDenon(0x1278, kDenonLegacyBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_LEGACY_BITS, true)); + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenonLegacyBits, true)); EXPECT_EQ(DENON, irsend.capture.decode_type); - EXPECT_EQ(DENON_LEGACY_BITS, irsend.capture.bits); + EXPECT_EQ(kDenonLegacyBits, irsend.capture.bits); EXPECT_EQ(0x1278, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -211,13 +219,11 @@ TEST(TestDecodeDenon, DecodeGlobalCacheExample) { irsend.reset(); // Denon AVR series Power On code from Global Cache. (Sharp style) - uint16_t gc_test_power[67] = {38000, 1, 1, - 10, 30, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, - 10, 30, 10, 30, 10, 70, 10, 70, 10, 70, 10, 70, - 10, 30, 10, 30, 10, 30, 10, 1657, - 10, 30, 10, 70, 10, 30, 10, 30, 10, 30, 10, 30, - 10, 70, 10, 70, 10, 30, 10, 30, 10, 30, 10, 30, - 10, 70, 10, 70, 10, 70, 10, 1657}; + uint16_t gc_test_power[67] = { + 38000, 1, 1, 10, 30, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, + 10, 30, 10, 70, 10, 70, 10, 70, 10, 70, 10, 30, 10, 30, 10, 30, 10, + 1657, 10, 30, 10, 70, 10, 30, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, + 10, 30, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, 10, 70, 10, 1657}; irsend.sendGC(gc_test_power, 67); irsend.makeDecodeResult(); @@ -230,15 +236,14 @@ TEST(TestDecodeDenon, DecodeGlobalCacheExample) { EXPECT_FALSE(irsend.capture.repeat); // Denon "Eco Mode Auto" code from Global Cache. (Panasonic style) - uint16_t gc_test_eco[103] = {37000, 1, 1, 128, 64, 16, 16, 16, 16, 16, 48, - 16, 16, 16, 48, 16, 16, 16, 48, 16, 16, 16, 16, - 16, 48, 16, 16, 16, 16, 16, 48, 16, 48, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 48, 16, 16, 16, 48, 16, 16, 16, 16, - 16, 16, 16, 48, 16, 48, 16, 16, 16, 48, 16, 16, - 16, 48, 16, 48, 16, 16, 16, 48, 16, 48, 16, 16, - 16, 16, 16, 48, 16, 48, 16, 48, 16, 16, 16, 16, - 16, 16, 16, 48, 16, 48, 16, 2766}; + uint16_t gc_test_eco[103] = { + 37000, 1, 1, 128, 64, 16, 16, 16, 16, 16, 48, 16, 16, 16, 48, + 16, 16, 16, 48, 16, 16, 16, 16, 16, 48, 16, 16, 16, 16, 16, + 48, 16, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 48, 16, 16, 16, 48, 16, 16, 16, 16, 16, + 16, 16, 48, 16, 48, 16, 16, 16, 48, 16, 16, 16, 48, 16, 48, + 16, 16, 16, 48, 16, 48, 16, 16, 16, 16, 16, 48, 16, 48, 16, + 48, 16, 16, 16, 16, 16, 16, 16, 48, 16, 48, 16, 2766}; irsend.reset(); irsend.sendGC(gc_test_eco, 103); irsend.makeDecodeResult(); @@ -259,14 +264,15 @@ TEST(TestDecodeDenon, FailToDecodeNonDenonExample) { irsend.begin(); irsend.reset(); - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, DENON_LEGACY_BITS, false)); + ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kDenonLegacyBits, false)); ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, DENON_BITS, false)); ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, DENON_48_BITS, false)); } diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Dish_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Dish_test.cpp similarity index 76% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Dish_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Dish_test.cpp index afd76e8fd..0c58496ce 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Dish_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Dish_test.cpp @@ -26,7 +26,8 @@ TEST(TestSendDish, SendDataOnly) { "m400s6100" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); irsend.reset(); irsend.sendDISH(0x9C00); // Power on. @@ -43,7 +44,8 @@ TEST(TestSendDish, SendDataOnly) { "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); irsend.reset(); irsend.sendDISH(0xFFFF); @@ -60,7 +62,8 @@ TEST(TestSendDish, SendDataOnly) { "m400s6100" "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); } // Test sending with different repeats. @@ -69,15 +72,16 @@ TEST(TestSendDish, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendDISH(0x9C00, DISH_BITS, 0); // 0 repeats. + irsend.sendDISH(0x9C00, kDishBits, 0); // 0 repeats. EXPECT_EQ( "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); irsend.reset(); - irsend.sendDISH(0x9C00, DISH_BITS, 1); // 1 repeat. + irsend.sendDISH(0x9C00, kDishBits, 1); // 1 repeat. EXPECT_EQ( "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" @@ -85,9 +89,10 @@ TEST(TestSendDish, SendWithRepeats) { "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); - irsend.sendDISH(0x9C00, DISH_BITS, 2); // 2 repeats. + irsend.sendDISH(0x9C00, kDishBits, 2); // 2 repeats. EXPECT_EQ( "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" @@ -98,7 +103,8 @@ TEST(TestSendDish, SendWithRepeats) { "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); } // Test sending an atypical data size. @@ -109,15 +115,16 @@ TEST(TestSendDish, SendUnusualSize) { irsend.reset(); irsend.sendDISH(0x0, 8); EXPECT_EQ( - "m400s6100" - "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100" - "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100" - "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100" - "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100", + irsend.outputStr()); irsend.reset(); irsend.sendDISH(0x1234567890ABCDEF, 64); @@ -158,7 +165,8 @@ TEST(TestSendDish, SendUnusualSize) { "m400s1700m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700" "m400s1700m400s1700m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700" "m400s1700m400s1700m400s1700m400s2800m400s1700m400s1700m400s1700m400s1700" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); } // Tests for decodeDISH(). @@ -173,9 +181,9 @@ TEST(TestDecodeDish, NormalDecodeWithStrict) { irsend.reset(); irsend.sendDISH(0x9C00); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); + EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -192,7 +200,7 @@ TEST(TestDecodeDish, DecodeWithNonStrictSize) { irsend.sendDISH(0x12, 8); // Illegal size Dish message. (smaller) irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -209,7 +217,7 @@ TEST(TestDecodeDish, DecodeWithNonStrictSize) { irsend.sendDISH(0x12345678, 32); // Illegal size Dish message. (larger) irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -247,47 +255,45 @@ TEST(TestDecodeDish, DecodeGlobalCacheExample) { IRrecv irrecv(4); irsend.begin(); -/* - irsend.reset(); - // Dish DTV Pal code from Global Cache. - uint16_t gc_test_dtv[27] = {58000, 1, 3, 22, 538, 22, 252, 22, 156, 22, 156, - 22, 156, 22, 156, 22, 252, 22, 252, 22, 252, 22, - 252, 22, 252, 22, 538}; - irsend.sendGC(gc_test_dtv, 27); - irsend.makeDecodeResult(); + /* + irsend.reset(); + // Dish DTV Pal code from Global Cache. + uint16_t gc_test_dtv[27] = {58000, 1, 3, 22, 538, 22, 252, 22, 156, 22, 156, + 22, 156, 22, 156, 22, 252, 22, 252, 22, 252, 22, + 252, 22, 252, 22, 538}; + irsend.sendGC(gc_test_dtv, 27); + irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); - EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); + EXPECT_EQ(DISH, irsend.capture.decode_type); + EXPECT_EQ(kDishBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture)); - EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -*/ + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture)); + EXPECT_EQ(DISH, irsend.capture.decode_type); + EXPECT_EQ(kDishBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + */ // Dish Hopper 3 code from Global Cache. - uint16_t gc_test_hopper[73] = {58000, 1, 37, 23, 351, 23, 94, 23, 164, - 23, 164, 23, 94, 23, 94, 23, 94, 23, 164, - 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, - 23, 164, 23, 164, 23, 164, 23, 164, 23, 351, - 23, 94, 23, 164, 23, 164, 23, 94, 23, 94, - 23, 94, 23, 164, 23, 164, 23, 164, 23, 164, - 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, - 23, 164, 23, 351}; + uint16_t gc_test_hopper[73] = { + 58000, 1, 37, 23, 351, 23, 94, 23, 164, 23, 164, 23, 94, 23, 94, 23, + 94, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, + 164, 23, 164, 23, 164, 23, 351, 23, 94, 23, 164, 23, 164, 23, 94, 23, + 94, 23, 94, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, + 164, 23, 164, 23, 164, 23, 164, 23, 351}; irsend.reset(); irsend.sendGC(gc_test_hopper, 73); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); + EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -295,7 +301,7 @@ TEST(TestDecodeDish, DecodeGlobalCacheExample) { ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture)); EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); + EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -310,12 +316,13 @@ TEST(TestDecodeDish, FailToDecodeNonDishExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, false)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kDishBits, false)); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp new file mode 100644 index 000000000..df5dd7a5c --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp @@ -0,0 +1,98 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendElectraAC(). + +// Test sending typical data only. +TEST(TestSendElectraAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + uint8_t data[kElectraAcStateLength] = {0xC3, 0xE1, 0x6F, 0x14, 0x06, + 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0xA0, 0xB0}; + + irsend.sendElectraAC(data); + EXPECT_EQ( + "m9166s4470" + "m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647m646s1647" + "m646s1647m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647" + "m646s547m646s1647m646s1647m646s547m646s1647m646s1647m646s1647m646s1647" + "m646s547m646s547m646s547m646s1647m646s547m646s1647m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s1647m646s1647m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s1647m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s1647m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547" + "m646s1647m646s547m646s1647m646s547m646s547m646s547m646s547m646s547" + "m646s1647m646s547m646s1647m646s1647m646s547m646s547m646s547m646s547" + "m646s100000", + irsend.outputStr()); +} + +// Tests for decodeElectraAC(). +// Decode normal ElectraAC messages. + +TEST(TestDecodeElectraAC, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Synthesised Normal ElectraAC message. + irsend.reset(); + uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0xE1, 0x6F, 0x14, 0x06, + 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0xA0, 0xB0}; + irsend.sendElectraAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(ELECTRA_AC, irsend.capture.decode_type); + EXPECT_EQ(kElectraAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a recorded example +TEST(TestDecodeElectraAC, RealExampleDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real ElectraAC message. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/527 + uint16_t rawData[211] = { + 9166, 4470, 642, 1632, 642, 1632, 668, 534, 666, 534, 668, 534, + 614, 536, 640, 1636, 640, 1646, 694, 1662, 612, 1628, 642, 1666, + 664, 532, 668, 534, 666, 534, 666, 532, 666, 1644, 642, 532, + 640, 1634, 668, 1632, 642, 538, 666, 1660, 610, 1666, 664, 1632, + 642, 1672, 610, 536, 666, 534, 694, 532, 666, 1636, 614, 538, + 666, 1632, 642, 536, 666, 544, 692, 534, 640, 558, 640, 534, + 640, 540, 666, 534, 638, 1666, 638, 1636, 640, 550, 666, 534, + 640, 540, 666, 534, 640, 540, 666, 536, 638, 540, 666, 536, + 638, 550, 664, 536, 638, 540, 664, 536, 638, 540, 666, 534, + 638, 1640, 664, 536, 692, 546, 664, 536, 664, 536, 664, 536, + 664, 546, 612, 532, 636, 538, 664, 536, 664, 546, 612, 538, + 638, 538, 638, 538, 664, 536, 690, 538, 662, 538, 664, 538, + 662, 548, 664, 536, 662, 538, 662, 562, 638, 564, 636, 564, + 636, 1668, 582, 556, 652, 572, 612, 568, 636, 564, 610, 570, + 636, 556, 616, 550, 656, 566, 610, 570, 632, 578, 608, 1640, + 662, 562, 642, 1686, 582, 570, 634, 566, 604, 576, 636, 566, + 610, 578, 634, 1664, 584, 590, 660, 1636, 610, 1642, 664, 590, + 610, 590, 636, 566, 634, 568, 686}; // UNKNOWN 9AD8CDB5 + uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0xE1, 0x6F, 0x14, 0x06, + 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0xA0, 0xB0}; + + irsend.reset(); + irsend.sendRaw(rawData, 211, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(ELECTRA_AC, irsend.capture.decode_type); + EXPECT_EQ(kElectraAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp new file mode 100644 index 000000000..23fa3e7a7 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp @@ -0,0 +1,555 @@ +// Copyright 2017 Jonny Graham, David Conran + +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "ir_Fujitsu.h" +#include "gtest/gtest.h" + +template +::testing::AssertionResult ArraysMatch(const T (&expected)[size], + const T* actual) { + for (size_t i(0); i < size; ++i) { + if (expected[i] != actual[i]) { + int e = expected[i]; + int a = actual[i]; + return ::testing::AssertionFailure() << "array[" << i + << "] (" << std::hex << a << std::dec << ") != expected[" << i + << "] (" << std::hex << e << std::dec << ")"; + } + } + return ::testing::AssertionSuccess(); +} +// Tests for Fujitsu A/C methods. + +// Test sending typical data only. +TEST(TestIRFujitsuACClass, GetRawDefault) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); // AR-RAH2E + fujitsu.setCmd(kFujitsuAcCmdTurnOn); + fujitsu.setSwing(kFujitsuAcSwingBoth); + fujitsu.setMode(kFujitsuAcModeCool); + fujitsu.setFanSpeed(kFujitsuAcFanHigh); + fujitsu.setTemp(24); + uint8_t expected_arrah2e[16] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); + + uint8_t expected_ardb1[15] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x1D}; + fujitsu.setModel(ARDB1); + EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawTurnOff) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.setModel(ARRAH2E); + fujitsu.off(); + uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort, fujitsu.getStateLength()); + EXPECT_EQ("Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); + + fujitsu.setModel(ARDB1); + uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawStepHoriz) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.stepHoriz(); + uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x79, 0x86}; + EXPECT_TRUE(ArraysMatch(expected, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: Step vane horizontally", + fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawStepVert) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.setModel(ARRAH2E); + fujitsu.stepVert(); + uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C, 0x93}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: Step vane vertically", + fujitsu.toString()); + + fujitsu.setModel(ARDB1); + fujitsu.stepVert(); + uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort - 1, + fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: Step vane vertically", + fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.setCmd(kFujitsuAcCmdStayOn); + fujitsu.setSwing(kFujitsuAcSwingHoriz); + fujitsu.setMode(kFujitsuAcModeCool); + fujitsu.setFanSpeed(kFujitsuAcFanQuiet); + fujitsu.setTemp(25); + uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, + 0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB}; + EXPECT_TRUE(ArraysMatch(expected, fujitsu.getRaw())); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 25C, Fan: 4 (QUIET), " + "Swing: Horiz, Command: N/A", + fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawWithFan) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.setCmd(kFujitsuAcCmdStayOn); + fujitsu.setSwing(kFujitsuAcSwingHoriz); + fujitsu.setMode(kFujitsuAcModeFan); + fujitsu.setFanSpeed(kFujitsuAcFanMed); + fujitsu.setTemp(20); // temp doesn't matter for fan + // but it is sent by the RC anyway + fujitsu.setModel(ARRAH2E); + uint8_t expected_arrah2e[16] = { + 0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, + 0x40, 0x3, 0x22, 0x0, 0x0, 0x0, 0x20, 0x4B}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 3 (FAN), Temp: 20C, Fan: 2 (MED), Swing: Horiz, " + "Command: N/A", fujitsu.toString()); + + fujitsu.setModel(ARDB1); + uint8_t expected_ardb1[15] = { + 0x14, 0x63, 0x0, 0x10, 0x10, 0xFC, 0x8, 0x30, + 0x40, 0x3, 0x22, 0x0, 0x0, 0x0, 0x6B}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 3 (FAN), Temp: 20C, Fan: 2 (MED), Swing: Horiz, " + "Command: N/A", fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, SetRaw) { + IRFujitsuAC fujitsu = IRFujitsuAC(0); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + uint8_t expected_default_arrah2e[kFujitsuAcStateLength] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD}; + EXPECT_TRUE(ArraysMatch(expected_default_arrah2e, fujitsu.getRaw())); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); + // Now set a new state via setRaw(); + // This state is a real state from an AR-DB1 remote. + uint8_t new_state1[kFujitsuAcStateLength - 1] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9F}; + fujitsu.setRaw(new_state1, kFujitsuAcStateLength - 1); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_TRUE(ArraysMatch(new_state1, fujitsu.getRaw())); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 0 (AUTO), " + "Swing: Off, Command: N/A", fujitsu.toString()); +} + +TEST(TestSendFujitsuAC, GenerateMessage) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + IRsendTest irsend(4); + fujitsu.begin(); + irsend.begin(); + + fujitsu.setCmd(kFujitsuAcCmdStayOn); + fujitsu.setSwing(kFujitsuAcSwingBoth); + fujitsu.setMode(kFujitsuAcModeCool); + fujitsu.setFanSpeed(kFujitsuAcFanHigh); + fujitsu.setTemp(24); + + EXPECT_EQ(kFujitsuAcFanHigh, fujitsu.getFanSpeed()); + EXPECT_EQ(kFujitsuAcModeCool, fujitsu.getMode()); + EXPECT_EQ(24, fujitsu.getTemp()); + EXPECT_EQ(kFujitsuAcSwingBoth, fujitsu.getSwing()); + EXPECT_EQ(kFujitsuAcCmdStayOn, fujitsu.getCmd()); + + irsend.reset(); + irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLength); + EXPECT_EQ( + "m3324s1574" + "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390" + "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" + "m448s1182m448s390m448s390m448s1182m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s1182" + "m448s1182m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s390" + "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" + "m448s8100", + irsend.outputStr()); +} + +TEST(TestSendFujitsuAC, GenerateShortMessage) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + IRsendTest irsend(4); + fujitsu.begin(); + irsend.begin(); + + fujitsu.off(); + + EXPECT_EQ(kFujitsuAcCmdTurnOff, fujitsu.getCmd()); + + irsend.reset(); + irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLengthShort); + EXPECT_EQ( + "m3324s1574m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448" + "s390m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s1182m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s1182m448" + "s1182m448s1182m448s1182m448s1182m448s1182m448s8100", + irsend.outputStr()); +} + +// Issue #275 +TEST(TestSendFujitsuAC, Issue275) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + IRsendTest irsend(4); + fujitsu.begin(); + irsend.begin(); + irsend.reset(); + + fujitsu.setCmd(kFujitsuAcCmdTurnOff); + irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLengthShort); + EXPECT_EQ( + // Header + "m3324s1574" + // 0 0 1 0 1 0 0 0 (0x28) + "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390" + // 1 1 0 0 0 1 1 0 (0xC6) + "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" + // 0 0 0 0 0 0 0 0 (0x00) + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + // 0 0 0 0 1 0 0 0 (0x08) + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + // 0 0 0 0 1 0 0 0 (0x08) + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + // 0 1 0 0 0 0 0 0 (0x40) + "m448s390m448s1182m448s390m448s390m448s390m448s390m448s390m448s390" + // 1 0 1 1 1 1 1 1 (0xBF) + "m448s1182m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" + // Footer + "m448s8100", irsend.outputStr()); + + irsend.reset(); + // Per report in Issue #275 + uint16_t off[115] = { + 3350, 1650, + 450, 400, 450, 450, 450, 1250, 450, 400, 450, 1250, 450, 400, 450, 400, + 450, 400, 450, 1250, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 1250, + 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, + 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, + 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, + 450, 400, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250, + 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250, + 450, 400, 450, 1250, 450, 1250, 450, 1250, 450, 1250, 450, 1250, + 450, 1250, 450}; + irsend.sendRaw(off, 115, 38); + EXPECT_EQ( + // Header + "m3350s1650" + // 0 0 1 0 1 0 0 0 (0x28) + "m450s400m450s450m450s1250m450s400m450s1250m450s400m450s400m450s400" + // 1 1 0 0 0 1 1 0 (0xC6) + "m450s1250m450s1250m450s400m450s400m450s400m450s1250m450s1250m450s400" + // 0 0 0 0 0 0 0 0 (0x00) + "m450s400m450s400m450s400m450s400m450s400m450s400m450s400m450s400" + // 0 0 0 0 1 0 0 0 (0x08) + "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400" + // 0 0 0 0 1 0 0 0 (0x08) + "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400" + // 0 1 0 0 0 0 0 0 (0x40) + "m450s400m450s1250m450s400m450s400m450s400m450s400m450s400m450s400" + // 1 0 1 1 1 1 1 1 (0xBF) + "m450s1250m450s400m450s1250m450s1250m450s1250m450s1250m450s1250m450s1250" + // Footer + "m450", + irsend.outputStr()); +} + +TEST(TestDecodeFujitsuAC, SyntheticShortMessages) { + IRsendTest irsend(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + IRrecv irrecv(0); + + irsend.begin(); + irsend.reset(); + + fujitsu.setModel(ARRAH2E); + fujitsu.setCmd(kFujitsuAcCmdTurnOff); + irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength()); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcMinBits + 8, irsend.capture.bits); + uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, irsend.capture.state)); + + irsend.reset(); + + fujitsu.setModel(ARDB1); + fujitsu.setCmd(kFujitsuAcCmdTurnOff); + irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength()); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcMinBits, irsend.capture.bits); + uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, irsend.capture.state)); +} + +TEST(TestDecodeFujitsuAC, SyntheticLongMessages) { + IRsendTest irsend(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + + fujitsu.setModel(ARRAH2E); + fujitsu.setCmd(kFujitsuAcCmdStayOn); + fujitsu.setSwing(kFujitsuAcSwingVert); + fujitsu.setMode(kFujitsuAcModeCool); + fujitsu.setFanSpeed(kFujitsuAcFanQuiet); + fujitsu.setTemp(18); + irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength()); + ASSERT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeFujitsuAC(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits); + uint8_t expected_arrah2e[kFujitsuAcStateLength] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x20, 0x01, 0x14, 0x00, 0x00, 0x00, 0x20, 0x7B}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 4 (QUIET), " + "Swing: Vert, Command: N/A", fujitsu.toString()); + + irsend.reset(); + + fujitsu.setModel(ARDB1); + irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength()); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits); + uint8_t expected_ardb1[kFujitsuAcStateLength - 1] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x20, 0x01, 0x14, 0x00, 0x00, 0x00, 0x9B}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 4 (QUIET), " + "Swing: Vert, Command: N/A", fujitsu.toString()); +} + +TEST(TestDecodeFujitsuAC, RealShortARDB1OffExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + + irsend.begin(); + + irsend.reset(); + // "Off" Message recorded from an AR-DB1 remote. + uint16_t rawData[99] = { + 3310, 1636, 440, 386, 440, 394, 442, 1210, 442, 390, 414, 1220, + 444, 390, 446, 380, 446, 380, 436, 1216, 438, 1214, 438, 388, + 438, 386, 438, 396, 410, 1222, 440, 1220, 442, 384, 442, 384, + 442, 384, 442, 382, 444, 382, 442, 382, 444, 380, 446, 380, + 446, 380, 444, 380, 436, 390, 436, 388, 436, 388, 438, 1214, + 438, 386, 438, 388, 438, 386, 440, 386, 440, 384, 442, 384, + 442, 384, 442, 1210, 444, 382, 444, 382, 444, 382, 444, 380, + 446, 1206, 436, 390, 436, 388, 436, 388, 438, 388, 438, 396, + 420, 388, 436}; + irsend.sendRaw(rawData, 99, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcMinBits, irsend.capture.bits); + uint8_t expected[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02}; + EXPECT_TRUE(ArraysMatch(expected, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLengthShort - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), " + "Swing: Off, Command: N/A", fujitsu.toString()); +} + +TEST(TestDecodeFujitsuAC, RealLongARDB1Example) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + + irsend.begin(); + irsend.reset(); + uint16_t rawData1[243] = { + 3316, 1632, 444, 390, 438, 388, 436, 1216, 438, 388, 438, 1214, + 438, 388, 438, 386, 440, 386, 440, 1212, 440, 1210, 442, 392, + 412, 396, 442, 392, 444, 1208, 444, 1208, 444, 380, 444, 380, + 446, 380, 436, 390, 436, 390, 436, 390, 436, 388, 438, 388, + 438, 388, 438, 388, 438, 386, 438, 386, 440, 384, 440, 1210, + 442, 384, 442, 382, 442, 384, 442, 384, 442, 382, 442, 382, + 444, 382, 444, 1208, 444, 382, 444, 380, 446, 380, 436, 390, + 436, 390, 436, 1214, 438, 1214, 438, 1212, 440, 1212, 440, 1220, + 412, 1222, 440, 394, 442, 382, 442, 382, 444, 1208, 444, 382, + 444, 380, 446, 380, 446, 380, 434, 390, 436, 388, 438, 388, + 438, 388, 438, 1214, 438, 1212, 440, 386, 440, 394, 412, 1222, + 440, 394, 442, 384, 442, 384, 442, 382, 442, 1208, 444, 390, + 414, 394, 442, 1216, 446, 380, 436, 390, 436, 390, 436, 388, + 436, 390, 436, 388, 438, 386, 440, 386, 440, 386, 438, 1212, + 440, 386, 440, 384, 440, 384, 442, 392, 412, 396, 440, 394, + 442, 382, 444, 382, 444, 382, 444, 380, 444, 380, 444, 382, + 444, 380, 446, 380, 436, 388, 436, 390, 436, 388, 438, 388, + 438, 388, 438, 388, 438, 386, 440, 386, 440, 386, 442, 384, + 440, 386, 442, 384, 440, 384, 442, 384, 442, 382, 442, 382, + 444, 1208, 444, 382, 444, 1208, 444, 380, 446, 1206, 436, 390, + 436, 1216, 436}; + irsend.sendRaw(rawData1, 243, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits); + uint8_t expected1[kFujitsuAcStateLength - 1] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x21, 0x01, 0x04, 0x00, 0x00, 0x00, 0xAA}; + EXPECT_TRUE(ArraysMatch(expected1, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 4 (QUIET), " + "Swing: Off, Command: N/A", fujitsu.toString()); + + irsend.reset(); + uint16_t rawData2[243] = { + 3316, 1630, 436, 398, 438, 386, 438, 1212, 440, 384, 440, 1212, + 442, 384, 442, 392, 414, 394, 442, 1218, 446, 1206, 436, 390, + 436, 388, 438, 388, 438, 1214, 440, 1212, 440, 384, 442, 384, + 442, 384, 442, 382, 444, 382, 444, 382, 444, 380, 446, 380, + 444, 380, 436, 390, 436, 388, 438, 396, 418, 388, 438, 1232, + 410, 396, 440, 394, 442, 384, 442, 384, 442, 382, 442, 392, + 414, 392, 444, 1216, 446, 380, 436, 390, 436, 396, 418, 390, + 436, 398, 438, 1214, 440, 1212, 440, 1210, 442, 1208, 444, 1216, + 416, 1218, 444, 388, 436, 390, 436, 388, 438, 1214, 440, 386, + 438, 386, 440, 386, 440, 384, 442, 384, 442, 384, 442, 382, + 444, 382, 444, 1206, 446, 1206, 436, 390, 436, 388, 438, 388, + 438, 386, 440, 394, 410, 396, 440, 1220, 442, 1210, 442, 392, + 414, 394, 442, 1218, 446, 406, 410, 388, 436, 390, 436, 390, + 436, 388, 438, 386, 440, 386, 440, 386, 440, 386, 440, 384, + 442, 384, 442, 384, 442, 382, 444, 382, 444, 380, 446, 380, + 446, 380, 436, 390, 436, 390, 436, 388, 438, 386, 438, 388, + 438, 386, 440, 386, 440, 384, 442, 384, 442, 384, 442, 384, + 442, 382, 444, 382, 444, 380, 446, 380, 446, 380, 436, 390, + 436, 388, 436, 388, 438, 386, 438, 386, 440, 386, 440, 1212, + 440, 1210, 442, 1210, 442, 1208, 444, 1208, 436, 390, 436, 388, + 436, 1214, 440}; + irsend.sendRaw(rawData2, 243, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits); + uint8_t expected2[kFujitsuAcStateLength - 1] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9F}; + EXPECT_TRUE(ArraysMatch(expected2, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 0 (AUTO), " + "Swing: Off, Command: N/A", fujitsu.toString()); +} + +TEST(TestDecodeFujitsuAC, Issue414) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + + // Capture as supplied by arpmota + uint16_t rawData[259] = {3352, 1574, 480, 350, 480, 346, 480, 1190, 458, 346, + 508, 1140, 480, 346, 506, 346, 458, 346, 480, 1168, 480, 1192, 452, 374, + 458, 346, 480, 346, 508, 1168, 480, 1140, 480, 346, 506, 346, 458, 346, + 480, 346, 480, 346, 480, 346, 484, 372, 454, 374, 456, 346, 508, 318, + 480, 374, 458, 374, 480, 318, 480, 1196, 452, 346, 480, 346, 484, 342, + 484, 346, 480, 374, 458, 346, 506, 318, 508, 1170, 452, 346, 480, 374, + 458, 346, 506, 318, 480, 1196, 452, 1190, 458, 1162, 480, 1196, 452, + 1170, 480, 1190, 458, 1164, 480, 1196, 480, 318, 508, 346, 456, 1192, + 480, 346, 456, 374, 452, 346, 480, 374, 458, 342, 484, 346, 508, 346, + 456, 342, 512, 1164, 458, 1164, 508, 346, 456, 346, 480, 1190, 456, 342, + 484, 346, 506, 346, 456, 374, 452, 346, 508, 346, 458, 1164, 508, 346, + 458, 374, 452, 1168, 480, 374, 480, 318, 480, 374, 456, 346, 508, 318, + 480, 346, 484, 374, 480, 318, 484, 342, 484, 374, 480, 318, 484, 342, + 484, 346, 508, 318, 508, 346, 458, 346, 506, 318, 480, 374, 458, 346, + 506, 318, 480, 346, 484, 374, 480, 318, 482, 372, 456, 346, 508, 318, + 506, 348, 456, 342, 484, 346, 508, 318, 484, 374, 480, 318, 508, 318, + 484, 346, 508, 318, 480, 374, 456, 346, 508, 346, 480, 318, 480, 346, + 484, 374, 480, 320, 484, 1164, 508, 346, 458, 342, 512, 1164, 458, 1190, + 454, 346, 484, 1164, 508, 346, 458, 1164, 480, 350, 480, 374, 480}; + uint8_t state[16] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, 0x81, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x2B}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData, 259, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits); + EXPECT_TRUE(ArraysMatch(state, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 4 (HEAT), Temp: 24C, Fan: 0 (AUTO), " + "Swing: Off, Command: N/A", fujitsu.toString()); + + // Resend it using the state this time. + irsend.reset(); + irsend.sendFujitsuAC(state, 16); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits); + EXPECT_TRUE(ArraysMatch(state, irsend.capture.state)); + EXPECT_EQ( + "m3324s1574" + "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390" + "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" + "m448s1182m448s390m448s390m448s1182m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390" + "m448s1182m448s390m448s390m448s390m448s390m448s390m448s390m448s1182" + "m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s390" + "m448s1182m448s1182m448s390m448s1182m448s390m448s1182m448s390m448s390" + "m448s8100", irsend.outputStr()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp new file mode 100644 index 000000000..b9bfce997 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp @@ -0,0 +1,161 @@ +// Copyright 2018 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendGICable(). + +// Test sending typical data only. +TEST(TestSendGICable, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + irsend.sendGICable(0); + EXPECT_EQ( + "m9000s4400" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200" + "m550s41650" + "m9000s2200m550s87850", + irsend.outputStr()); + irsend.sendGICable(0x8807); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" + "m550s30650" + "m9000s2200m550s87850", + irsend.outputStr()); + irsend.sendGICable(0xFFFF); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400" + "m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400" + "m550s6450" + "m9000s2200m550s87850", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendGICable, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + // Send a command with 0 repeats. + irsend.sendGICable(0x8807, kGicableBits, 0); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" + "m550s30650", + irsend.outputStr()); + // Send a command with 1 repeat. + irsend.sendGICable(0x8807, kGicableBits, 1); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" + "m550s30650" + "m9000s2200m550s87850", + irsend.outputStr()); + // Send a command with 3 repeats. + irsend.sendGICable(0x8807, kGicableBits, 3); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" + "m550s30650" + "m9000s2200m550s87850" + "m9000s2200m550s87850" + "m9000s2200m550s87850", + irsend.outputStr()); +} + +// Tests for decodeGICable(). +// Decode normal GICable messages. +TEST(TestDecodeGICable, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Synthesised Normal GICable message. + irsend.reset(); + irsend.sendGICable(0x8807); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GICABLE, irsend.capture.decode_type); + EXPECT_EQ(kGicableBits, irsend.capture.bits); + EXPECT_EQ(0x8807, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +// Decode a recorded example +TEST(TestDecodeGICable, RealExampleDecodeOK) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real GICable "OK/Select" message. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/447 + uint16_t rawData[39] = {9064, 4408, 580, 4408, 580, 2152, 578, 2150, + 580, 2150, 580, 4408, 580, 2150, 580, 2150, + 580, 2150, 580, 2150, 580, 2150, 580, 2150, + 580, 2150, 580, 2150, 580, 4408, 580, 4408, + 580, 4408, 580, 30622, 9066, 2148, 580}; + irsend.reset(); + irsend.sendRaw(rawData, 39, 39); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GICABLE, irsend.capture.decode_type); + EXPECT_EQ(kGicableBits, irsend.capture.bits); + EXPECT_EQ(0x8807, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +TEST(TestDecodeGICable, RealExampleDecodeLEFT) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real GICable "LEFT" message. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/447 + uint16_t rawData[39] = {9040, 4434, 554, 2176, 580, 4408, 554, 4434, + 582, 2148, 554, 4434, 580, 4408, 556, 2174, + 580, 2150, 580, 2150, 582, 2148, 556, 2176, + 580, 2150, 580, 4408, 580, 4408, 580, 4408, + 582, 2150, 580, 26078, 9066, 2148, 580}; + irsend.reset(); + irsend.sendRaw(rawData, 39, 39); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GICABLE, irsend.capture.decode_type); + EXPECT_EQ(kGicableBits, irsend.capture.bits); + EXPECT_EQ(0x6C0E, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +TEST(TestDecodeGICable, RealExampleDecodeZEROKey) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real GICable "Zero Key" message. + // Note: Zero key looks similar to a JVC message, hence this test. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/447 + uint16_t rawData[39] = {9036, 4434, 552, 2178, 552, 2178, 552, 2180, + 550, 2178, 552, 2178, 550, 2180, 552, 2178, + 552, 2178, 550, 2180, 552, 2178, 526, 2204, + 552, 2178, 552, 2178, 526, 2204, 526, 2204, + 526, 2204, 526, 41932, 9036, 2176, 552}; + irsend.reset(); + irsend.sendRaw(rawData, 39, 39); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GICABLE, irsend.capture.decode_type); + EXPECT_EQ(kGicableBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp new file mode 100644 index 000000000..16a556b57 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp @@ -0,0 +1,71 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendGlobalCache(). + +// Test sending a typical command wihtout a repeat. +TEST(TestSendGlobalCache, NonRepeatingCode) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + // Modified NEC TV "Power On" from Global Cache with no repeats + uint16_t gc_test[71] = {38000, 1, 1, 342, 172, 21, 22, 21, 21, 21, 65, 21, + 21, 21, 22, 21, 22, 21, 21, 21, 22, 21, 65, 21, + 65, 21, 22, 21, 65, 21, 65, 21, 65, 21, 65, 21, + 65, 21, 65, 21, 22, 21, 22, 21, 21, 21, 22, 21, + 22, 21, 65, 21, 22, 21, 21, 21, 65, 21, 65, 21, + 65, 21, 64, 22, 65, 21, 22, 21, 65, 21, 1519}; + irsend.sendGC(gc_test, 71); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x20DF827D, irsend.capture.value); + EXPECT_EQ(0x4, irsend.capture.address); + EXPECT_EQ(0x41, irsend.capture.command); + EXPECT_EQ( + "m8892s4472m546s572m546s546m546s1690m546s546m546s572m546s572" + "m546s546m546s572m546s1690m546s1690m546s572m546s1690m546s1690" + "m546s1690m546s1690m546s1690m546s1690m546s572m546s572m546s546" + "m546s572m546s572m546s1690m546s572m546s546m546s1690m546s1690" + "m546s1690m546s1664m572s1690m546s572m546s1690m546s39494", + irsend.outputStr()); +} + +// Test sending typical command with repeats. +TEST(TestSendGlobalCache, RepeatCode) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + // Sherwood (NEC-like) "Power On" from Global Cache with 2 repeats + uint16_t gc_test[75] = { + 38000, 2, 69, 341, 171, 21, 64, 21, 64, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 64, 21, 64, 21, 21, 21, 64, 21, 21, 21, + 21, 21, 21, 21, 64, 21, 21, 21, 64, 21, 21, 21, 21, 21, 21, + 21, 64, 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 64, 21, + 64, 21, 21, 21, 64, 21, 64, 21, 64, 21, 1600, 341, 85, 21, 3647}; + irsend.sendGC(gc_test, 75); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0xC1A28877, irsend.capture.value); + EXPECT_EQ(0x4583, irsend.capture.address); + EXPECT_EQ(0x11, irsend.capture.command); + EXPECT_EQ( + "m8866s4446m546s1664m546s1664m546s546m546s546m546s546m546s546" + "m546s546m546s1664m546s1664m546s546m546s1664m546s546m546s546" + "m546s546m546s1664m546s546m546s1664m546s546m546s546m546s546" + "m546s1664m546s546m546s546m546s546m546s546m546s1664m546s1664" + "m546s1664m546s546m546s1664m546s1664m546s1664m546s41600" + "m8866s2210m546s94822" + "m8866s2210m546s94822", + irsend.outputStr()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp new file mode 100644 index 000000000..6c7a1f637 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp @@ -0,0 +1,527 @@ +// Copyright 2017 David Conran + +#include "ir_Gree.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendGree(). + +// Test sending typical data only. +TEST(TestSendGreeChars, SendData) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t gree_code[kGreeStateLength] = {0x12, 0x34, 0x56, 0x78, + 0x90, 0xAB, 0xCD, 0xEF}; + irsend.reset(); + irsend.sendGree(gree_code); + EXPECT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000", + irsend.outputStr()); +} + +TEST(TestSendGreeUint64, SendData) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendGree(0x1234567890ABCDEF); + EXPECT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendGreeChars, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t gree_code[kGreeStateLength] = {0x12, 0x34, 0x56, 0x78, + 0x90, 0xAB, 0xCD, 0xEF}; + irsend.reset(); + + irsend.sendGree(gree_code, kGreeStateLength, 1); + EXPECT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000" + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000", + irsend.outputStr()); +} + +TEST(TestSendGreeUint64, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendGree(0x1234567890ABCDEF, kGreeBits, 1); + EXPECT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000" + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendGreeChars, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t gree_short_code[kGreeStateLength - 1] = {0x12, 0x34, 0x56, 0x78, + 0x90, 0xAB, 0xCD}; + uint8_t gree_long_code[kGreeStateLength + 1] = {0x12, 0x34, 0x56, 0x78, 0x90, + 0xAB, 0xCD, 0xEF, 0x12}; + irsend.reset(); + irsend.sendGree(gree_short_code, kGreeStateLength - 1); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendGree(gree_long_code, kGreeStateLength + 1); + ASSERT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s19000", + irsend.outputStr()); +} + +TEST(TestSendGreeUint64, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendGree(0x1234567890ABCDEF, kGreeBits - 1); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendGree(0x1234567890ABCDEF, kGreeBits + 1); + ASSERT_EQ("", irsend.outputStr()); +} + +TEST(TestSendGree, CompareUint64ToCharResults) { + IRsendTest irsend_chars(4); + IRsendTest irsend_uint64(0); + + uint8_t gree_code[kGreeStateLength] = {0x12, 0x34, 0x56, 0x78, + 0x90, 0xAB, 0xCD, 0xEF}; + + irsend_chars.begin(); + irsend_uint64.begin(); + + irsend_chars.reset(); + irsend_uint64.reset(); + irsend_chars.sendGree(gree_code); + irsend_uint64.sendGree(0x1234567890ABCDEF); + ASSERT_EQ(irsend_chars.outputStr(), irsend_uint64.outputStr()); + + uint8_t gree_zero_code[kGreeStateLength] = {0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + irsend_chars.reset(); + irsend_uint64.reset(); + irsend_chars.sendGree(gree_zero_code); + irsend_uint64.sendGree((uint64_t)0x0); + ASSERT_EQ(irsend_chars.outputStr(), irsend_uint64.outputStr()); +} + +// Tests for IRGreeAC class. + +TEST(TestGreeClass, Power) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.on(); + EXPECT_TRUE(irgree.getPower()); + + irgree.off(); + EXPECT_FALSE(irgree.getPower()); + + irgree.setPower(true); + EXPECT_TRUE(irgree.getPower()); + + irgree.setPower(false); + EXPECT_FALSE(irgree.getPower()); +} + +TEST(TestGreeClass, Temperature) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setMode(kGreeCool); + + irgree.setTemp(0); + EXPECT_EQ(kGreeMinTemp, irgree.getTemp()); + + irgree.setTemp(255); + EXPECT_EQ(kGreeMaxTemp, irgree.getTemp()); + + irgree.setTemp(kGreeMinTemp); + EXPECT_EQ(kGreeMinTemp, irgree.getTemp()); + + irgree.setTemp(kGreeMaxTemp); + EXPECT_EQ(kGreeMaxTemp, irgree.getTemp()); + + irgree.setTemp(kGreeMinTemp - 1); + EXPECT_EQ(kGreeMinTemp, irgree.getTemp()); + + irgree.setTemp(kGreeMaxTemp + 1); + EXPECT_EQ(kGreeMaxTemp, irgree.getTemp()); + + irgree.setTemp(17); + EXPECT_EQ(17, irgree.getTemp()); + + irgree.setTemp(21); + EXPECT_EQ(21, irgree.getTemp()); + + irgree.setTemp(25); + EXPECT_EQ(25, irgree.getTemp()); + + irgree.setTemp(29); + EXPECT_EQ(29, irgree.getTemp()); +} + +TEST(TestGreeClass, OperatingMode) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setTemp(17); + irgree.setMode(kGreeAuto); // Auto should lock the temp to 25C. + EXPECT_EQ(kGreeAuto, irgree.getMode()); + EXPECT_EQ(25, irgree.getTemp()); + irgree.setTemp(17); + EXPECT_EQ(25, irgree.getTemp()); + + irgree.setMode(kGreeCool); + EXPECT_EQ(kGreeCool, irgree.getMode()); + + irgree.setMode(kGreeHeat); + EXPECT_EQ(kGreeHeat, irgree.getMode()); + + ASSERT_NE(kGreeFanMax, 1); + irgree.setFan(kGreeFanMax); + irgree.setMode(kGreeDry); // Dry should lock the fan to speed 1. + EXPECT_EQ(kGreeDry, irgree.getMode()); + EXPECT_EQ(1, irgree.getFan()); + irgree.setFan(kGreeFanMax); + EXPECT_EQ(1, irgree.getFan()); + + irgree.setMode(kGreeFan); + EXPECT_EQ(kGreeFan, irgree.getMode()); + + irgree.setMode(kGreeHeat + 1); + EXPECT_EQ(kGreeAuto, irgree.getMode()); + + irgree.setMode(255); + EXPECT_EQ(kGreeAuto, irgree.getMode()); +} + +TEST(TestGreeClass, Light) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setLight(true); + EXPECT_TRUE(irgree.getLight()); + + irgree.setLight(false); + EXPECT_FALSE(irgree.getLight()); + + irgree.setLight(true); + EXPECT_TRUE(irgree.getLight()); +} + +TEST(TestGreeClass, XFan) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setXFan(true); + EXPECT_TRUE(irgree.getXFan()); + + irgree.setXFan(false); + EXPECT_FALSE(irgree.getXFan()); + + irgree.setXFan(true); + EXPECT_TRUE(irgree.getXFan()); +} + +TEST(TestGreeClass, Turbo) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setTurbo(true); + EXPECT_TRUE(irgree.getTurbo()); + + irgree.setTurbo(false); + EXPECT_FALSE(irgree.getTurbo()); + + irgree.setTurbo(true); + EXPECT_TRUE(irgree.getTurbo()); +} + +TEST(TestGreeClass, Sleep) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setSleep(true); + EXPECT_TRUE(irgree.getSleep()); + + irgree.setSleep(false); + EXPECT_FALSE(irgree.getSleep()); + + irgree.setSleep(true); + EXPECT_TRUE(irgree.getSleep()); +} + +TEST(TestGreeClass, FanSpeed) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setFan(0); + EXPECT_EQ(0, irgree.getFan()); + + irgree.setFan(255); + EXPECT_EQ(kGreeFanMax, irgree.getFan()); + + irgree.setFan(kGreeFanMax); + EXPECT_EQ(kGreeFanMax, irgree.getFan()); + + irgree.setFan(kGreeFanMax + 1); + EXPECT_EQ(kGreeFanMax, irgree.getFan()); + + irgree.setFan(kGreeFanMax - 1); + EXPECT_EQ(kGreeFanMax - 1, irgree.getFan()); + + irgree.setFan(1); + EXPECT_EQ(1, irgree.getFan()); + + irgree.setFan(1); + EXPECT_EQ(1, irgree.getFan()); + + irgree.setFan(3); + EXPECT_EQ(3, irgree.getFan()); +} + +TEST(TestGreeClass, VerticalSwing) { + IRGreeAC irgree(0); + irgree.begin(); + EXPECT_FALSE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingLastPos, irgree.getSwingVerticalPosition()); + + irgree.setSwingVertical(true, kGreeSwingAuto); + EXPECT_TRUE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingAuto, irgree.getSwingVerticalPosition()); + + irgree.setSwingVertical(false, kGreeSwingMiddle); + EXPECT_FALSE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingMiddle, irgree.getSwingVerticalPosition()); + + irgree.setSwingVertical(true, kGreeSwingDownAuto); + EXPECT_TRUE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingDownAuto, irgree.getSwingVerticalPosition()); + + // Out of bounds. + irgree.setSwingVertical(false, 255); + EXPECT_FALSE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingLastPos, irgree.getSwingVerticalPosition()); + irgree.setSwingVertical(false, kGreeSwingAuto); + EXPECT_FALSE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingLastPos, irgree.getSwingVerticalPosition()); + + irgree.setSwingVertical(true, 255); + EXPECT_TRUE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingAuto, irgree.getSwingVerticalPosition()); + irgree.setSwingVertical(true, kGreeSwingDown); + EXPECT_TRUE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingAuto, irgree.getSwingVerticalPosition()); +} + +TEST(TestGreeClass, SetAndGetRaw) { + IRGreeAC irgree(0); + uint8_t initialState[kGreeStateLength] = {0x00, 0x09, 0x20, 0x50, + 0x00, 0x20, 0x00, 0x50}; + uint8_t expectedState[kGreeStateLength] = {0xA9, 0x05, 0xD0, 0x50, + 0x00, 0x20, 0x00, 0xA0}; + + EXPECT_STATE_EQ(initialState, irgree.getRaw(), kGreeBits); + + // toggle the power state. + irgree.setPower(!irgree.getPower()); + irgree.setMode(kGreeCool); + irgree.setTemp(21); + irgree.setFan(2); + irgree.setLight(false); + irgree.setTurbo(true); + irgree.setSleep(true); + irgree.setXFan(true); + + EXPECT_EQ(kGreeCool, irgree.getMode()); + EXPECT_EQ(21, irgree.getTemp()); + EXPECT_EQ(2, irgree.getFan()); + EXPECT_FALSE(irgree.getLight()); + EXPECT_TRUE(irgree.getTurbo()); + EXPECT_TRUE(irgree.getSleep()); + EXPECT_TRUE(irgree.getXFan()); + + EXPECT_STATE_EQ(expectedState, irgree.getRaw(), kGreeBits); + irgree.setRaw(initialState); + EXPECT_STATE_EQ(initialState, irgree.getRaw(), kGreeBits); +} + +TEST(TestGreeClass, HumanReadable) { + IRGreeAC irgree(0); + + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), Turbo: Off, " + "XFan: Off, Light: On, Sleep: Off, Swing Vertical Mode: Manual, " + "Swing Vertical Pos: 0 (Last Pos)", + irgree.toString()); + irgree.on(); + irgree.setMode(kGreeCool); + irgree.setTemp(kGreeMinTemp); + irgree.setFan(kGreeFanMax); + irgree.setXFan(true); + irgree.setSleep(true); + irgree.setLight(false); + irgree.setTurbo(true); + irgree.setSwingVertical(true, kGreeSwingAuto); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 3 (MAX), Turbo: On, " + "XFan: On, Light: Off, Sleep: On, Swing Vertical Mode: Auto, " + "Swing Vertical Pos: 1 (Auto)", + irgree.toString()); +} + +// Tests for decodeGree(). + +// Decode a synthetic Gree message. +TEST(TestDecodeGree, NormalSynthetic) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t gree_code[kGreeStateLength] = {0x00, 0x09, 0x20, 0x50, + 0x00, 0x20, 0x00, 0x50}; + + irsend.reset(); + irsend.sendGree(gree_code); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GREE, irsend.capture.decode_type); + ASSERT_EQ(kGreeBits, irsend.capture.bits); + EXPECT_STATE_EQ(gree_code, irsend.capture.state, kGreeBits); +} + +// Decode a synthetic Gree message. +TEST(TestDecodeGree, NormalRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + IRGreeAC irgree(4); + irsend.begin(); + + uint8_t gree_code[kGreeStateLength] = {0x19, 0x0A, 0x60, 0x50, + 0x02, 0x23, 0x00, 0xF0}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/386 + uint16_t rawData[139] = { + 9008, 4496, 644, 1660, 676, 530, 648, 558, 672, 1636, 646, 1660, + 644, 556, 650, 584, 626, 560, 644, 580, 628, 1680, 624, 560, + 648, 1662, 644, 582, 648, 536, 674, 530, 646, 580, 628, 560, + 670, 532, 646, 562, 644, 556, 672, 536, 648, 1662, 646, 1660, + 652, 554, 644, 558, 672, 538, 644, 560, 668, 560, 648, 1638, + 668, 536, 644, 1660, 668, 532, 648, 560, 648, 1660, 674, 554, + 622, 19990, 646, 580, 624, 1660, 648, 556, 648, 558, 674, 556, + 622, 560, 644, 564, 668, 536, 646, 1662, 646, 1658, 672, 534, + 648, 558, 644, 562, 648, 1662, 644, 584, 622, 558, 648, 562, + 668, 534, 670, 536, 670, 532, 672, 536, 646, 560, 646, 558, + 648, 558, 670, 534, 650, 558, 646, 560, 646, 560, 668, 1638, + 646, 1662, 646, 1660, 646, 1660, 648}; // Issue #386 + + irsend.reset(); + irsend.sendRaw(rawData, 139, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GREE, irsend.capture.decode_type); + ASSERT_EQ(kGreeBits, irsend.capture.bits); + EXPECT_STATE_EQ(gree_code, irsend.capture.state, kGreeBits); + irgree.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 26C, Fan: 1, Turbo: Off, " + "XFan: Off, Light: On, Sleep: Off, Swing Vertical Mode: Manual, " + "Swing Vertical Pos: 2", + irgree.toString()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp new file mode 100644 index 000000000..11848e00a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp @@ -0,0 +1,989 @@ +// Copyright 2018 David Conran + +#include "ir_Haier.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendHaierAC() + +// Test sending typical data only. +TEST(TestSendHaierAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + uint8_t haier_zero[kHaierACStateLength] = {0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + + irsend.reset(); + irsend.sendHaierAC(haier_zero); + EXPECT_EQ( + "m3000s3000m3000s4300" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s150000", + irsend.outputStr()); + + uint8_t haier_test[kHaierACStateLength] = {0xA5, 0x01, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0xA7}; + irsend.reset(); + irsend.sendHaierAC(haier_test); + EXPECT_EQ( + "m3000s3000m3000s4300" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s1650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s1650m520s1650" + "m520s150000", + irsend.outputStr()); +} + +// Test sending typical data with repeats. +TEST(TestSendHaierAC, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + uint8_t haier_test[kHaierACStateLength] = {0xA5, 0x01, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0xA7}; + irsend.reset(); + irsend.sendHaierAC(haier_test, kHaierACStateLength, 2); // two repeats. + EXPECT_EQ( + "m3000s3000m3000s4300" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s1650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s1650m520s1650" + "m520s150000" + "m3000s3000m3000s4300" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s1650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s1650m520s1650" + "m520s150000" + "m3000s3000m3000s4300" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s1650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s1650m520s1650" + "m520s150000", + irsend.outputStr()); +} + +// Tests for IRHaierAC class. + +TEST(TestHaierACClass, Command) { + IRHaierAC haier(0); + haier.begin(); + + haier.setCommand(kHaierAcCmdOff); + EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); + haier.setCommand(kHaierAcCmdOn); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + haier.setCommand(kHaierAcCmdMode); + EXPECT_EQ(kHaierAcCmdMode, haier.getCommand()); + haier.setCommand(kHaierAcCmdFan); + EXPECT_EQ(kHaierAcCmdFan, haier.getCommand()); + haier.setCommand(kHaierAcCmdTempUp); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + haier.setCommand(kHaierAcCmdTempDown); + EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + haier.setCommand(kHaierAcCmdSleep); + EXPECT_EQ(kHaierAcCmdSleep, haier.getCommand()); + haier.setCommand(kHaierAcCmdTimerSet); + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + haier.setCommand(kHaierAcCmdTimerCancel); + EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); + haier.setCommand(kHaierAcCmdHealth); + EXPECT_EQ(kHaierAcCmdHealth, haier.getCommand()); + haier.setCommand(kHaierAcCmdSwing); + EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); + haier.setCommand(kHaierAcCmdOn); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + // Test unexpected values. + haier.setCommand(0b00001110); + EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); + haier.setCommand(0b00001111); + EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); + haier.setCommand(0b00000100); + EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); +} + +TEST(TestHaierACClass, OperatingMode) { + IRHaierAC haier(0); + haier.begin(); + + haier.setMode(kHaierAcAuto); + EXPECT_EQ(kHaierAcAuto, haier.getMode()); + + haier.setMode(kHaierAcCool); + EXPECT_EQ(kHaierAcCool, haier.getMode()); + + haier.setMode(kHaierAcHeat); + EXPECT_EQ(kHaierAcHeat, haier.getMode()); + + haier.setMode(kHaierAcFan); + EXPECT_EQ(kHaierAcFan, haier.getMode()); + + haier.setMode(kHaierAcDry); + EXPECT_EQ(kHaierAcDry, haier.getMode()); + + haier.setMode(kHaierAcAuto - 1); + EXPECT_EQ(kHaierAcAuto, haier.getMode()); + + haier.setMode(kHaierAcCool); + EXPECT_EQ(kHaierAcCool, haier.getMode()); + + haier.setMode(kHaierAcFan + 1); + EXPECT_EQ(kHaierAcAuto, haier.getMode()); + + haier.setMode(255); + EXPECT_EQ(kHaierAcAuto, haier.getMode()); +} + +TEST(TestHaierACClass, Temperature) { + IRHaierAC haier(0); + haier.begin(); + + haier.setTemp(kHaierAcMinTemp); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + + haier.setCommand(kHaierAcCmdOn); + haier.setTemp(kHaierAcMinTemp + 1); + EXPECT_EQ(kHaierAcMinTemp + 1, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + + haier.setTemp(kHaierAcMaxTemp); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + + haier.setTemp(kHaierAcMinTemp - 1); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + + haier.setTemp(kHaierAcMaxTemp + 1); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + + haier.setTemp(23); + EXPECT_EQ(23, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + haier.setCommand(kHaierAcCmdOn); + haier.setTemp(23); + EXPECT_EQ(23, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + haier.setTemp(0); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + + haier.setTemp(255); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); +} + +TEST(TestHaierACClass, FanSpeed) { + IRHaierAC haier(0); + haier.begin(); + haier.setFan(kHaierAcFanLow); + haier.setCommand(kHaierAcCmdOn); + + haier.setFan(kHaierAcFanAuto); + EXPECT_EQ(kHaierAcFanAuto, haier.getFan()); + EXPECT_EQ(kHaierAcCmdFan, haier.getCommand()); + + haier.setFan(kHaierAcFanLow); + EXPECT_EQ(kHaierAcFanLow, haier.getFan()); + haier.setFan(kHaierAcFanMed); + EXPECT_EQ(kHaierAcFanMed, haier.getFan()); + haier.setFan(kHaierAcFanHigh); + EXPECT_EQ(kHaierAcFanHigh, haier.getFan()); + + haier.setCommand(kHaierAcCmdOn); + haier.setFan(kHaierAcFanHigh); + EXPECT_EQ(kHaierAcFanHigh, haier.getFan()); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); +} + +TEST(TestHaierACClass, Swing) { + IRHaierAC haier(0); + haier.begin(); + haier.setFan(kHaierAcFanLow); + haier.setCommand(kHaierAcCmdOn); + + haier.setSwing(kHaierAcSwingOff); + EXPECT_EQ(kHaierAcSwingOff, haier.getSwing()); + + haier.setSwing(kHaierAcSwingUp); + EXPECT_EQ(kHaierAcSwingUp, haier.getSwing()); + EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); + + haier.setSwing(kHaierAcSwingDown); + EXPECT_EQ(kHaierAcSwingDown, haier.getSwing()); + EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); + + haier.setSwing(kHaierAcSwingChg); + EXPECT_EQ(kHaierAcSwingChg, haier.getSwing()); + EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); +} + +TEST(TestHaierACClass, CurrentTime) { + IRHaierAC haier(0); + haier.begin(); + EXPECT_EQ(0, haier.getCurrTime()); + + haier.setCurrTime(1); + EXPECT_EQ(1, haier.getCurrTime()); + + haier.setCurrTime(60); + EXPECT_EQ(60, haier.getCurrTime()); + + haier.setCurrTime(61); + EXPECT_EQ(61, haier.getCurrTime()); + + haier.setCurrTime(18 * 60 + 34); // 18:34 + EXPECT_EQ(1114, haier.getCurrTime()); + + haier.setCurrTime(23 * 60 + 59); // 23:59 + EXPECT_EQ(kHaierAcMaxTime, haier.getCurrTime()); // 23:59 + + haier.setCurrTime(23 * 60 + 59 + 1); // 24:00 + EXPECT_EQ(kHaierAcMaxTime, haier.getCurrTime()); // 23:59 + + haier.setCurrTime(UINT16_MAX); + EXPECT_EQ(kHaierAcMaxTime, haier.getCurrTime()); // 23:59 +} + +TEST(TestHaierACClass, Timers) { + IRHaierAC haier(0); + haier.begin(); + + haier.setCommand(kHaierAcCmdOn); + + // Off by default. + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + // On Timer. + haier.setOnTimer(6 * 60); // 6am + EXPECT_EQ(6 * 60, haier.getOnTimer()); // 6am + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + + haier.setCommand(kHaierAcCmdOn); + EXPECT_EQ(6 * 60, haier.getOnTimer()); // 6am + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + haier.cancelTimers(); + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); + + // Off Timer. + haier.setOffTimer(18 * 60 + 30); // 6:30pm + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_EQ(18 * 60 + 30, haier.getOffTimer()); // 6:30pm + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + + haier.setCommand(kHaierAcCmdOn); + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_EQ(18 * 60 + 30, haier.getOffTimer()); // 6:30pm + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + haier.cancelTimers(); + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); + + // Both Timers. + haier.setOnTimer(6 * 60); // 6am + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + haier.setOffTimer(18 * 60 + 30); // 6:30pm + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + EXPECT_EQ(6 * 60, haier.getOnTimer()); // 6am + EXPECT_EQ(18 * 60 + 30, haier.getOffTimer()); // 6:30pm + + haier.cancelTimers(); + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); +} + +TEST(TestHaierACClass, TimeToString) { + EXPECT_EQ("00:00", IRHaierAC::timeToString(0)); + EXPECT_EQ("00:01", IRHaierAC::timeToString(1)); + EXPECT_EQ("00:10", IRHaierAC::timeToString(10)); + EXPECT_EQ("00:59", IRHaierAC::timeToString(59)); + + EXPECT_EQ("01:00", IRHaierAC::timeToString(60)); + EXPECT_EQ("01:01", IRHaierAC::timeToString(61)); + EXPECT_EQ("01:59", IRHaierAC::timeToString(60 + 59)); + EXPECT_EQ("18:59", IRHaierAC::timeToString(18 * 60 + 59)); + EXPECT_EQ("23:59", IRHaierAC::timeToString(23 * 60 + 59)); +} + +TEST(TestHaierACClass, MessageConstuction) { + IRHaierAC haier(0); + + EXPECT_EQ( + "Command: 1 (On), Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Current Time: 00:00, On Timer: Off, Off Timer: Off", + haier.toString()); + haier.setMode(kHaierAcCool); + haier.setTemp(21); + haier.setFan(kHaierAcFanHigh); + EXPECT_EQ( + "Command: 3 (Fan), Mode: 1 (COOL), Temp: 21C, Fan: 3 (MAX), " + "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Current Time: 00:00, On Timer: Off, Off Timer: Off", + haier.toString()); + haier.setSwing(kHaierAcSwingChg); + haier.setHealth(true); + haier.setSleep(true); + haier.setCurrTime(615); // 10:15am + EXPECT_EQ( + "Command: 8 (Sleep), Mode: 3 (HEAT), Temp: 21C, Fan: 3 (MAX), " + "Swing: 3 (Chg), Sleep: On, Health: On, " + "Current Time: 10:15, On Timer: Off, Off Timer: Off", + haier.toString()); + haier.setOnTimer(800); // 1:20pm + haier.setOffTimer(1125); // 6:45pm + haier.setCommand(kHaierAcCmdOn); + + EXPECT_EQ( + "Command: 1 (On), Mode: 2 (DRY), Temp: 21C, Fan: 2, " + "Swing: 3 (Chg), Sleep: On, Health: On, " + "Current Time: 10:15, On Timer: 13:20, Off Timer: 18:45", + haier.toString()); + + // Now change a few already set things. + haier.setMode(kHaierAcHeat); + EXPECT_EQ( + "Command: 2 (Mode), Mode: 3 (HEAT), Temp: 21C, Fan: 2, " + "Swing: 3 (Chg), Sleep: On, Health: On, " + "Current Time: 10:15, On Timer: 13:52, Off Timer: 18:45", + haier.toString()); + + haier.setTemp(25); + EXPECT_EQ( + "Command: 6 (Temp Up), Mode: 3 (HEAT), Temp: 25C, Fan: 2, " + "Swing: 3 (Chg), Sleep: On, Health: On, " + "Current Time: 10:15, On Timer: 13:52, Off Timer: 18:45", + haier.toString()); + + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x96, 0xEA, 0xCF, 0x32, + 0x2D, 0x0D, 0x74, 0xD4}; + EXPECT_STATE_EQ(expectedState, haier.getRaw(), kHaierACBits); + + // Check that the checksum is valid. + EXPECT_TRUE(IRHaierAC::validChecksum(haier.getRaw())); + + // Now load up some random data. + uint8_t randomState[kHaierACStateLength] = {0x52, 0x49, 0x50, 0x20, 0x54, + 0x61, 0x6C, 0x69, 0x61}; + EXPECT_FALSE(IRHaierAC::validChecksum(randomState)); + haier.setRaw(randomState); + EXPECT_EQ( + "Command: 9 (Timer Set), Mode: 3 (HEAT), Temp: 20C, Fan: 2, " + "Swing: 1 (Up), Sleep: On, Health: Off, " + "Current Time: 16:32, On Timer: Off, Off Timer: Off", + haier.toString()); + // getRaw() should correct the checksum. + EXPECT_TRUE(IRHaierAC::validChecksum(haier.getRaw())); +} + +// Tests for the IRHaierACYRW02 class. + +TEST(TestHaierACYRW02Class, Button) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setButton(kHaierAcYrw02ButtonPower); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + haier.setButton(kHaierAcYrw02ButtonMode); + EXPECT_EQ(kHaierAcYrw02ButtonMode, haier.getButton()); + haier.setButton(kHaierAcYrw02ButtonSleep); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); + haier.setButton(kHaierAcYrw02ButtonFan); + + // Test unexpected values. + haier.setButton(0xFF); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + haier.setButton(0x10); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, OperatingMode) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setButton(kHaierAcYrw02ButtonPower); + haier.setMode(kHaierAcYrw02Auto); + EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); + EXPECT_EQ(kHaierAcYrw02ButtonMode, haier.getButton()); + + haier.setMode(kHaierAcYrw02Cool); + EXPECT_EQ(kHaierAcYrw02Cool, haier.getMode()); + + haier.setMode(kHaierAcYrw02Heat); + EXPECT_EQ(kHaierAcYrw02Heat, haier.getMode()); + + haier.setMode(kHaierAcYrw02Fan); + EXPECT_EQ(kHaierAcYrw02Fan, haier.getMode()); + + haier.setMode(kHaierAcYrw02Dry); + EXPECT_EQ(kHaierAcYrw02Dry, haier.getMode()); + + haier.setMode(kHaierAcYrw02Auto - 1); + EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); + + haier.setMode(kHaierAcYrw02Cool); + EXPECT_EQ(kHaierAcYrw02Cool, haier.getMode()); + + haier.setMode(kHaierAcYrw02Fan + 1); + EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); + + haier.setMode(255); + EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); +} + +TEST(TestHaierACYRW02Class, Temperature) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setTemp(kHaierAcMinTemp); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + + haier.setButton(kHaierAcYrw02ButtonPower); + haier.setTemp(kHaierAcMinTemp + 1); + EXPECT_EQ(kHaierAcMinTemp + 1, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + + haier.setTemp(kHaierAcMaxTemp); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + + haier.setTemp(kHaierAcMinTemp - 1); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, haier.getButton()); + + haier.setTemp(kHaierAcMaxTemp + 1); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + + haier.setTemp(23); + EXPECT_EQ(23, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, haier.getButton()); + haier.setButton(kHaierAcYrw02ButtonPower); + haier.setTemp(23); + EXPECT_EQ(23, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + + haier.setTemp(0); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, haier.getButton()); + + haier.setTemp(255); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, HealthMode) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setHealth(true); + EXPECT_TRUE(haier.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setHealth(false); + EXPECT_FALSE(haier.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, haier.getButton()); + + haier.setHealth(true); + EXPECT_TRUE(haier.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, Power) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setPower(true); + EXPECT_TRUE(haier.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setPower(false); + EXPECT_FALSE(haier.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + + haier.setPower(true); + EXPECT_TRUE(haier.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + + haier.off(); + EXPECT_FALSE(haier.getPower()); + haier.on(); + EXPECT_TRUE(haier.getPower()); +} + +TEST(TestHaierACYRW02Class, SleepMode) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setSleep(true); + EXPECT_TRUE(haier.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setSleep(false); + EXPECT_FALSE(haier.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); + + haier.setSleep(true); + EXPECT_TRUE(haier.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, TurboMode) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setTurbo(kHaierAcYrw02TurboOff); + EXPECT_EQ(kHaierAcYrw02TurboOff, haier.getTurbo()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + + haier.setTurbo(kHaierAcYrw02TurboLow); + EXPECT_EQ(kHaierAcYrw02TurboLow, haier.getTurbo()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + + haier.setTurbo(kHaierAcYrw02TurboHigh); + EXPECT_EQ(kHaierAcYrw02TurboHigh, haier.getTurbo()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + + haier.setTurbo(kHaierAcYrw02TurboOff); + EXPECT_EQ(kHaierAcYrw02TurboOff, haier.getTurbo()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, Fan) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setFan(kHaierAcYrw02FanAuto); + EXPECT_EQ(kHaierAcYrw02FanAuto, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + + haier.setFan(kHaierAcYrw02FanLow); + EXPECT_EQ(kHaierAcYrw02FanLow, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + + haier.setFan(kHaierAcYrw02FanHigh); + EXPECT_EQ(kHaierAcYrw02FanHigh, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + + haier.setFan(kHaierAcYrw02FanMed); + EXPECT_EQ(kHaierAcYrw02FanMed, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + + // Test unexpected values. + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setFan(0x00); + EXPECT_EQ(kHaierAcYrw02FanMed, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, Swing) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setSwing(kHaierAcYrw02SwingOff); + EXPECT_EQ(kHaierAcYrw02SwingOff, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + + haier.setSwing(kHaierAcYrw02SwingAuto); + EXPECT_EQ(kHaierAcYrw02SwingAuto, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + + haier.setSwing(kHaierAcYrw02SwingTop); + EXPECT_EQ(kHaierAcYrw02SwingTop, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + + haier.setSwing(kHaierAcYrw02SwingDown); + EXPECT_EQ(kHaierAcYrw02SwingDown, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + + // Test unexpected values. + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setSwing(0xFF); + EXPECT_EQ(kHaierAcYrw02SwingDown, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + + // Test the mode-dependant positions. + haier.setMode(kHaierAcYrw02Auto); + haier.setSwing(kHaierAcYrw02SwingMiddle); + EXPECT_EQ(kHaierAcYrw02SwingMiddle, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + haier.setMode(kHaierAcYrw02Heat); + haier.setSwing(kHaierAcYrw02SwingMiddle); + EXPECT_EQ(kHaierAcYrw02SwingBottom, haier.getSwing()); + haier.setSwing(kHaierAcYrw02SwingAuto); + EXPECT_EQ(kHaierAcYrw02SwingAuto, haier.getSwing()); + haier.setSwing(kHaierAcYrw02SwingBottom); + EXPECT_EQ(kHaierAcYrw02SwingBottom, haier.getSwing()); + haier.setMode(kHaierAcYrw02Cool); + haier.setSwing(kHaierAcYrw02SwingBottom); + EXPECT_EQ(kHaierAcYrw02SwingMiddle, haier.getSwing()); +} + +TEST(TestHaierACYRW02Class, MessageConstuction) { + IRHaierACYRW02 haier(0); + + EXPECT_EQ( + "Power: On, Button: 5 (Power), Mode: 0 (Auto), Temp: 25C," + " Fan: 10 (Auto), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," + " Health: On", + haier.toString()); + haier.setMode(kHaierAcYrw02Cool); + haier.setTemp(21); + haier.setFan(kHaierAcYrw02FanHigh); + EXPECT_EQ( + "Power: On, Button: 4 (Fan), Mode: 2 (Cool), Temp: 21C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," + " Health: On", + haier.toString()); + + haier.setSwing(kHaierAcYrw02SwingMiddle); + haier.setHealth(false); + haier.setSleep(true); + haier.setTurbo(kHaierAcYrw02TurboHigh); + EXPECT_EQ( + "Power: On, Button: 8 (Turbo), Mode: 2 (Cool), Temp: 21C," + " Fan: 2 (High), Turbo: 1 (High), Swing: 2 (Middle)," + " Sleep: On, Health: Off", + haier.toString()); +} + +// Decode "real" state messages. +TEST(TestHaierACYRW02Class, RealStates) { + uint8_t expectedState1[kHaierACYRW02StateLength] = { + 0xA6, 0xE1, 0x00, 0x00, 0x40, 0x20, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6E}; + + IRHaierACYRW02 haier(0); + haier.setRaw(expectedState1); + EXPECT_EQ( + "Power: On, Button: 7 (Health), Mode: 8 (Heat), Temp: 30C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 1 (Top), Sleep: Off," + " Health: Off", + haier.toString()); + + uint8_t expectedState2[kHaierACYRW02StateLength] = { + 0xA6, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x75}; + haier.setRaw(expectedState2); + EXPECT_EQ( + "Power: Off, Button: 5 (Power), Mode: 8 (Heat), Temp: 30C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," + " Health: Off", + haier.toString()); + + uint8_t expectedState3[kHaierACYRW02StateLength] = { + 0xA6, 0x02, 0x00, 0x02, 0x40, 0x20, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2B}; + haier.setRaw(expectedState3); + EXPECT_EQ( + "Power: On, Button: 1 (Temp Down), Mode: 2 (Cool), Temp: 16C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off," + " Health: On", + haier.toString()); + + // cool 25, health, fan auto, swing auto, sleep on + uint8_t expectedState4[kHaierACYRW02StateLength] = { + 0xA6, 0x9C, 0x00, 0x02, 0x40, 0xA8, 0x00, + 0x20, 0x80, 0x00, 0x00, 0x00, 0x0B, 0xD7}; + haier.setRaw(expectedState4); + EXPECT_EQ( + "Power: On, Button: 11 (Sleep), Mode: 2 (Cool), Temp: 25C," + " Fan: 10 (Auto), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On," + " Health: On", + haier.toString()); + + // cool 25, health, fan 3, swing auto, sleep on + uint8_t expectedState5[kHaierACYRW02StateLength] = { + 0xA6, 0x9C, 0x00, 0x02, 0x40, 0x27, 0x36, + 0x20, 0x80, 0x00, 0x00, 0x00, 0x04, 0x85}; + haier.setRaw(expectedState5); + EXPECT_EQ( + "Power: On, Button: 4 (Fan), Mode: 2 (Cool), Temp: 25C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On," + " Health: On", + haier.toString()); +} + +// Tests for decodeHaierAC(). + +// Decode normal "synthetic" messages. +TEST(TestDecodeHaierAC, NormalDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x01, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0xA7}; + + // With the specific decoder. + irsend.reset(); + irsend.sendHaierAC(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeHaierAC(&irsend.capture, kHaierACBits, true)); + EXPECT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + // With the all the decoders. + irsend.reset(); + irsend.sendHaierAC(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a "real" example message. +TEST(TestDecodeHaierAC, RealExample1) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #404 captured by kuzin2006 + uint16_t rawData[149] = { + 3030, 3044, 3030, 4304, 576, 1694, 550, 582, 552, 1704, 552, 714, 550, + 582, 550, 1706, 552, 582, 550, 1836, 552, 582, 578, 568, 550, 582, + 550, 714, 550, 582, 550, 582, 552, 582, 550, 1836, 552, 582, 552, + 580, 580, 1692, 550, 712, 552, 582, 550, 582, 552, 580, 550, 714, + 552, 582, 550, 582, 552, 582, 578, 698, 552, 580, 552, 582, 552, + 582, 552, 1836, 552, 580, 552, 582, 552, 582, 550, 714, 578, 568, + 550, 582, 550, 582, 552, 714, 550, 1706, 550, 1706, 550, 582, 550, + 714, 552, 582, 580, 566, 552, 582, 550, 714, 552, 580, 552, 580, + 552, 1706, 550, 714, 550, 582, 552, 582, 578, 568, 552, 712, 552, + 582, 550, 582, 550, 582, 550, 712, 552, 582, 550, 582, 552, 582, + 578, 722, 552, 1704, 550, 582, 550, 1706, 550, 736, 550, 582, 550, + 1706, 550, 1704, 552, 1704, 578}; + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x01, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0xA7}; + + irsend.sendRaw(rawData, 149, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRHaierAC haier(0); + haier.setRaw(irsend.capture.state); + EXPECT_EQ( + "Command: 1 (On), Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Current Time: 00:01, On Timer: Off, Off Timer: Off", + haier.toString()); +} + +// Decode a "real" example message. +TEST(TestDecodeHaierAC, RealExample2) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #404 captured by kuzin2006 + uint16_t rawData[149] = { + 3028, 3046, 3028, 4304, 576, 1694, 552, 582, 550, 1704, 552, 714, + 550, 582, 552, 1704, 550, 582, 550, 1836, 552, 582, 578, 1690, + 552, 1704, 552, 712, 550, 582, 550, 1706, 550, 1706, 552, 712, + 550, 582, 552, 582, 578, 1690, 552, 714, 552, 580, 552, 582, + 552, 582, 550, 712, 552, 582, 550, 582, 550, 582, 578, 698, + 552, 582, 550, 584, 550, 582, 552, 1836, 550, 582, 550, 582, + 550, 582, 550, 712, 578, 568, 550, 582, 550, 582, 550, 714, + 552, 1706, 550, 1706, 552, 580, 550, 714, 550, 582, 580, 568, + 550, 582, 550, 714, 550, 582, 550, 582, 550, 1706, 552, 712, + 550, 582, 550, 582, 580, 568, 552, 712, 550, 584, 550, 582, + 550, 584, 550, 712, 550, 582, 550, 582, 550, 582, 578, 722, + 550, 582, 552, 580, 552, 582, 550, 738, 550, 1706, 550, 1704, + 552, 582, 550, 582, 578}; + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x66, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0x0C}; + + irsend.sendRaw(rawData, 149, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRHaierAC haier(0); + haier.setRaw(irsend.capture.state); + EXPECT_EQ( + "Command: 6 (Temp Up), Mode: 0 (AUTO), Temp: 22C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Current Time: 00:01, On Timer: Off, Off Timer: Off", + haier.toString()); +} + +// Decode a "real" example message. +TEST(TestDecodeHaierAC, RealExample3) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #404 captured by kuzin2006 + uint16_t rawData[149] = { + 3030, 3044, 3030, 4302, 578, 1692, 550, 582, 550, 1706, 550, 714, + 550, 582, 552, 1706, 550, 582, 550, 1836, 552, 1706, 578, 1690, + 552, 1704, 552, 714, 550, 1706, 552, 1706, 550, 582, 550, 714, + 552, 582, 550, 582, 578, 1690, 550, 714, 552, 582, 552, 582, + 550, 582, 550, 714, 550, 584, 550, 582, 550, 582, 578, 700, + 552, 1706, 550, 582, 550, 582, 552, 1836, 550, 582, 550, 582, + 552, 1706, 550, 714, 578, 568, 552, 582, 552, 582, 550, 714, + 550, 1706, 550, 1706, 550, 582, 552, 712, 552, 582, 580, 568, + 550, 582, 550, 714, 550, 582, 550, 582, 550, 1706, 550, 714, + 550, 582, 550, 582, 578, 568, 552, 712, 552, 582, 550, 582, + 550, 582, 550, 712, 550, 584, 550, 582, 552, 582, 578, 722, + 552, 1704, 550, 582, 550, 1706, 550, 1862, 550, 1706, 550, 582, + 550, 1704, 552, 582, 578}; + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0xEC, 0x20, 0x09, 0x20, + 0xC0, 0x20, 0x00, 0xBA}; + + irsend.sendRaw(rawData, 149, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRHaierAC haier(0); + haier.setRaw(irsend.capture.state); + EXPECT_EQ( + "Command: 12 (Health), Mode: 0 (AUTO), Temp: 30C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: On, " + "Current Time: 00:09, On Timer: Off, Off Timer: Off", + haier.toString()); +} + +// Decode normal "synthetic" messages. +TEST(TestDecodeHaierAC_YRW02, NormalDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expectedState[kHaierACYRW02StateLength] = { + 0xA6, 0x12, 0x00, 0x02, 0x40, 0x20, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3F}; + + irsend.reset(); + irsend.sendHaierACYRW02(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HAIER_AC_YRW02, irsend.capture.decode_type); + EXPECT_EQ(kHaierACYRW02Bits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a "real" example message. +TEST(TestDecodeHaierAC_YRW02, RealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #485 captured by non7top + uint16_t rawData[229] = { + 2998, 3086, 2998, 4460, 568, 1640, 596, 492, 514, 1690, 590, 496, + 566, 532, 592, 1596, 570, 1618, 518, 584, 590, 538, 524, 536, + 568, 532, 590, 1596, 516, 612, 568, 538, 522, 1638, 586, 500, + 512, 614, 568, 538, 520, 538, 586, 538, 566, 540, 520, 538, + 586, 538, 522, 538, 588, 538, 568, 538, 520, 538, 586, 538, + 566, 538, 520, 540, 588, 1596, 590, 536, 568, 538, 520, 1592, + 640, 538, 520, 540, 588, 538, 568, 538, 516, 562, 566, 538, + 518, 542, 586, 540, 566, 1596, 590, 538, 566, 538, 516, 544, + 586, 538, 516, 542, 588, 540, 564, 540, 468, 590, 588, 538, + 566, 540, 466, 590, 588, 538, 514, 544, 588, 538, 566, 538, + 468, 1692, 606, 526, 466, 592, 588, 538, 568, 490, 588, 538, + 566, 540, 466, 592, 588, 538, 566, 538, 466, 592, 588, 538, + 568, 492, 586, 540, 566, 540, 468, 590, 588, 538, 568, 516, + 488, 590, 588, 538, 568, 492, 588, 538, 566, 518, 488, 590, + 588, 540, 564, 518, 490, 590, 588, 538, 562, 496, 588, 538, + 566, 518, 488, 590, 588, 538, 562, 522, 488, 588, 590, 538, + 560, 498, 588, 540, 564, 522, 486, 590, 590, 538, 560, 524, + 488, 588, 588, 1598, 514, 608, 564, 1600, 548, 536, 586, 538, + 568, 1594, 590, 1618, 578, 1606, 606, 1582, 590, 1596, 590, 1616, + 580}; + uint8_t expectedState[kHaierACYRW02StateLength] = { + 0xA6, 0x12, 0x00, 0x02, 0x40, 0x20, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3F}; + + irsend.sendRaw(rawData, 229, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC_YRW02, irsend.capture.decode_type); + EXPECT_EQ(kHaierACYRW02Bits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRHaierACYRW02 haier(0); + haier.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Button: 5 (Power), Mode: 2 (Cool), Temp: 17C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off," + " Health: On", + haier.toString()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp new file mode 100644 index 000000000..de0a4a2a1 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp @@ -0,0 +1,765 @@ +// Copyright 2018 David Conran + +#include "ir_Hitachi.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendHitachiAC(). + +// Test sending typical data only. +TEST(TestSendHitachiAC, SendData) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + irsend.reset(); + irsend.sendHitachiAC(hitachi_code); + EXPECT_EQ( + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s500m400s500" + "m400s100000", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendHitachiAC, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + irsend.reset(); + + irsend.sendHitachiAC(hitachi_code, kHitachiAcStateLength, 1); + EXPECT_EQ( + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s500m400s500" + "m400s100000" + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s500m400s500" + "m400s100000", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendHitachiAC, SendUnexpectedSizes) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_short_code[kHitachiAcStateLength - 1] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, + 0x80, 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00}; + uint8_t hitachi_long_code[kHitachiAcStateLength + 1] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC, 0xFF}; + irsend.reset(); + irsend.sendHitachiAC(hitachi_short_code, kHitachiAcStateLength - 1); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendHitachiAC(hitachi_long_code, kHitachiAcStateLength + 1); + ASSERT_EQ( + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s100000", + irsend.outputStr()); +} + +// Tests for IRHitachiAc class. +TEST(TestIRHitachiAcClass, SetAndGetPower) { + IRHitachiAc ac(0); + ac.on(); + EXPECT_TRUE(ac.getPower()); + ac.off(); + EXPECT_FALSE(ac.getPower()); + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestIRHitachiAcClass, SetAndGetSwing) { + IRHitachiAc ac(0); + ac.setSwingVertical(true); + ac.setSwingHorizontal(true); + EXPECT_TRUE(ac.getSwingVertical()); + EXPECT_TRUE(ac.getSwingHorizontal()); + ac.setSwingVertical(false); + EXPECT_FALSE(ac.getSwingVertical()); + EXPECT_TRUE(ac.getSwingHorizontal()); + ac.setSwingVertical(true); + EXPECT_TRUE(ac.getSwingVertical()); + EXPECT_TRUE(ac.getSwingHorizontal()); + ac.setSwingHorizontal(false); + EXPECT_TRUE(ac.getSwingVertical()); + EXPECT_FALSE(ac.getSwingHorizontal()); + ac.setSwingHorizontal(true); + EXPECT_TRUE(ac.getSwingHorizontal()); +} + +TEST(TestIRHitachiAcClass, SetAndGetTemp) { + IRHitachiAc ac(0); + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + ac.setTemp(kHitachiAcMinTemp); + EXPECT_EQ(kHitachiAcMinTemp, ac.getTemp()); + ac.setTemp(kHitachiAcMinTemp - 1); + EXPECT_EQ(kHitachiAcMinTemp, ac.getTemp()); + ac.setTemp(kHitachiAcMaxTemp); + EXPECT_EQ(kHitachiAcMaxTemp, ac.getTemp()); + ac.setTemp(kHitachiAcMaxTemp + 1); + EXPECT_EQ(kHitachiAcMaxTemp, ac.getTemp()); + ac.setTemp(64); + EXPECT_EQ(64, ac.getTemp()); +} + +TEST(TestIRHitachiAcClass, SetAndGetMode) { + IRHitachiAc ac(0); + ac.setMode(kHitachiAcCool); + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcCool, ac.getMode()); + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + EXPECT_EQ(kHitachiAcFanAuto, ac.getFan()); + ac.setMode(kHitachiAcFan); + EXPECT_EQ(kHitachiAcFan, ac.getMode()); + EXPECT_EQ(64, ac.getTemp()); + EXPECT_NE(kHitachiAcFanAuto, ac.getFan()); + ac.setMode(kHitachiAcHeat); + EXPECT_EQ(25, ac.getTemp()); + EXPECT_EQ(kHitachiAcHeat, ac.getMode()); + ac.setMode(kHitachiAcAuto); + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcAuto, ac.getMode()); + ac.setMode(kHitachiAcDry); + EXPECT_EQ(kHitachiAcDry, ac.getMode()); + EXPECT_NE(kHitachiAcFanAuto, ac.getFan()); +} + +TEST(TestIRHitachiAcClass, SetAndGetFan) { + IRHitachiAc ac(0); + ac.setMode(kHitachiAcCool); // All fan options are available in this mode. + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcFanAuto, ac.getFan()); + ac.setFan(kHitachiAcFanLow); + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); + ac.setFan(kHitachiAcFanHigh); + EXPECT_EQ(kHitachiAcFanHigh, ac.getFan()); + ac.setFan(kHitachiAcFanHigh + 1); + EXPECT_EQ(kHitachiAcFanHigh, ac.getFan()); + ac.setFan(0); + EXPECT_EQ(kHitachiAcFanAuto, ac.getFan()); + + ac.setMode(kHitachiAcFan); // No auto-fan in Fan mode. + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); + ac.setFan(kHitachiAcFanHigh); + EXPECT_EQ(kHitachiAcFanHigh, ac.getFan()); + + // Only Low and one higher fan settin in Dry mode. + ac.setMode(kHitachiAcDry); + EXPECT_EQ(kHitachiAcFanLow + 1, ac.getFan()); + ac.setFan(kHitachiAcFanHigh); + EXPECT_EQ(kHitachiAcFanLow + 1, ac.getFan()); + ac.setFan(kHitachiAcFanLow); + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); +} + +TEST(TestIRHitachiAcClass, HumanReadable) { + IRHitachiAc ac(0); + + ac.setMode(kHitachiAcHeat); + ac.setTemp(kHitachiAcMaxTemp); + ac.on(); + ac.setFan(kHitachiAcFanHigh); + ac.setSwingVertical(true); + EXPECT_EQ( + "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (HIGH), " + "Swing (Vertical): On, Swing (Horizontal): Off", + ac.toString()); + ac.setMode(kHitachiAcCool); + ac.setTemp(kHitachiAcMinTemp); + ac.setFan(kHitachiAcFanLow); + ac.setSwingVertical(false); + ac.setSwingHorizontal(true); + EXPECT_EQ( + "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 2 (LOW), " + "Swing (Vertical): Off, Swing (Horizontal): On", + ac.toString()); +} + +TEST(TestIRHitachiAcClass, ChecksumCalculation) { + IRHitachiAc ac(0); + + const uint8_t originalstate[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + uint8_t examplestate[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + + EXPECT_TRUE(IRHitachiAc::validChecksum(examplestate)); + EXPECT_EQ(0xAC, IRHitachiAc::calcChecksum(examplestate)); + + examplestate[kHitachiAcStateLength - 1] = + 0x12; // Make the existing checksum invalid + EXPECT_FALSE(IRHitachiAc::validChecksum(examplestate)); + EXPECT_EQ(0xAC, IRHitachiAc::calcChecksum(examplestate)); + ac.setRaw(examplestate); + // Extracting the state from the object should have a correct checksum. + EXPECT_TRUE(IRHitachiAc::validChecksum(ac.getRaw())); + EXPECT_STATE_EQ(originalstate, ac.getRaw(), kHitachiAcBits); + + examplestate[8] = 0x12; // Force a different checksum calc. + EXPECT_FALSE(IRHitachiAc::validChecksum(examplestate)); + EXPECT_EQ(0xFF, IRHitachiAc::calcChecksum(examplestate)); +} + +// Tests for decodeHitachiAC(). + +// Decode a synthetic HitachiAC message. +TEST(TestDecodeHitachiAC, NormalSynthetic) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + + irsend.reset(); + irsend.sendHitachiAC(hitachi_code); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAcBits); +} + +// Decode a 'real' HitachiAC message. +TEST(TestDecodeHitachiAC, NormalRealExample1) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/417 + // 'On' '16c' 'auto fan' 'cooling mode' + uint16_t rawData[451] = { + 3318, 1720, 400, 1276, 400, 432, 398, 434, 398, 434, 400, 432, + 398, 432, 398, 432, 398, 434, 398, 432, 398, 434, 400, 432, + 398, 434, 398, 1278, 398, 434, 398, 434, 396, 434, 398, 434, + 398, 432, 398, 434, 398, 432, 398, 1276, 426, 1252, 424, 408, + 424, 406, 424, 408, 426, 406, 398, 432, 398, 434, 398, 432, + 400, 432, 398, 1276, 426, 408, 424, 1252, 426, 1252, 424, 1250, + 426, 1252, 428, 1250, 426, 1252, 424, 406, 426, 1248, 428, 1252, + 426, 406, 426, 406, 424, 408, 400, 432, 400, 430, 400, 432, + 400, 430, 400, 432, 400, 1276, 400, 1276, 402, 1276, 400, 1276, + 400, 1276, 400, 1278, 400, 1276, 402, 1276, 402, 428, 402, 430, + 400, 430, 402, 1276, 400, 430, 402, 430, 400, 432, 402, 428, + 402, 1278, 400, 430, 402, 430, 402, 1276, 402, 428, 402, 430, + 402, 430, 400, 1276, 402, 430, 402, 430, 402, 430, 402, 430, + 402, 428, 402, 430, 404, 430, 402, 428, 402, 430, 402, 1276, + 402, 430, 402, 428, 402, 430, 400, 428, 402, 430, 402, 430, + 402, 430, 402, 430, 402, 428, 402, 430, 402, 1274, 402, 428, + 402, 430, 402, 430, 402, 430, 402, 430, 402, 428, 402, 428, + 402, 428, 404, 428, 404, 428, 402, 1276, 400, 430, 402, 430, + 400, 432, 400, 456, 374, 432, 400, 456, 404, 428, 404, 426, + 404, 428, 402, 428, 402, 430, 402, 430, 400, 432, 398, 434, + 376, 454, 378, 454, 380, 452, 378, 452, 404, 428, 406, 424, + 432, 398, 406, 426, 430, 402, 404, 428, 428, 402, 400, 430, + 400, 432, 398, 434, 398, 432, 398, 434, 372, 460, 374, 434, + 398, 432, 398, 434, 396, 434, 376, 456, 376, 456, 376, 456, + 376, 1300, 378, 454, 378, 452, 378, 454, 378, 454, 378, 454, + 378, 452, 378, 454, 400, 432, 402, 430, 402, 430, 402, 430, + 402, 428, 402, 430, 402, 430, 400, 430, 402, 430, 400, 432, + 400, 430, 400, 432, 400, 430, 402, 430, 400, 432, 398, 432, + 400, 430, 400, 432, 398, 432, 398, 434, 398, 432, 398, 432, + 400, 434, 398, 432, 398, 432, 398, 434, 398, 434, 396, 434, + 398, 434, 398, 432, 398, 434, 398, 432, 398, 456, 376, 454, + 376, 436, 396, 454, 376, 454, 378, 454, 376, 454, 376, 456, + 374, 458, 374, 1302, 374, 456, 374, 458, 374, 458, 376, 456, + 374, 456, 374, 456, 374, 456, 376, 456, 376, 456, 374, 458, + 374, 458, 374, 458, 372, 458, 372, 460, 374, 458, 372, 460, + 372, 460, 372, 460, 370, 462, 372, 460, 372, 460, 370, 462, + 370, 462, 356, 1320, 368, 464, 346, 1332, 356, 476, 368, 1310, + 366, 1312, 366, 464, 366, 466, 366}; + + irsend.reset(); + irsend.sendRaw(rawData, 451, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeHitachiAC(&irsend.capture)); + EXPECT_EQ(HITACHI_AC, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAcBits); + IRHitachiAc ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 1 (AUTO), " + "Swing (Vertical): Off, Swing (Horizontal): Off", + ac.toString()); +} + +// Decode another 'real' HitachiAC message. +TEST(TestDecodeHitachiAC, NormalRealExample2) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x10, + 0xC0, 0x02, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xD0}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/417 + // 'On' '32c' 'auto fan' 'heating mode' + uint16_t rawData[451] = { + 3322, 1718, 400, 1278, 398, 432, 402, 430, 400, 430, 402, 430, + 402, 430, 400, 432, 400, 432, 402, 430, 400, 430, 402, 430, + 400, 430, 402, 1276, 402, 430, 400, 430, 402, 430, 402, 430, + 402, 428, 402, 430, 400, 430, 402, 1278, 400, 1274, 402, 430, + 400, 432, 400, 430, 402, 430, 402, 430, 400, 430, 400, 432, + 402, 428, 402, 1276, 404, 428, 402, 1276, 402, 1274, 402, 1274, + 404, 1272, 402, 1274, 402, 1274, 404, 430, 402, 1274, 402, 1274, + 402, 430, 402, 430, 402, 430, 400, 430, 402, 430, 404, 428, + 402, 430, 400, 430, 402, 1274, 402, 1276, 402, 1276, 402, 1276, + 400, 1276, 402, 1272, 404, 1274, 402, 1272, 404, 430, 402, 430, + 402, 430, 402, 1274, 404, 428, 402, 428, 404, 430, 402, 430, + 402, 1274, 402, 430, 402, 430, 402, 1274, 402, 430, 402, 430, + 402, 428, 404, 428, 402, 430, 402, 430, 402, 1272, 406, 430, + 402, 428, 402, 430, 402, 430, 400, 1276, 400, 1276, 402, 430, + 402, 430, 402, 430, 402, 430, 402, 428, 402, 430, 402, 430, + 402, 430, 402, 430, 402, 430, 402, 430, 400, 430, 402, 1272, + 404, 430, 400, 430, 402, 430, 402, 428, 404, 430, 400, 430, + 402, 430, 402, 430, 402, 428, 402, 1276, 402, 428, 402, 1276, + 402, 430, 402, 428, 402, 430, 402, 430, 402, 430, 402, 428, + 402, 430, 402, 430, 402, 430, 402, 430, 402, 428, 402, 428, + 404, 430, 402, 428, 402, 430, 402, 428, 402, 430, 402, 432, + 402, 428, 402, 430, 402, 430, 402, 430, 400, 430, 400, 430, + 402, 430, 402, 430, 402, 426, 404, 430, 402, 430, 400, 428, + 404, 428, 404, 432, 398, 432, 400, 456, 376, 456, 376, 456, + 376, 1276, 402, 454, 378, 456, 376, 454, 378, 454, 402, 430, + 376, 454, 376, 456, 400, 430, 378, 454, 400, 432, 402, 430, + 376, 454, 376, 456, 376, 454, 400, 432, 374, 458, 400, 430, + 398, 434, 374, 456, 374, 456, 374, 458, 374, 458, 374, 456, + 352, 482, 372, 460, 374, 458, 364, 468, 352, 480, 372, 460, + 352, 480, 352, 480, 352, 480, 352, 480, 352, 454, 400, 432, + 376, 480, 374, 456, 374, 456, 378, 430, 404, 452, 376, 430, + 404, 428, 406, 426, 406, 426, 404, 426, 406, 428, 406, 426, + 430, 400, 430, 1244, 408, 424, 434, 398, 432, 400, 406, 424, + 432, 400, 406, 426, 430, 400, 432, 400, 432, 400, 430, 402, + 428, 402, 404, 428, 404, 426, 406, 426, 406, 426, 404, 428, + 428, 402, 404, 428, 404, 428, 402, 428, 404, 428, 402, 428, + 404, 428, 404, 1274, 402, 1274, 404, 428, 400, 1276, 402, 430, + 402, 430, 402, 430, 402, 430, 400}; + + irsend.reset(); + irsend.sendRaw(rawData, 451, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAcBits); + IRHitachiAc ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (HIGH), " + "Swing (Vertical): Off, Swing (Horizontal): Off", + ac.toString()); +} + +// Tests for sendHitachiAC1(). + +// Test sending typical data only. +TEST(TestSendHitachiAC1, SendData) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAc1StateLength] = {0xB2, 0xAE, 0x4D, 0x51, 0xF0, + 0x61, 0x84, 0x00, 0x00, 0x00, + 0x00, 0x30, 0xB8}; + irsend.reset(); + irsend.sendHitachiAC1(hitachi_code); + EXPECT_EQ( + "m3400s3400" + "m400s1250m400s500m400s1250m400s1250m400s500m400s500m400s1250m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s1250m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s1250m400s500m400s1250" + "m400s500m400s1250m400s500m400s1250m400s500m400s500m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s500m400s500m400s500m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s1250m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s1250m400s1250m400s500m400s500m400s500" + "m400s100000", + irsend.outputStr()); +} + +// Decode a 'real' HitachiAC1 message. +TEST(TestDecodeHitachiAC1, NormalRealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAc1StateLength] = {0xB2, 0xAE, 0x4D, 0x51, 0xF0, + 0x61, 0x84, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x98}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/453 + uint16_t rawData[211] = { + 3400, 3350, 450, 1250, 450, 400, 400, 1300, 400, 1300, 400, 400, + 450, 400, 400, 1300, 400, 400, 400, 1300, 400, 400, 450, 1250, + 400, 450, 400, 1300, 400, 1250, 450, 1250, 450, 400, 400, 450, + 400, 1250, 450, 400, 400, 400, 400, 1300, 400, 1300, 400, 400, + 450, 1250, 450, 400, 400, 1300, 400, 400, 450, 1250, 400, 400, + 450, 400, 400, 400, 450, 1250, 400, 1300, 450, 1250, 450, 1250, + 400, 1300, 400, 400, 450, 400, 400, 450, 350, 450, 400, 400, + 400, 1300, 400, 1300, 400, 400, 450, 400, 400, 400, 450, 400, + 400, 1300, 400, 1250, 450, 400, 400, 400, 450, 400, 400, 400, + 450, 1250, 450, 400, 400, 400, 450, 400, 400, 400, 450, 400, + 400, 400, 450, 400, 400, 400, 450, 400, 400, 400, 400, 450, + 400, 400, 400, 400, 450, 400, 400, 400, 450, 400, 400, 450, + 400, 400, 400, 400, 450, 400, 400, 400, 450, 400, 400, 450, + 400, 400, 400, 400, 400, 450, 400, 400, 400, 400, 450, 400, + 400, 400, 450, 400, 400, 400, 450, 400, 400, 400, 450, 400, + 400, 400, 450, 400, 400, 1300, 400, 400, 450, 400, 400, 400, + 400, 400, 450, 1250, 450, 400, 400, 400, 450, 1250, 450, 1250, + 450, 400, 400, 400, 450, 400, 400}; // UNKNOWN 828A89E1 + + irsend.reset(); + irsend.sendRaw(rawData, 211, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC1, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAc1Bits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAc1Bits); +} + +// Tests for sendHitachiAC2(). + +// Test sending typical data only. +TEST(TestSendHitachiAC2, SendData) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAc2StateLength] = { + 0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF, 0x00, 0x33, 0xCC, 0x49, 0xB6, + 0x22, 0xDD, 0x01, 0xFE, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F, 0x70, 0x00, 0xFF, 0x00, 0xFF, + 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F, 0x11, 0xEE, 0x00, 0xFF, 0x00, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00}; + irsend.reset(); + irsend.sendHitachiAC2(hitachi_code); + EXPECT_EQ( + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s1250m400s500m400s500m400s1250m400s1250" + "m400s1250m400s1250m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s1250" + "m400s1250m400s500m400s1250m400s1250m400s500m400s1250m400s1250m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s500m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s1250m400s500m400s500m400s1250m400s500m400s1250m400s500" + "m400s500m400s500m400s1250m400s1250m400s500m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s1250m400s1250m400s1250m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500" + "m400s1250m400s1250m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s1250m400s500m400s500m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s500m400s1250m400s1250m400s1250m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s100000", + irsend.outputStr()); +} + +// Decode a synthetic HitachiAC2 message. + +TEST(TestDecodeHitachiAC2, NormalSyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // ON - 32c cool (fan auto) + uint8_t hitachi_code[kHitachiAc2StateLength] = { + 0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF, 0x00, 0x33, 0xCC, 0x49, 0xB6, + 0x22, 0xDD, 0x01, 0xFE, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F, 0x70, 0x00, 0xFF, 0x00, 0xFF, + 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F, 0x11, 0xEE, 0x00, 0xFF, 0x00, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00}; + + irsend.reset(); + irsend.sendHitachiAC2(hitachi_code); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC2, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAc2Bits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAc2Bits); +} + +// Decode a 'real' HitachiAC2 message. +TEST(TestDecodeHitachiAC2, NormalRealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAc2StateLength] = { + 0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF, 0x00, 0x33, 0xCC, 0x49, 0xB6, + 0x22, 0xDD, 0x01, 0xFE, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F, 0x70, 0x00, 0xFF, 0x00, 0xFF, + 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F, 0x11, 0xEE, 0x00, 0xFF, 0x00, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/417 + uint16_t rawData[851] = { + // ON - 32c cool (fan auto) + 3432, 1654, 492, 1180, 488, 360, 486, 360, 486, 360, 486, 362, + 486, 362, 460, 360, 486, 362, 486, 362, 486, 360, 486, 362, + 486, 362, 486, 1184, 488, 362, 486, 360, 486, 362, 486, 362, + 486, 362, 460, 362, 486, 362, 486, 362, 484, 362, 486, 362, + 486, 362, 486, 362, 458, 362, 484, 362, 486, 362, 484, 364, + 484, 362, 486, 1184, 486, 362, 486, 1210, 488, 1210, 488, 1184, + 486, 1210, 488, 1210, 488, 1182, 488, 360, 488, 1208, 488, 1208, + 488, 1182, 488, 1208, 488, 1208, 488, 1208, 462, 1208, 490, 1208, + 488, 1208, 490, 332, 488, 360, 488, 360, 488, 360, 486, 360, + 486, 360, 486, 362, 460, 360, 486, 362, 486, 362, 486, 1210, + 488, 1210, 460, 362, 486, 362, 486, 1210, 488, 1210, 488, 1182, + 488, 1210, 488, 362, 486, 360, 488, 1182, 488, 1210, 488, 362, + 486, 362, 486, 360, 486, 1182, 488, 362, 486, 362, 486, 1210, + 488, 360, 486, 336, 486, 1210, 488, 1210, 488, 360, 486, 1182, + 488, 1210, 488, 360, 488, 1208, 488, 1182, 488, 362, 486, 362, + 486, 360, 486, 1210, 460, 362, 486, 360, 486, 362, 486, 1210, + 486, 362, 486, 1184, 488, 1208, 488, 360, 486, 1210, 488, 1184, + 488, 1208, 488, 362, 486, 1208, 462, 360, 486, 360, 486, 362, + 486, 360, 486, 362, 486, 360, 486, 334, 486, 1210, 488, 1208, + 488, 1210, 488, 1182, 488, 1208, 488, 1210, 488, 1182, 488, 1208, + 488, 360, 488, 360, 486, 360, 486, 334, 486, 362, 486, 362, + 486, 362, 486, 362, 486, 362, 486, 1182, 488, 1210, 486, 1210, + 488, 1210, 460, 1210, 488, 1210, 488, 1210, 488, 1184, 488, 360, + 486, 360, 486, 362, 486, 362, 486, 360, 460, 360, 486, 362, + 486, 362, 484, 1210, 488, 1182, 488, 1210, 488, 1210, 488, 1210, + 488, 1182, 488, 1208, 488, 1208, 488, 360, 460, 360, 486, 360, + 486, 360, 488, 360, 486, 362, 486, 362, 486, 334, 486, 1210, + 488, 1208, 488, 1210, 460, 1210, 488, 1208, 488, 1210, 488, 1182, + 488, 1208, 488, 360, 486, 362, 486, 360, 488, 334, 486, 360, + 486, 362, 486, 362, 486, 362, 486, 1210, 460, 1210, 488, 1210, + 488, 1210, 488, 1182, 488, 1210, 488, 1208, 488, 1182, 488, 360, + 486, 360, 486, 362, 486, 362, 486, 360, 486, 362, 460, 360, + 486, 362, 486, 1210, 486, 1212, 486, 1184, 488, 1210, 488, 1208, + 488, 1182, 488, 1208, 488, 1208, 488, 1208, 462, 1208, 488, 360, + 486, 362, 486, 1208, 488, 334, 486, 1208, 488, 360, 486, 360, + 486, 362, 486, 1182, 488, 1210, 488, 360, 486, 1210, 488, 334, + 486, 1208, 488, 1208, 488, 360, 486, 360, 486, 334, 486, 1210, + 488, 1210, 488, 1210, 460, 1210, 488, 360, 486, 1208, 488, 1182, + 490, 1208, 488, 360, 486, 360, 486, 360, 486, 360, 460, 360, + 486, 362, 486, 362, 486, 362, 486, 362, 486, 362, 486, 362, + 458, 362, 486, 1210, 488, 1210, 488, 1182, 488, 1210, 488, 1208, + 488, 1208, 462, 1208, 488, 1208, 488, 360, 486, 360, 486, 334, + 486, 360, 486, 362, 486, 362, 486, 362, 486, 362, 486, 1184, + 488, 1210, 488, 1210, 488, 1208, 462, 1210, 488, 1208, 488, 1208, + 488, 1182, 488, 360, 486, 360, 486, 360, 486, 362, 486, 360, + 460, 362, 486, 360, 488, 1208, 488, 1210, 488, 1184, 488, 1208, + 488, 1210, 488, 1182, 488, 1208, 488, 1208, 488, 360, 488, 1182, + 488, 1208, 488, 360, 488, 360, 488, 360, 486, 334, 486, 360, + 486, 362, 486, 362, 486, 360, 486, 1210, 488, 1182, 488, 1210, + 488, 1210, 488, 1182, 488, 1210, 488, 1210, 488, 360, 488, 334, + 486, 360, 488, 360, 486, 362, 486, 362, 486, 362, 486, 362, + 460, 1210, 488, 1210, 488, 1210, 488, 1184, 488, 1208, 488, 1208, + 490, 1182, 488, 360, 488, 360, 486, 362, 486, 1208, 488, 360, + 460, 362, 486, 362, 486, 1210, 488, 1210, 488, 1182, 488, 1208, + 488, 360, 488, 1208, 488, 1184, 486, 1210, 488, 360, 488, 360, + 486, 360, 460, 362, 486, 362, 486, 362, 486, 362, 484, 362, + 486, 362, 486, 1184, 488, 1210, 488, 1210, 488, 1182, 488, 1210, + 488, 1208, 488, 1208, 462, 1210, 488, 360, 486, 362, 486, 360, + 486, 362, 486, 334, 486, 362, 486, 360, 486, 362, 486, 1208, + 488, 1184, 488, 1208, 488, 1210, 488, 1182, 488, 1208, 488, 1208, + 488, 1208, 488, 1182, 488, 1208, 488, 1208, 488, 1182, 488, 1208, + 488, 1208, 488, 1182, 488, 1208, 488, 360, 488, 360, 486, 360, + 486, 362, 460, 362, 486, 362, 486, 362, 486, 360, 486, 1208, + 488, 1182, 488, 1208, 488, 1210, 488, 1182, 488, 1208, 490, 1208, + 488, 1208, 462, 360, 488, 360, 486, 360, 488, 360, 486, 360, + 486, 360, 486, 336, 486, 362, 486, 1210, 488, 1208, 488, 1182, + 488, 1208, 488, 1208, 488, 1208, 462, 1208, 490, 1206, 490, 360, + 488, 360, 488, 332, 486, 360, 488, 360, 486, 360, 488, 360, + 486, 360, 486, 1182, 488, 1208, 488, 1206, 492, 1208, 462, 1208, + 488, 1208, 488, 1208, 490, 1182, 490, 360, 486, 360, 486, 360, + 488, 360, 488, 360, 460, 360, 486, 362, 486, 360, 488}; + + irsend.reset(); + irsend.sendRaw(rawData, 851, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC2, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAc2Bits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAc2Bits); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_JVC_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_JVC_test.cpp similarity index 76% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_JVC_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_JVC_test.cpp index 0826b2268..c899fa8c6 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_JVC_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_JVC_test.cpp @@ -17,7 +17,8 @@ TEST(TestSendJVC, SendDataOnly) { "m8400s4200" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000", irsend.outputStr()); + "m525s21675", + irsend.outputStr()); } // Test sending with different repeats. @@ -26,31 +27,33 @@ TEST(TestSendJVC, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendJVC(0xC2B8, JVC_BITS, 1); // 1 repeat. + irsend.sendJVC(0xC2B8, kJvcBits, 1); // 1 repeat. EXPECT_EQ( "m8400s4200" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000" + "m525s21675" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000", irsend.outputStr()); - irsend.sendJVC(0xC2B8, JVC_BITS, 2); // 2 repeats. + "m525s34275", + irsend.outputStr()); + irsend.sendJVC(0xC2B8, kJvcBits, 2); // 2 repeats. EXPECT_EQ( "m8400s4200" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000" + "m525s21675" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000" + "m525s34275" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000", irsend.outputStr()); + "m525s34275", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendJVC, SendUsualSize) { +TEST(TestSendJVC, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); @@ -59,7 +62,8 @@ TEST(TestSendJVC, SendUsualSize) { EXPECT_EQ( "m8400s4200" "m525s525m525s525m525s525m525s525m525s525m525s525m525s525m525s525" - "m525s60000", irsend.outputStr()); + "m525s38475", + irsend.outputStr()); irsend.reset(); irsend.sendJVC(0x1234567890ABCDEF, 64); @@ -73,7 +77,8 @@ TEST(TestSendJVC, SendUsualSize) { "m525s1725m525s525m525s1725m525s525m525s1725m525s525m525s1725m525s1725" "m525s1725m525s1725m525s525m525s525m525s1725m525s1725m525s525m525s1725" "m525s1725m525s1725m525s1725m525s525m525s1725m525s1725m525s1725m525s1725" - "m525s60000", irsend.outputStr()); + "m525s10875", + irsend.outputStr()); } // Tests for encodeJVC(). @@ -100,9 +105,9 @@ TEST(TestDecodeJVC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendJVC(0xC2B8); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_EQ(0x43, irsend.capture.address); EXPECT_EQ(0x1D, irsend.capture.command); @@ -112,9 +117,9 @@ TEST(TestDecodeJVC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendJVC(irsend.encodeJVC(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xE099, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -124,9 +129,9 @@ TEST(TestDecodeJVC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendJVC(irsend.encodeJVC(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0x8080, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x1, irsend.capture.command); @@ -141,42 +146,42 @@ TEST(TestDecodeJVC, NormalDecodeWithRepeatAndStrict) { // Normal JVC 16-bit message with 2 repeats. irsend.reset(); - irsend.sendJVC(0xC2B8, JVC_BITS, 2); + irsend.sendJVC(0xC2B8, kJvcBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_EQ(0x43, irsend.capture.address); EXPECT_EQ(0x1D, irsend.capture.command); EXPECT_FALSE(irsend.capture.repeat); - irsend.makeDecodeResult(2 * JVC_BITS + 4); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + irsend.makeDecodeResult(2 * kJvcBits + 4); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_TRUE(irsend.capture.repeat); - irsend.makeDecodeResult(2 * JVC_BITS + 4 + 2 * JVC_BITS + 2); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + irsend.makeDecodeResult(2 * kJvcBits + 4 + 2 * kJvcBits + 2); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_TRUE(irsend.capture.repeat); // Simulate 'just' a JVC repeat command. // JVC VCR Power On from Global Cache, but modified to be a repeat message. - uint16_t gc_test[37] = {38000, 1, 1, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 61, 20, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[37] = {38000, 1, 1, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 61, 20, 20, 20, 61, 20, 20, 20, 61, 20, + 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.reset(); irsend.sendGC(gc_test, 37); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_EQ(0x43, irsend.capture.address); EXPECT_EQ(0x1D, irsend.capture.command); @@ -193,7 +198,7 @@ TEST(TestDecodeJVC, DecodeWithNonStrictValues) { irsend.sendJVC(0x0, 8); // Illegal value JVC 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 8, false)); EXPECT_EQ(JVC, irsend.capture.decode_type); @@ -206,7 +211,7 @@ TEST(TestDecodeJVC, DecodeWithNonStrictValues) { irsend.sendJVC(0x12345678, 32); // Illegal value JVC 32-bit message. irsend.makeDecodeResult(); // Should not pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -225,7 +230,7 @@ TEST(TestDecodeJVC, DecodeWithNonStrictValues) { irsend.makeDecodeResult(); // Shouldn't pass if strict off and the wrong expected bits. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, false)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, false)); // Re-decode with correct bit size. ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, 36, true)); @@ -264,16 +269,17 @@ TEST(TestDecodeJVC, DecodeGlobalCacheExample) { irsend.reset(); // JVC VCR Power On from Global Cache. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 61, 20, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; - // 38000,1,37,320,161,21,59,21,59,21,19,21,19,21,19,21,19,21,59,21,19,21,59,21,59,21,19,21,59,21,19,21,19,21,19,21,19,21,838,21,59,21,59,21,19,21,19,21,19,21,19,21,59,21,19,21,59,21,19,21,59,21,59,21,59,21,19,21,19,21,19,21,850}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 61, 20, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; + // 38000,1,37,320,161,21,59,21,59,21,19,21,19,21,19,21,19,21,59,21,19,21,59,21,59,21,19,21,59,21,19,21,19,21,19,21,19,21,838,21,59,21,59,21,19,21,19,21,19,21,19,21,59,21,19,21,59,21,19,21,59,21,59,21,59,21,19,21,19,21,19,21,850}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_EQ(0x43, irsend.capture.address); EXPECT_EQ(0x1D, irsend.capture.command); @@ -288,12 +294,13 @@ TEST(TestDecodeJVC, FailToDecodeNonJVCExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, false)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, false)); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp new file mode 100644 index 000000000..001f8bcf2 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp @@ -0,0 +1,518 @@ +// Copyright 2017 David Conran + +#include "ir_Kelvinator.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendKelvinator(). + +// Test sending typical data only. +TEST(TestSendKelvinator, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t kelv_code[kKelvinatorStateLength] = { + 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; + irsend.reset(); + irsend.sendKelvinator(kelv_code); + EXPECT_EQ( + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendKelvinator, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t kelv_code[kKelvinatorStateLength] = { + 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; + irsend.reset(); + + irsend.sendKelvinator(kelv_code, kKelvinatorStateLength, 1); + EXPECT_EQ( + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendKelvinator, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t kelv_short_code[15] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10}; + uint8_t kelv_long_code[17] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, + 0x00, 0xE0, 0x19, 0x0B, 0x80, 0x70, + 0x00, 0x00, 0x10, 0xf0, 0x00}; + irsend.reset(); + irsend.sendKelvinator(kelv_short_code, 15); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + // Shouldn't be different from the SendDataOnly. We just don't send the + // extra data. + irsend.sendKelvinator(kelv_long_code, 17); + ASSERT_EQ( + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950", + irsend.outputStr()); +} + +// Tests for IRKelvinatorAC class. + +TEST(TestKelvinatorClass, Power) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.on(); + EXPECT_TRUE(irkelv.getPower()); + + irkelv.off(); + EXPECT_FALSE(irkelv.getPower()); + + irkelv.setPower(true); + EXPECT_TRUE(irkelv.getPower()); + + irkelv.setPower(false); + EXPECT_FALSE(irkelv.getPower()); +} + +TEST(TestKelvinatorClass, Temperature) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setTemp(0); + EXPECT_EQ(kKelvinatorMinTemp, irkelv.getTemp()); + + irkelv.setTemp(255); + EXPECT_EQ(kKelvinatorMaxTemp, irkelv.getTemp()); + + irkelv.setTemp(kKelvinatorMinTemp); + EXPECT_EQ(kKelvinatorMinTemp, irkelv.getTemp()); + + irkelv.setTemp(kKelvinatorMaxTemp); + EXPECT_EQ(kKelvinatorMaxTemp, irkelv.getTemp()); + + irkelv.setTemp(kKelvinatorMinTemp - 1); + EXPECT_EQ(kKelvinatorMinTemp, irkelv.getTemp()); + + irkelv.setTemp(kKelvinatorMaxTemp + 1); + EXPECT_EQ(kKelvinatorMaxTemp, irkelv.getTemp()); + + irkelv.setTemp(17); + EXPECT_EQ(17, irkelv.getTemp()); + + irkelv.setTemp(21); + EXPECT_EQ(21, irkelv.getTemp()); + + irkelv.setTemp(25); + EXPECT_EQ(25, irkelv.getTemp()); + + irkelv.setTemp(29); + EXPECT_EQ(29, irkelv.getTemp()); +} + +TEST(TestKelvinatorClass, OperatingMode) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setTemp(24); + irkelv.setMode(kKelvinatorAuto); + EXPECT_EQ(kKelvinatorAuto, irkelv.getMode()); + EXPECT_EQ(kKelvinatorAutoTemp, irkelv.getTemp()); + + irkelv.setMode(kKelvinatorCool); + EXPECT_EQ(kKelvinatorCool, irkelv.getMode()); + + irkelv.setMode(kKelvinatorHeat); + EXPECT_EQ(kKelvinatorHeat, irkelv.getMode()); + + irkelv.setTemp(24); + irkelv.setMode(kKelvinatorDry); + EXPECT_EQ(kKelvinatorDry, irkelv.getMode()); + EXPECT_EQ(kKelvinatorAutoTemp, irkelv.getTemp()); + + irkelv.setMode(kKelvinatorFan); + EXPECT_EQ(kKelvinatorFan, irkelv.getMode()); + + irkelv.setMode(kKelvinatorHeat + 1); + EXPECT_EQ(kKelvinatorAuto, irkelv.getMode()); + + irkelv.setMode(255); + EXPECT_EQ(kKelvinatorAuto, irkelv.getMode()); +} + +TEST(TestKelvinatorClass, VaneSwing) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setSwingHorizontal(true); + irkelv.setSwingVertical(false); + + irkelv.setSwingHorizontal(true); + EXPECT_TRUE(irkelv.getSwingHorizontal()); + EXPECT_FALSE(irkelv.getSwingVertical()); + + irkelv.setSwingVertical(true); + EXPECT_TRUE(irkelv.getSwingHorizontal()); + EXPECT_TRUE(irkelv.getSwingVertical()); + + irkelv.setSwingHorizontal(false); + EXPECT_FALSE(irkelv.getSwingHorizontal()); + EXPECT_TRUE(irkelv.getSwingVertical()); + + irkelv.setSwingVertical(false); + EXPECT_FALSE(irkelv.getSwingHorizontal()); + EXPECT_FALSE(irkelv.getSwingVertical()); +} + +TEST(TestKelvinatorClass, QuietMode) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setQuiet(true); + EXPECT_TRUE(irkelv.getQuiet()); + + irkelv.setQuiet(false); + EXPECT_FALSE(irkelv.getQuiet()); + + irkelv.setQuiet(true); + EXPECT_TRUE(irkelv.getQuiet()); +} + +TEST(TestKelvinatorClass, IonFilter) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setIonFilter(true); + EXPECT_TRUE(irkelv.getIonFilter()); + + irkelv.setIonFilter(false); + EXPECT_FALSE(irkelv.getIonFilter()); + + irkelv.setIonFilter(true); + EXPECT_TRUE(irkelv.getIonFilter()); +} + +TEST(TestKelvinatorClass, Light) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setLight(true); + EXPECT_TRUE(irkelv.getLight()); + + irkelv.setLight(false); + EXPECT_FALSE(irkelv.getLight()); + + irkelv.setLight(true); + EXPECT_TRUE(irkelv.getLight()); +} + +TEST(TestKelvinatorClass, XFan) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setXFan(true); + EXPECT_TRUE(irkelv.getXFan()); + + irkelv.setXFan(false); + EXPECT_FALSE(irkelv.getXFan()); + + irkelv.setXFan(true); + EXPECT_TRUE(irkelv.getXFan()); +} + +TEST(TestKelvinatorClass, TurboFan) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setTurbo(true); + EXPECT_TRUE(irkelv.getTurbo()); + + irkelv.setTurbo(false); + EXPECT_FALSE(irkelv.getTurbo()); + + irkelv.setFan(2); + irkelv.setTurbo(true); + EXPECT_TRUE(irkelv.getTurbo()); + + // Turbo mode is turned off if the temperature is changed. + irkelv.setFan(3); + EXPECT_FALSE(irkelv.getTurbo()); + + // But only when it is changed, not set to the same value again. + irkelv.setTurbo(true); + irkelv.setFan(3); + EXPECT_TRUE(irkelv.getTurbo()); +} + +TEST(TestKelvinatorClass, FanSpeed) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setFan(0); + EXPECT_EQ(0, irkelv.getFan()); + + irkelv.setFan(255); + EXPECT_EQ(kKelvinatorFanMax, irkelv.getFan()); + + irkelv.setFan(kKelvinatorFanMax); + EXPECT_EQ(kKelvinatorFanMax, irkelv.getFan()); + + irkelv.setFan(kKelvinatorFanMax + 1); + EXPECT_EQ(kKelvinatorFanMax, irkelv.getFan()); + + irkelv.setFan(kKelvinatorFanMax - 1); + EXPECT_EQ(kKelvinatorFanMax - 1, irkelv.getFan()); + + irkelv.setFan(1); + EXPECT_EQ(1, irkelv.getFan()); + + irkelv.setFan(1); + EXPECT_EQ(1, irkelv.getFan()); + + irkelv.setFan(3); + EXPECT_EQ(3, irkelv.getFan()); +} + +TEST(TestKelvinatorClass, Checksums) { + uint8_t kelv_code[kKelvinatorStateLength] = { + 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; + + EXPECT_TRUE(IRKelvinatorAC::validChecksum(kelv_code)); + // Change the array so the checksum is invalid. + kelv_code[0] ^= 0xFF; + EXPECT_FALSE(IRKelvinatorAC::validChecksum(kelv_code)); + // Restore the previous change, and change another byte. + kelv_code[0] ^= 0xFF; + kelv_code[4] ^= 0xFF; + EXPECT_FALSE(IRKelvinatorAC::validChecksum(kelv_code)); + kelv_code[4] ^= 0xFF; + // Change something in the 2nd block. + kelv_code[10] ^= 0xFF; + EXPECT_FALSE(IRKelvinatorAC::validChecksum(kelv_code)); + kelv_code[10] ^= 0xFF; + EXPECT_TRUE(IRKelvinatorAC::validChecksum(kelv_code)); +} + +TEST(TestKelvinatorClass, SetAndGetRaw) { + IRKelvinatorAC irkelv(0); + uint8_t initialState[kKelvinatorStateLength] = { + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xA0, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xA0}; + uint8_t expectedState[kKelvinatorStateLength] = { + 0x08, 0x05, 0x20, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x08, 0x05, 0x20, 0x70, 0x00, 0x00, 0x00, 0x70}; + + EXPECT_STATE_EQ(initialState, irkelv.getRaw(), kKelvinatorBits); + // toggle the power state. + irkelv.setPower(!irkelv.getPower()); + irkelv.setTemp(21); + irkelv.setLight(true); + EXPECT_STATE_EQ(expectedState, irkelv.getRaw(), kKelvinatorBits); + irkelv.setRaw(initialState); + EXPECT_STATE_EQ(initialState, irkelv.getRaw(), kKelvinatorBits); +} + +TEST(TestKelvinatorClass, HumanReadable) { + IRKelvinatorAC irkelv(0); + + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), Turbo: Off, " + "Quiet: Off, XFan: Off, IonFilter: Off, Light: Off, " + "Swing (Horizontal): Off, Swing (Vertical): Off", + irkelv.toString()); + irkelv.on(); + irkelv.setMode(kKelvinatorCool); + irkelv.setTemp(25); + irkelv.setFan(kKelvinatorFanMax); + irkelv.setXFan(true); + irkelv.setIonFilter(true); + irkelv.setLight(true); + irkelv.setSwingHorizontal(true); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 25C, Fan: 5 (MAX), Turbo: Off, " + "Quiet: Off, XFan: On, IonFilter: On, Light: On, " + "Swing (Horizontal): On, Swing (Vertical): Off", + irkelv.toString()); +} + +TEST(TestKelvinatorClass, MessageConstuction) { + IRKelvinatorAC irkelv(0); + IRsendTest irsend(4); + irkelv.begin(); + irsend.begin(); + + irkelv.setFan(1); + irkelv.setMode(kKelvinatorCool); + irkelv.setTemp(27); + irkelv.setSwingVertical(false); + irkelv.setSwingHorizontal(true); + irkelv.setIonFilter(true); + irkelv.setQuiet(false); + irkelv.setLight(false); + irkelv.setPower(true); + irkelv.setTurbo(false); + irkelv.setXFan(true); + + // Check everything for kicks. + EXPECT_EQ(1, irkelv.getFan()); + EXPECT_EQ(kKelvinatorCool, irkelv.getMode()); + EXPECT_EQ(27, irkelv.getTemp()); + EXPECT_FALSE(irkelv.getSwingVertical()); + EXPECT_TRUE(irkelv.getSwingHorizontal()); + EXPECT_TRUE(irkelv.getIonFilter()); + EXPECT_FALSE(irkelv.getQuiet()); + EXPECT_FALSE(irkelv.getLight()); + EXPECT_TRUE(irkelv.getPower()); + EXPECT_FALSE(irkelv.getTurbo()); + EXPECT_TRUE(irkelv.getXFan()); + + irsend.reset(); + irsend.sendKelvinator(irkelv.getRaw()); + EXPECT_EQ( + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s1530m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s1530m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950", + irsend.outputStr()); +} + +// Decode a synthetic Kelvinator message. +TEST(TestDecodeKelvinator, NormalSynthetic) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t kelv_code[kKelvinatorStateLength] = { + 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; + irsend.reset(); + irsend.sendKelvinator(kelv_code); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(KELVINATOR, irsend.capture.decode_type); + ASSERT_EQ(kKelvinatorBits, irsend.capture.bits); + EXPECT_STATE_EQ(kelv_code, irsend.capture.state, kKelvinatorBits); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_LG_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_LG_test.cpp similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_LG_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_LG_test.cpp index fbdaf7126..8ab24a731 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_LG_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_LG_test.cpp @@ -1,8 +1,8 @@ // Copyright 2017 David Conran +#include "ir_LG.h" #include "IRsend.h" #include "IRsend_test.h" -#include "ir_LG.h" #include "gtest/gtest.h" // Tests for calcLGChecksum() @@ -30,23 +30,25 @@ TEST(TestSendLG, SendDataOnly) { irsend.reset(); irsend.sendLG(0x4B4AE51); EXPECT_EQ( - "m8000s4000" + "m8500s4250" "m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s1600m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s550m550s1600m550s1600m550s1600m550s550" "m550s550m550s1600m550s550m550s1600m550s550m550s550m550s550m550s1600" - "m550s108050", irsend.outputStr()); + "m550s50300", + irsend.outputStr()); irsend.reset(); - irsend.sendLG(0xB4B4AE51, LG32_BITS); + irsend.sendLG(0xB4B4AE51, kLg32Bits); EXPECT_EQ( "m4480s4480" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560m560s1680" - "m560s108080" - "m8950s2250m550s108050", irsend.outputStr()); + "m560s44800" + "m8950s2250m550s96300", + irsend.outputStr()); } // Test sending with different repeats. @@ -55,43 +57,46 @@ TEST(TestSendLG, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendLG(0x4B4AE51, LG_BITS, 1); + irsend.sendLG(0x4B4AE51, kLgBits, 1); EXPECT_EQ( - "m8000s4000" + "m8500s4250" "m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s1600m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s550m550s1600m550s1600m550s1600m550s550" "m550s550m550s1600m550s550m550s1600m550s550m550s550m550s550m550s1600" - "m550s108050" - "m8000s2250m550s108050", irsend.outputStr()); + "m550s50300" + "m8500s2250m550s96750", + irsend.outputStr()); irsend.reset(); - irsend.sendLG(0xB4B4AE51, LG32_BITS, 1); + irsend.sendLG(0xB4B4AE51, kLg32Bits, 1); EXPECT_EQ( "m4480s4480" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560m560s1680" - "m560s108080" - "m8950s2250m550s108050" - "m8950s2250m550s108050", irsend.outputStr()); + "m560s44800" + "m8950s2250m550s96300" + "m8950s2250m550s96300", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendLG, SendUsualSize) { +TEST(TestSendLG, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); irsend.reset(); irsend.sendLG(0x0, 31); EXPECT_EQ( - "m8000s4000" + "m8500s4250" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550" - "m550s108050", irsend.outputStr()); + "m550s60650", + irsend.outputStr()); irsend.reset(); irsend.sendLG(0x0, 64); @@ -105,8 +110,9 @@ TEST(TestSendLG, SendUsualSize) { "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s108080" - "m8950s2250m550s108050", irsend.outputStr()); + "m560s26880" + "m8950s2250m550s96300", + irsend.outputStr()); } // Tests for encodeLG(). @@ -132,11 +138,11 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { // Normal LG 28-bit message. irsend.reset(); - irsend.sendLG(0x4B4AE51, LG_BITS); + irsend.sendLG(0x4B4AE51, kLgBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x4B4AE51, irsend.capture.value); EXPECT_EQ(0x4B, irsend.capture.address); EXPECT_EQ(0x4AE5, irsend.capture.command); @@ -144,11 +150,11 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { // Normal LG 32-bit message. irsend.reset(); - irsend.sendLG(0xB4B4AE51, LG32_BITS); + irsend.sendLG(0xB4B4AE51, kLg32Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0xB4B4AE51, irsend.capture.value); EXPECT_EQ(0xB4B, irsend.capture.address); EXPECT_EQ(0x4AE5, irsend.capture.command); @@ -158,9 +164,9 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { irsend.reset(); irsend.sendLG(irsend.encodeLG(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x700992, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -168,11 +174,11 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { // Synthesised Normal LG 32-bit message. irsend.reset(); - irsend.sendLG(irsend.encodeLG(0x800, 0x8000), LG32_BITS); + irsend.sendLG(irsend.encodeLG(0x800, 0x8000), kLg32Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0x80080008, irsend.capture.value); EXPECT_EQ(0x800, irsend.capture.address); EXPECT_EQ(0x8000, irsend.capture.command); @@ -187,11 +193,11 @@ TEST(TestDecodeLG, NormalDecodeWithRepeatAndStrict) { // Normal LG 28-bit message with 2 repeats. irsend.reset(); - irsend.sendLG(irsend.encodeLG(0x07, 0x99), LG_BITS, 2); + irsend.sendLG(irsend.encodeLG(0x07, 0x99), kLgBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x700992, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -199,11 +205,11 @@ TEST(TestDecodeLG, NormalDecodeWithRepeatAndStrict) { // Normal LG 32-bit message with 2 repeats. irsend.reset(); - irsend.sendLG(irsend.encodeLG(0x07, 0x99), LG32_BITS, 2); + irsend.sendLG(irsend.encodeLG(0x07, 0x99), kLg32Bits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0x700992, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -221,30 +227,30 @@ TEST(TestDecodeLG, DecodeWithNonStrictValues) { irsend.reset(); irsend.sendLG(0x1); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); // Illegal LG 32-bit message value. irsend.reset(); - irsend.sendLG(0x1111111, LG32_BITS); + irsend.sendLG(0x1111111, kLg32Bits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0x1111111, irsend.capture.value); EXPECT_EQ(0x11, irsend.capture.address); EXPECT_EQ(0x1111, irsend.capture.command); EXPECT_FALSE(irsend.capture.repeat); irsend.reset(); - irsend.sendLG(0x1111111, LG32_BITS); + irsend.sendLG(0x1111111, kLg32Bits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); } // Decode unsupported LG message sizes. @@ -259,10 +265,10 @@ TEST(TestDecodeLG, DecodeWithNonStrictSizes) { irsend.sendLG(irsend.encodeLG(0x07, 0x99), 16); irsend.makeDecodeResult(); // Should fail when unexpected against different bit sizes. - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, 16, false)); @@ -277,10 +283,10 @@ TEST(TestDecodeLG, DecodeWithNonStrictSizes) { irsend.sendLG(0x123456789, 36); // Illegal value LG 36-bit message. irsend.makeDecodeResult(); // Should fail when unexpected against different bit sizes. - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, 36, false)); EXPECT_EQ(LG, irsend.capture.decode_type); @@ -317,22 +323,21 @@ TEST(TestDecodeLG, DecodeGlobalCacheExample) { IRrecv irrecv(4); irsend.begin(); -// TODO(anyone): Find a Global Cache example of the LG 28-bit message. + // TODO(anyone): Find a Global Cache example of the LG 28-bit message. irsend.reset(); // LG (32-bit) code from Global Cache. - uint16_t gc_test[75] = {38000, 1, 69, 341, 170, 21, 64, 21, 21, 21, 64, - 21, 64, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, - 21, 21, 21, 64, 21, 64, 21, 21, 21, 64, 21, 21, - 21, 21, 21, 64, 21, 21, 21, 64, 21, 21, 21, 64, - 21, 64, 21, 64, 21, 21, 21, 21, 21, 64, 21, 21, - 21, 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 1517, - 341, 85, 21, 3655}; + uint16_t gc_test[75] = { + 38000, 1, 69, 341, 170, 21, 64, 21, 21, 21, 64, 21, 64, 21, 21, + 21, 64, 21, 21, 21, 21, 21, 64, 21, 21, 21, 64, 21, 64, 21, + 21, 21, 64, 21, 21, 21, 21, 21, 64, 21, 21, 21, 64, 21, 21, + 21, 64, 21, 64, 21, 64, 21, 21, 21, 21, 21, 64, 21, 21, 21, + 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 1517, 341, 85, 21, 3655}; irsend.sendGC(gc_test, 75); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0xB4B4AE51, irsend.capture.value); EXPECT_EQ(0xB4B, irsend.capture.address); EXPECT_EQ(0x4AE5, irsend.capture.command); @@ -347,12 +352,71 @@ TEST(TestDecodeLG, FailToDecodeNonLGExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeLG(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); +} + +// Tests for sendLG2(). + +// Test sending typical data only. +TEST(TestSendLG2, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendLG2(0x880094D); + EXPECT_EQ( + "m3200s9850" + "m550s1600m550s550m550s550m550s550m550s1600m550s550m550s550m550s550" + "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" + "m550s1600m550s550m550s550m550s1600m550s550m550s1600m550s550m550s550" + "m550s1600m550s1600m550s550m550s1600" + "m550s55250", + irsend.outputStr()); +} + +TEST(TestDecodeLG2, SyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendLG2(0x880094D); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture)); + ASSERT_EQ(LG2, irsend.capture.decode_type); + EXPECT_EQ(kLgBits, irsend.capture.bits); + EXPECT_EQ(0x880094D, irsend.capture.value); +} + +// Verify decoding of LG variant 2 messages. +TEST(TestDecodeLG2, RealLG2Example) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // From issue #548 + uint16_t rawData[59] = { + 3154, 9834, 520, 1634, 424, 606, 424, 568, 462, 570, 462, 1564, + 508, 568, 458, 544, 500, 546, 508, 530, 508, 532, 506, 566, + 464, 568, 460, 578, 464, 568, 464, 532, 506, 552, 474, 1592, + 506, 568, 460, 570, 462, 1564, 506, 606, 424, 1640, 424, 616, + 422, 570, 462, 1616, 460, 1584, 500, 544, 506, 1598, 490}; // UNKNOWN + // F6D13AE8 + irsend.sendRaw(rawData, 59, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture)); + ASSERT_EQ(LG2, irsend.capture.decode_type); + EXPECT_EQ(kLgBits, irsend.capture.bits); + EXPECT_EQ(0x880094D, irsend.capture.value); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp new file mode 100644 index 000000000..041109fb8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp @@ -0,0 +1,342 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// LL AAA SSSSS EEEEEEE RRRRRR TTTTTTT AAA GGGG +// LL AAAAA SS EE RR RR TTT AAAAA GG GG +// LL AA AA SSSSS EEEEE RRRRRR TTT AA AA GG +// LL AAAAAAA SS EE RR RR TTT AAAAAAA GG GG +// LLLLLLL AA AA SSSSS EEEEEEE RR RR TTT AA AA GGGGGG + +// Tests for sendLasertag(). + +// Test sending simplest case data only. +TEST(TestSendLasertag, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendLasertag(0x1); // Red 1 + EXPECT_EQ( + "m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333" + "s333m333s333m333s333m333s666m333s100000", + irsend.outputStr()); + + irsend.reset(); + irsend.sendLasertag(0x2); // Red 2 + EXPECT_EQ( + "m333s333m333s333m333s333m333s333m333s333m333s333m333s333" + "m333s333m333s333m333s333m333s666m666s100333", + irsend.outputStr()); + + irsend.reset(); + irsend.sendLasertag(0x51); // Green 1 + // Raw: (21) + // m364s364m332s336m384s276m332s364m332s304m416s584m692s724m640s360m304s332m392s612m380, + EXPECT_EQ( + // m364s364m332s336m384s276m332s364m332s304m416s584 + // m692s724m640s360m304s332m392s612m380 + "m333s333m333s333m333s333m333s333m333s333m333s666" + "m666s666m666s333m333s333m333s666m333s100000", + irsend.outputStr()); + + irsend.reset(); + // Raw: (19) + // m332s308m412s280m360s336m332s304m444s248m332s644m744s612m696s692m668s636m360 + irsend.sendLasertag(0x55); // Green 5 + EXPECT_EQ( + // m332s308m412s280m360s336m332s304m444s248m332s644 + // m744s612m696s692m668s636m360 + "m333s333m333s333m333s333m333s333m333s333m333s666" + "m666s666m666s666m666s666m333s100000", + irsend.outputStr()); +} + +TEST(TestSendLasertag, SendDataWithRepeat) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendLasertag(0x1, kLasertagBits, 1); // Red 1, one repeat. + EXPECT_EQ( + "m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333s333" + "m333s333m333s333m333s333m333s666m333s100000" + "m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333s333" + "m333s333m333s333m333s333m333s666m333s100000", + irsend.outputStr()); + + irsend.reset(); + irsend.sendLasertag(0x52, kLasertagBits, 2); // Green 2, two repeats. + EXPECT_EQ( + "m333s333m333s333m333s333m333s333m333s333m333s666m666s666m666s333" + "m333s666m666s100333" + "m333s333m333s333m333s333m333s333m333s333m333s666m666s666m666s333" + "m333s666m666s100333" + "m333s333m333s333m333s333m333s333m333s333m333s666m666s666m666s333" + "m333s666m666s100333", + irsend.outputStr()); +} + +TEST(TestSendLasertag, SmallestMessageSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendLasertag(0x1555); // Alternating bit pattern will be the smallest. + // i.e. 7 actual 'mark' pulses, which is a rawlen of 13. + EXPECT_EQ("m0s333m666s666m666s666m666s666m666s666m666s666m666s666m333s100000", + irsend.outputStr()); +} + +// Tests for decodeLasertag(). + +// Decode normal Lasertag messages. +TEST(TestDecodeLasertag, NormalSyntheticDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Normal Lasertag 13-bit message. + irsend.reset(); + irsend.sendLasertag(0x01); // Red 1 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x01, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit 1 + EXPECT_EQ(0x0, irsend.capture.command); // Team Red + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendLasertag(0x02); // Red 2 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit 2 + EXPECT_EQ(0x0, irsend.capture.command); // Team Red + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendLasertag(0x06); // Red 6 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x06, irsend.capture.value); + EXPECT_EQ(0x6, irsend.capture.address); // Unit 6 + EXPECT_EQ(0x0, irsend.capture.command); // Team Red + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendLasertag(0x51); // Green 1 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x51, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit 1 + EXPECT_EQ(0x5, irsend.capture.command); // Team Green + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendLasertag(0x56); // Green 6 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x56, irsend.capture.value); + EXPECT_EQ(0x6, irsend.capture.address); // Unit + EXPECT_EQ(0x5, irsend.capture.command); // Team + EXPECT_FALSE(irsend.capture.repeat); +} + +// Example data taken from: https://github.com/z3t0/Arduino-IRremote/issues/532 +TEST(TestDecodeLasertag, RealExamples) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t green3[21] = {360, 364, 272, 360, 420, 248, 360, 360, 332, 308, 388, + 612, 692, 696, 636, 360, 332, 700, 300, 308, 416}; + irsend.sendRaw(green3, 21, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x53, irsend.capture.value); + EXPECT_EQ(0x3, irsend.capture.address); // Unit + EXPECT_EQ(0x5, irsend.capture.command); // Team + + irsend.reset(); + uint16_t green1[21] = {364, 364, 332, 336, 384, 276, 332, 364, 332, 304, 416, + 584, 692, 724, 640, 360, 304, 332, 392, 612, 380}; + irsend.sendRaw(green1, 21, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x51, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit + EXPECT_EQ(0x5, irsend.capture.command); // Team + + irsend.reset(); + uint16_t green4[19] = {336, 304, 412, 280, 360, 360, 304, 308, 420, 276, + 332, 636, 744, 620, 688, 724, 640, 360, 304}; + irsend.sendRaw(green4, 19, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x54, irsend.capture.value); + EXPECT_EQ(0x4, irsend.capture.address); // Unit + EXPECT_EQ(0x5, irsend.capture.command); // Team + + irsend.reset(); + uint16_t unit15[25] = {280, 360, 360, 308, 332, 388, 308, 332, 360, + 308, 360, 360, 304, 304, 412, 284, 304, 692, + 364, 360, 276, 336, 416, 276, 328}; + irsend.sendRaw(unit15, 25, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x0F, irsend.capture.value); + EXPECT_EQ(0xF, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_1[23] = {406, 262, 384, 374, 256, 354, 306, 366, + 252, 442, 256, 374, 358, 336, 278, 438, + 246, 340, 380, 292, 304, 688, 746}; + irsend.sendRaw(red_unit2_1, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_2[23] = {302, 306, 302, 392, 196, 476, 278, 352, + 304, 348, 278, 438, 226, 382, 328, 366, + 252, 458, 196, 392, 302, 688, 644}; + irsend.sendRaw(red_unit2_2, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_3[23] = {196, 432, 304, 348, 328, 386, 304, 326, + 302, 370, 252, 442, 272, 356, 278, 374, + 276, 438, 274, 352, 302, 668, 622}; + irsend.sendRaw(red_unit2_3, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_4[23] = {304, 390, 328, 324, 324, 346, 350, 364, + 300, 330, 320, 310, 324, 388, 242, 366, + 354, 318, 354, 340, 244, 726, 670}; + irsend.sendRaw(red_unit2_4, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit1_1_issue532[25] = { + 368, 352, 336, 308, 388, 276, 364, 356, 280, 360, 332, 336, 360, + 360, 308, 300, 416, 280, 356, 360, 312, 328, 336, 636, 424}; + irsend.sendRaw(red_unit1_1_issue532, 25, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x01, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit1_2_issue532[25] = { + 328, 400, 272, 360, 388, 280, 360, 364, 272, 364, 332, 336, 332, + 388, 304, 308, 388, 280, 356, 364, 272, 368, 384, 612, 408}; + irsend.sendRaw(red_unit1_2_issue532, 25, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x01, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit1_3_issue532[25] = { + 416, 284, 356, 336, 328, 336, 384, 308, 328, 368, 304, 308, 412, + 280, 328, 368, 272, 368, 376, 312, 332, 392, 276, 700, 272}; + irsend.sendRaw(red_unit1_3_issue532, 25, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x01, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_1_issue532[23] = {308, 340, 408, 284, 332, 388, 276, 336, + 356, 340, 332, 360, 300, 364, 360, 304, + 280, 444, 276, 336, 384, 640, 696}; + irsend.sendRaw(red_unit2_1_issue532, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_2_issue532[23] = {332, 308, 388, 280, 328, 420, 308, 304, + 384, 308, 332, 364, 272, 368, 384, 276, + 364, 360, 308, 332, 384, 612, 696}; + irsend.sendRaw(red_unit2_2_issue532, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_3_issue532[23] = {392, 332, 340, 272, 448, 276, 364, 328, + 340, 272, 396, 296, 340, 380, 312, 296, + 400, 272, 364, 352, 284, 720, 672}; + irsend.sendRaw(red_unit2_3_issue532, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp new file mode 100644 index 000000000..6c99b9904 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp @@ -0,0 +1,143 @@ +// Copyright 2018 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendLutron(). + +// Test sending typical data only. +TEST(TestSendLutron, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + irsend.sendLutron(0); + EXPECT_EQ("m2288s230080", irsend.outputStr()); + irsend.sendLutron(0xAAAAAAAAA); // Longest possible sequence. (I think) + EXPECT_EQ( + "m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288" + "m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288" + "m2288s2288m2288s2288m2288s2288m2288s152288", + irsend.outputStr()); + irsend.sendLutron(0x7FFFFFFFF); + EXPECT_EQ("m82368s150000", irsend.outputStr()); + irsend.sendLutron(0x7F88BD120); + EXPECT_EQ( + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendLutron, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + // Send a command with 0 repeats. + irsend.sendLutron(0x7F88BD120, kLutronBits, 0); + EXPECT_EQ( + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440", + irsend.outputStr()); + // Send a command with 1 repeat. + irsend.sendLutron(0x7F88BD120, kLutronBits, 1); + EXPECT_EQ( + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440" + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440", + irsend.outputStr()); + // Send a command with 3 repeats. + irsend.sendLutron(0x7F88BD120, kLutronBits, 3); + EXPECT_EQ( + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440" + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440" + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440" + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440", + irsend.outputStr()); +} + +// Tests for decodeLutron(). +// Decode normal Lutron messages. +TEST(TestDecodeLutron, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Synthesised Normal Lutron messages. + irsend.reset(); + irsend.sendLutron(0x7F88BD120); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x7F88BD120, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendLutron(0x0DEADBEEF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x0DEADBEEF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendLutron(0x0); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendLutron(0x7FFFFFFFF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x7FFFFFFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +// Decode a documented example +TEST(TestDecodeLutron, DocumentedExampleFullOff) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Full Off code. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/515 + uint16_t rawData[14] = {20518, 6839, 2280, 6839, 2280, 2280, 9119, + 2280, 2280, 6839, 2280, 4560, 2280, 11399}; + irsend.reset(); + irsend.sendRaw(rawData, 14, 40); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x7F88BD120, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + uint16_t pronto[18] = {0x0000, 0x0069, 0x0007, 0x0000, 0x032a, 0x010e, + 0x005a, 0x010e, 0x005a, 0x005a, 0x0168, 0x005a, + 0x005a, 0x010e, 0x005a, 0x00b4, 0x005a, 0x01c2}; + irsend.reset(); + irsend.sendPronto(pronto, 18); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x7F88BD120, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp new file mode 100644 index 000000000..9ecd0eac1 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp @@ -0,0 +1,124 @@ +// Copyright 2017 David Conran +// Copyright 2018 Brett T. Warden + +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// MM MM WW WW MM MM +// MMM MMM WW WW MMM MMM +// MM M MM WW W WW MM M MM +// MM MM WWW WWW MM MM +// MM MM WW WW MM MM + +// Tests for sendMWM(). + +// Test sending simplest case data only. +TEST(TestSendMWM, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + unsigned char test1[] = {0x96, 0x19, 0x10, 0x24, 0x0A, + 0x6B, 0x20, 0x03, 0x82}; + /* + ++--+-++-- + +-++--+++- + +++++-+++- + +++-++-++- + ++-+-++++- + +--+-+--+- + ++++++-++- + +--++++++- + ++-+++++-- + */ + irsend.sendMWM(test1, sizeof(test1), 0); + EXPECT_EQ( + "m834s834m417s417m834s834" + "m417s417m834s834m1251s417" + "m2085s417m1251s417" + "m1251s417m834s417m834s417" + "m834s417m417s417m1668s417" + "m417s834m417s417m417s834m417s417" + "m2502s417m834s417" + "m417s834m2502s417" + "m834s417m2085s30834", irsend.outputStr()); + + irsend.reset(); + unsigned char test2[] = { + 0x99, 0x26, 0x66, 0x6E, 0xD1, 0x42, 0x06, + 0x20, 0xD0, 0x32, 0xF0, 0x0B + // +-++--++-- + // ++--++-++- + // ++--++--+- + // ++---+--+- + // +-+++-+--- + // ++-++++-+- + // ++--+++++- + // ++++++-++- + // +++++-+--- + // ++-++--++- + // +++++----- + // +--+-++++- + }; + irsend.sendMWM(test2, sizeof(test2), 0); + EXPECT_EQ( + "m417s417m834s834m834s834" + "m834s834m834s417m834s417" + "m834s834m834s834m417s417" + "m834s1251m417s834m417s417" + "m417s417m1251s417m417s1251" + "m834s417m1668s417m417s417" + "m834s834m2085s417" + "m2502s417m834s417" + "m2085s417m417s1251" + "m834s417m834s834m834s417" + "m2085s2085" + "m417s834m417s417m1668s30417", irsend.outputStr()); +} + +// Tests for decodeMWM(). + +// Example data +TEST(TestDecodeMWM, RealExamples) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t short_code[] = { + 915, 793, 488, 366, 915, 793, 427, 366, 915, 793, 1281, 427, + 2136, 366, 1281, 366, 915, 793, 427, 854, 854, 366, 1281, 854, + 1708, 366, 488, 793, 854, 427, 427, 427, 427, 366, 854, 427, + 2563, 366, 488, 793, 2563, 366, 488, 2075, 427, 34057}; + unsigned char short_expected[] = {0x96, 0x19, 0x10, 0x36, 0x0C, + 0x53, 0x02, 0x03, 0xDF}; + irsend.sendRaw(short_code, sizeof(short_code) / sizeof(short_code[0]), 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MWM, irsend.capture.decode_type); + EXPECT_EQ(8 * sizeof(short_expected) / sizeof(short_expected[0]), + irsend.capture.bits); + EXPECT_STATE_EQ(short_expected, irsend.capture.state, irsend.capture.bits); + + irsend.reset(); + uint16_t long_code[] = { + 427, 427, 854, 854, 854, 793, 915, 793, 854, 366, 915, 366, 854, + 854, 854, 793, 488, 366, 915, 1220, 427, 793, 488, 366, 488, 366, + 1281, 427, 427, 1220, 915, 366, 1708, 366, 488, 366, 854, 854, 2136, + 366, 2563, 366, 854, 427, 2136, 366, 488, 1220, 854, 427, 854, 793, + 915, 366, 2136, 2075, 427, 793, 488, 366, 1708, 30517}; + unsigned char long_expected[] = {0x99, 0x26, 0x66, 0x6E, 0xD1, 0x42, + 0x06, 0x20, 0xD0, 0x32, 0xF0, 0x0B}; + irsend.sendRaw(long_code, sizeof(long_code) / sizeof(long_code[0]), 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MWM, irsend.capture.decode_type); + EXPECT_EQ(8 * sizeof(long_expected) / sizeof(long_expected[0]), + irsend.capture.bits); + EXPECT_STATE_EQ(long_expected, irsend.capture.state, irsend.capture.bits); +} + +// vim: et:ts=2:sw=2 diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp new file mode 100644 index 000000000..e1c3da83d --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp @@ -0,0 +1,162 @@ +// Copyright 2017 David Conran + +#include "ir_Magiquest.h" +#include "IRrecv.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for encodeMagiQuest() +TEST(TestEncodeMagiQuest, General) { + IRsendTest irsend(0); + EXPECT_EQ(0x0, irsend.encodeMagiQuest(0x0, 0x0)); + EXPECT_EQ(0x10001, irsend.encodeMagiQuest(0x1, 0x1)); + EXPECT_EQ(0x20003, irsend.encodeMagiQuest(0x2, 0x3)); + EXPECT_EQ(0x123456781234, irsend.encodeMagiQuest(0x12345678, 0x1234)); + EXPECT_EQ(0xFFFFFFFFFFFF, irsend.encodeMagiQuest(0xFFFFFFFF, 0xFFFF)); +} + +// Tests for sendMagiQuest() + +// Test sending typical data only. +TEST(TestSendMagiQuest, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendMagiQuest(0x0); + EXPECT_EQ( + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s100850", + irsend.outputStr()); + irsend.reset(); + irsend.sendMagiQuest(0x123456789ABC); + EXPECT_EQ( + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" + "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" + "m280s850m580s600m280s850m580s600m280s850m580s600m580s600m280s850" + "m280s850m580s600m580s600m580s600m580s600m280s850m280s850m280s850" + "m580s600m280s850m280s850m580s600m580s600m280s850m580s600m280s850" + "m580s600m280s850m580s600m580s600m580s600m580s600m280s850m280s100850", + irsend.outputStr()); +} + +// Test sending typical data only. +TEST(TestSendMagiQuest, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendMagiQuest(0x12345678ABCD, kMagiquestBits, 2); // two repeats. + EXPECT_EQ( + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" + "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" + "m280s850m580s600m280s850m580s600m280s850m580s600m580s600m280s850" + "m280s850m580s600m580s600m580s600m580s600m280s850m280s850m280s850" + "m580s600m280s850m580s600m280s850m580s600m280s850m580s600m580s600" + "m580s600m580s600m280s850m280s850m580s600m580s600m280s850m580s100600" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" + "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" + "m280s850m580s600m280s850m580s600m280s850m580s600m580s600m280s850" + "m280s850m580s600m580s600m580s600m580s600m280s850m280s850m280s850" + "m580s600m280s850m580s600m280s850m580s600m280s850m580s600m580s600" + "m580s600m580s600m280s850m280s850m580s600m580s600m280s850m580s100600" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" + "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" + "m280s850m580s600m280s850m580s600m280s850m580s600m580s600m280s850" + "m280s850m580s600m580s600m580s600m580s600m280s850m280s850m280s850" + "m580s600m280s850m580s600m280s850m580s600m280s850m580s600m580s600" + "m580s600m580s600m280s850m280s850m580s600m580s600m280s850m580s100600", + irsend.outputStr()); +} + +// Tests for decodeMagiQuest(). + +// Decode normal "synthetic" messages. +TEST(TestDecodeMagiQuest, NormalDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendMagiQuest(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kMagiquestBits, true)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendMagiQuest(irsend.encodeMagiQuest(0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kMagiquestBits, true)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x10001, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x1, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendMagiQuest(irsend.encodeMagiQuest(0x12345678, 0xABCD)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kMagiquestBits, true)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x12345678ABCD, irsend.capture.value); + EXPECT_EQ(0x12345678, irsend.capture.address); + EXPECT_EQ(0xABCD, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Do the last one again, & use the full decoder, not just protocol specific. + irsend.reset(); + irsend.sendMagiQuest(irsend.encodeMagiQuest(0x12345678, 0xABCD)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x12345678ABCD, irsend.capture.value); +} + +// Decode a "real" example message. +TEST(TestDecodeMagiQuest, RealExamples) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[111] = {262, 842, 298, 858, 238, 866, 240, 890, 238, 866, + 240, 862, 244, 886, 242, 860, 246, 858, 554, 604, + 264, 840, 560, 622, 266, 836, 552, 604, 556, 626, + 262, 866, 240, 864, 264, 838, 268, 862, 244, 886, + 536, 620, 530, 628, 554, 628, 532, 624, 244, 858, + 552, 604, 264, 840, 268, 862, 266, 838, 268, 888, + 240, 864, 242, 860, 268, 862, 244, 860, 236, 868, + 272, 832, 264, 866, 240, 890, 532, 598, 268, 834, + 294, 836, 270, 834, 262, 866, 272, 858, 238, 866, + 534, 622, 268, 836, 270, 860, 268, 862, 526, 604, + 264, 892, 530, 600, 268, 836, 586, 598, 270, 834, + 556}; // Data from PR #365 captured by coolacid + + irsend.sendRaw(rawData, 111, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x560F40020455, irsend.capture.value); + EXPECT_EQ(0x560F4002, irsend.capture.address); // Wand ID + EXPECT_EQ(0x0455, irsend.capture.command); // Magnitude + EXPECT_FALSE(irsend.capture.repeat); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp new file mode 100644 index 000000000..5d5f5e932 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp @@ -0,0 +1,651 @@ +// Copyright 2017 David Conran + +#include "ir_Midea.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendMidea(). + +// Test sending typical data only. +TEST(TestSendMidea, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMidea(0x0); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMidea(0x55AA55AA55AA); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMidea(0xFFFFFFFFFFFF); + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5600" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s5600", + irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendMidea, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMidea(0x55AA55AA55AA, kMideaBits, 1); // 1 repeat. + EXPECT_EQ( + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600" + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600", + irsend.outputStr()); + irsend.sendMidea(0x55AA55AA55AA, kMideaBits, 2); // 2 repeats. + EXPECT_EQ( + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600" + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600" + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600", + irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendMidea, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMidea(0x0, 8); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMidea(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560" + "m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s5600" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560m560s1680" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680" + "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" + "m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" + "m560s5600", + irsend.outputStr()); + + // Bit sizes must be a multiple of 8. + irsend.reset(); + irsend.sendMidea(0x0, 17); + EXPECT_EQ("", irsend.outputStr()); +} + +// Tests for IRMideaAC class. + +// Tests for controlling the power state. +TEST(TestMideaACClass, Power) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1026FFFFFE2); // Power off. + + midea.on(); + EXPECT_TRUE(midea.getPower()); + + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); + + midea.off(); + EXPECT_FALSE(midea.getPower()); + EXPECT_EQ(0xA1026FFFFFE2, midea.getRaw()); + + midea.setPower(true); + EXPECT_TRUE(midea.getPower()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); + + midea.setPower(false); + EXPECT_FALSE(midea.getPower()); + EXPECT_EQ(0xA1026FFFFFE2, midea.getRaw()); +} + +// Tests for the various Checksum routines. +TEST(TestMideaACClass, Checksums) { + IRMideaAC midea(0); + midea.begin(); + + // Known good states + EXPECT_EQ(0x62, IRMideaAC::calcChecksum(0xA1826FFFFF62)); + EXPECT_EQ(0x70, IRMideaAC::calcChecksum(0xA18177FFFF70)); + // Now without the checksum part. + EXPECT_EQ(0x62, IRMideaAC::calcChecksum(0xA1826FFFFF00)); + EXPECT_EQ(0x70, IRMideaAC::calcChecksum(0xA18177FFFF00)); + // Made up values. + EXPECT_EQ(0x00, IRMideaAC::calcChecksum(0x000000000000)); + EXPECT_EQ(0xDF, IRMideaAC::calcChecksum(0x1234567890AB)); + EXPECT_EQ(0xA0, IRMideaAC::calcChecksum(0xFFFFFFFFFFFF)); + // Larger than expected value (full 64bit) + EXPECT_EQ(0xDF, IRMideaAC::calcChecksum(0xFF1234567890AB)); + EXPECT_EQ(0xDF, IRMideaAC::calcChecksum(0x551234567890AB)); + + // Validity tests. + EXPECT_TRUE(IRMideaAC::validChecksum(0xA1826FFFFF62)); + EXPECT_TRUE(IRMideaAC::validChecksum(0xA18177FFFF70)); + EXPECT_FALSE(IRMideaAC::validChecksum(0x1234567890AB)); + + // Doing a setRaw() with a bad state should make a valid checksum on getRaw(). + midea.setRaw(0xA1826FFFFF00); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); +} + +TEST(TestMideaACClass, OperatingMode) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); // Auto mode already set. + midea.setMode(kMideaACAuto); + EXPECT_EQ(kMideaACAuto, midea.getMode()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); // State shouldn't have changed. + + midea.setMode(kMideaACCool); + EXPECT_EQ(kMideaACCool, midea.getMode()); + EXPECT_EQ(0xA1806FFFFF61, midea.getRaw()); + + midea.setMode(kMideaACAuto); + EXPECT_EQ(kMideaACAuto, midea.getMode()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); + + midea.setMode(kMideaACHeat); + EXPECT_EQ(kMideaACHeat, midea.getMode()); + EXPECT_EQ(0xA1836FFFFF63, midea.getRaw()); + + midea.setMode(kMideaACDry); + EXPECT_EQ(kMideaACDry, midea.getMode()); + EXPECT_EQ(0xA1816FFFFF60, midea.getRaw()); + + midea.setMode(kMideaACFan); + EXPECT_EQ(kMideaACFan, midea.getMode()); + EXPECT_EQ(0xA1846FFFFF66, midea.getRaw()); + + midea.setMode(255); + EXPECT_EQ(kMideaACAuto, midea.getMode()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); +} + +TEST(TestMideaACClass, FanSpeed) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); // Auto mode already set. + EXPECT_EQ(kMideaACFanAuto, midea.getFan()); + + midea.setFan(kMideaACFanLow); + EXPECT_EQ(kMideaACFanLow, midea.getFan()); + EXPECT_EQ(0xA18A6FFFFF6C, midea.getRaw()); + + midea.setFan(255); // Setting an unexpected value defaults to auto. + EXPECT_EQ(kMideaACFanAuto, midea.getFan()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); + + midea.setFan(kMideaACFanMed); + EXPECT_EQ(kMideaACFanMed, midea.getFan()); + EXPECT_EQ(0xA1926FFFFF7C, midea.getRaw()); + + midea.setFan(kMideaACFanHigh); + EXPECT_EQ(kMideaACFanHigh, midea.getFan()); + EXPECT_EQ(0xA19A6FFFFF74, midea.getRaw()); + + midea.setFan(kMideaACFanAuto); + EXPECT_EQ(kMideaACFanAuto, midea.getFan()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); +} + +TEST(TestMideaACClass, Temperature) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); // 77F / 25C + EXPECT_EQ(77, midea.getTemp()); // F + EXPECT_EQ(77, midea.getTemp(false)); // F + EXPECT_EQ(25, midea.getTemp(true)); // F + + midea.setTemp(0); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp()); + EXPECT_EQ(0xA18260FFFF6C, midea.getRaw()); + + midea.setTemp(255); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp()); + EXPECT_EQ(0xA18278FFFF78, midea.getRaw()); + + midea.setTemp(0, true); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp()); + EXPECT_EQ(0xA18260FFFF6C, midea.getRaw()); + + midea.setTemp(255, true); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp()); + EXPECT_EQ(0xA18278FFFF78, midea.getRaw()); + + // fahrenheit min/max etc. + midea.setTemp(kMideaACMinTempF); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp()); + + midea.setTemp(kMideaACMaxTempF); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp()); + + midea.setTemp(kMideaACMinTempF - 1); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp()); + + midea.setTemp(kMideaACMaxTempF + 1); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp()); + + // celsius min/max etc. + midea.setTemp(kMideaACMinTempC, true); + EXPECT_EQ(kMideaACMinTempC, midea.getTemp(true)); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp(false)); + + midea.setTemp(kMideaACMaxTempC, true); + EXPECT_EQ(kMideaACMaxTempC, midea.getTemp(true)); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp(false)); + + midea.setTemp(kMideaACMinTempC - 1, true); + EXPECT_EQ(kMideaACMinTempC, midea.getTemp(true)); + + midea.setTemp(kMideaACMaxTempC + 1, true); + EXPECT_EQ(kMideaACMaxTempC, midea.getTemp(true)); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp(false)); + + // General changes. + midea.setTemp(17, true); // C + EXPECT_EQ(17, midea.getTemp(true)); // C + EXPECT_EQ(63, midea.getTemp(false)); // F + + midea.setTemp(21, true); // C + EXPECT_EQ(21, midea.getTemp(true)); // C + EXPECT_EQ(70, midea.getTemp(false)); // F + + midea.setTemp(25, true); // C + EXPECT_EQ(25, midea.getTemp(true)); // C + EXPECT_EQ(77, midea.getTemp(false)); // F + + midea.setTemp(30, true); // C + EXPECT_EQ(30, midea.getTemp(true)); // C + EXPECT_EQ(86, midea.getTemp(false)); // F + + midea.setTemp(80, false); // F + EXPECT_EQ(26, midea.getTemp(true)); // C + EXPECT_EQ(80, midea.getTemp(false)); // F + + midea.setTemp(70); // F + EXPECT_EQ(21, midea.getTemp(true)); // C + EXPECT_EQ(70, midea.getTemp(false)); // F + EXPECT_EQ(70, midea.getTemp()); // F +} + +// Tests for controlling the sleep state. +TEST(TestMideaACClass, Sleep) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); // Sleep off. + + EXPECT_FALSE(midea.getSleep()); + midea.setSleep(true); + EXPECT_TRUE(midea.getSleep()); + EXPECT_EQ(0xA1C26FFFFF22, midea.getRaw()); + midea.setSleep(false); + EXPECT_FALSE(midea.getSleep()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); +} + +TEST(TestMideaACClass, HumanReadableOutput) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); + EXPECT_EQ( + "Power: On, Mode: 2 (AUTO), Temp: 25C/77F, Fan: 0 (AUTO), " + "Sleep: Off", + midea.toString()); + midea.off(); + midea.setTemp(25); + midea.setFan(kMideaACFanHigh); + midea.setMode(kMideaACDry); + midea.setSleep(true); + EXPECT_EQ("Power: Off, Mode: 1 (DRY), Temp: 16C/62F, Fan: 3 (HI), Sleep: On", + midea.toString()); + + midea.setRaw(0xA19867FFFF7E); + EXPECT_EQ("Power: On, Mode: 0 (COOL), Temp: 20C/69F, Fan: 3 (HI), Sleep: Off", + midea.toString()); +} + +// Tests for decodeMidea(). + +// Decode normal Midea messages with strict set. +TEST(TestDecodeMidea, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Midea 48-bit message. + irsend.reset(); + irsend.sendMidea(0x1234567890DF); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0x1234567890DF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Midea 48-bit message. + irsend.reset(); + irsend.sendMidea(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Midea 48-bit message. + irsend.reset(); + irsend.sendMidea(0xFFFFFFFFFFA0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFA0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Real Midea 48-bit message via just decode(). + // i.e. No conficts with other decoders. + irsend.reset(); + irsend.sendMidea(0xA18263FFFF6E); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated Midea messages. +TEST(TestDecodeMidea, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Midea 48-bit message with 2 repeats. + irsend.reset(); + irsend.sendMidea(0xA18263FFFF6E, kMideaBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.makeDecodeResult(2 * (2 * kMideaBits + 4)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); + + irsend.makeDecodeResult(4 * (2 * kMideaBits + 4)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); +} + +// Decode unsupported Midea messages. +TEST(TestDecodeMidea, DecodeWithNonStrictSizes) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMidea(0x12, 8); // Illegal value Midea 8-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, 8, false)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x12, irsend.capture.value); + + irsend.reset(); + irsend.sendMidea(0x12345678, 32); // Illegal value Midea 32-bit message. + irsend.makeDecodeResult(); + // Shouldn't pass with strict when we ask for less bits than we got. + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, 32, false)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + + // Decode should fail if asked to decode non-multiples of 8 bits. + irsend.reset(); + irsend.sendMidea(0x123456, kMideaBits, 2); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, 9, false)); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeMidea, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal size Midea 64-bit message. + irsend.sendMidea(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, 64, false)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); +} + +// Fail to decode a non-Midea example via GlobalCache +TEST(TestDecodeMidea, FailToDecodeNonMideaExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Modified a few entries to unexpected values, based on previous test case. + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; + irsend.sendGC(gc_test, 39); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kMideaBits, false)); +} + +// Decode against a real capture reported by a user. See issue #354 +TEST(TestDecodeMidea, DecodeRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + uint16_t rawData[199] = { + 4366, 4470, 498, 1658, 522, 554, 498, 1658, 496, 580, 498, 580, + 498, 578, 498, 580, 498, 1658, 498, 1658, 498, 578, 498, 578, + 498, 580, 496, 582, 496, 578, 498, 1658, 498, 580, 498, 580, + 498, 1656, 498, 1656, 500, 580, 498, 578, 502, 576, 500, 1656, + 498, 1656, 500, 1654, 500, 1656, 500, 1656, 498, 1658, 498, 1656, + 500, 1658, 498, 1656, 498, 1656, 500, 1656, 500, 1654, 500, 1578, + 578, 1658, 498, 1656, 500, 1658, 498, 1656, 498, 1656, 500, 578, + 498, 1638, 516, 1656, 500, 578, 500, 1656, 500, 1656, 498, 1658, + 522, 554, 500, 5258, 4366, 4472, 498, 580, 498, 1658, 498, 580, + 498, 1656, 500, 1600, 556, 1658, 500, 1656, 500, 578, 498, 578, + 522, 1634, 498, 1588, 568, 1658, 498, 1656, 500, 1654, 498, 580, + 498, 1658, 498, 1658, 498, 580, 496, 578, 500, 1654, 500, 1636, + 518, 1656, 500, 578, 520, 558, 498, 578, 498, 580, 498, 576, + 500, 578, 498, 580, 498, 578, 498, 578, 498, 580, 498, 578, + 498, 580, 498, 580, 520, 556, 498, 580, 496, 580, 498, 578, + 500, 578, 498, 1658, 498, 580, 498, 578, 498, 1656, 500, 578, + 498, 580, 498, 580, 498, 1656, 522}; + irsend.sendRaw(rawData, 199, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp new file mode 100644 index 000000000..7b8eb2192 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp @@ -0,0 +1,1118 @@ +// Copyright 2017 David Conran +// Copyright 2018 denxhun + +#include "ir_Mitsubishi.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendMitsubishi(). + +// Test sending typical data only. +TEST(TestSendMitsubishi, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi(0xE242); + EXPECT_EQ( + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080" + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi(0x0); + EXPECT_EQ( + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s34080" + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s34080", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi(0x4321); + EXPECT_EQ( + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s2100" + "m300s900m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100" + "m300s28080" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s2100" + "m300s900m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100" + "m300s28080", + irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendMitsubishi, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi(0xE242, kMitsubishiBits, 0); // 0 repeat. + EXPECT_EQ( + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi(0xE242, kMitsubishiBits, 1); // 1 repeat. + EXPECT_EQ( + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080" + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080", + irsend.outputStr()); + irsend.sendMitsubishi(0xE242, kMitsubishiBits, 2); // 2 repeats. + EXPECT_EQ( + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080" + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080" + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080", + irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendMitsubishi, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi(0x0, 8); + EXPECT_EQ( + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s43680" + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s43680", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m300s900m300s900m300s900m300s2100m300s900m300s900m300s2100m300s900" + "m300s900m300s900m300s2100m300s2100m300s900m300s2100m300s900m300s900" + "m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100m300s900" + "m300s900m300s2100m300s2100m300s2100m300s2100m300s900m300s900m300s900" + "m300s2100m300s900m300s900m300s2100m300s900m300s900m300s900m300s900" + "m300s2100m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100" + "m300s2100m300s2100m300s900m300s900m300s2100m300s2100m300s900m300s2100" + "m300s2100m300s2100m300s2100m300s900m300s2100m300s2100m300s2100m300s2100" + "m300s28080" + "m300s900m300s900m300s900m300s2100m300s900m300s900m300s2100m300s900" + "m300s900m300s900m300s2100m300s2100m300s900m300s2100m300s900m300s900" + "m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100m300s900" + "m300s900m300s2100m300s2100m300s2100m300s2100m300s900m300s900m300s900" + "m300s2100m300s900m300s900m300s2100m300s900m300s900m300s900m300s900" + "m300s2100m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100" + "m300s2100m300s2100m300s900m300s900m300s2100m300s2100m300s900m300s2100" + "m300s2100m300s2100m300s2100m300s900m300s2100m300s2100m300s2100m300s2100" + "m300s28080", + irsend.outputStr()); +} + +// Decode normal Mitsubishi messages. +TEST(TestDecodeMitsubishi, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Mitsubishi 16-bit message. + irsend.reset(); + irsend.sendMitsubishi(0xC2B8); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xC2B8, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendMitsubishi(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendMitsubishi(0xFFFF); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xFFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Non-standard Mitsubishi sizes should fail with strict. + irsend.reset(); + // 12 bits. + irsend.sendMitsubishi(0xFFF, 12); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); + + // 32 bits. + irsend.sendMitsubishi(0xFFF, 32); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); +} + +// Decode normal repeated Mitsubishi messages. +TEST(TestDecodeMitsubishi, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Mitsubishi 16-bit message with 2 repeats. + irsend.reset(); + irsend.sendMitsubishi(0xC2B8, kMitsubishiBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xC2B8, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Mitsubishi 16-bit message with 0 repeats. + irsend.reset(); + irsend.sendMitsubishi(0xC2B8, kMitsubishiBits, 0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xC2B8, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode unsupported Mitsubishi messages. +TEST(TestDecodeMitsubishi, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi(0x0, 8); // Illegal sized Mitsubishi 8-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); + + irsend.reset(); + // Illegal sized Mitsubishi 64-bit message. + irsend.sendMitsubishi(0xFEDCBA9876543210, 64); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFEDCBA9876543210, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + // Should fail when we are after a shorter message than we got. + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeMitsubishi, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi "Power On" (16-bit) code from Global Cache. + uint16_t gc_test[37] = {33000, 1, 1, 10, 70, 10, 70, 10, 70, 10, 30, 10, 30, + 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, 10, 30, 10, + 30, 10, 30, 10, 30, 10, 70, 10, 30, 10, 936}; + irsend.sendGC(gc_test, 37); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xE242, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Fail to decode a non-Mitsubishi example via GlobalCache +TEST(TestDecodeMitsubishi, FailToDecodeNonMitsubishiExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Modified a few entries to unexpected values, based on previous test case. + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; + irsend.sendGC(gc_test, 39); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture)); + ASSERT_FALSE( + irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, false)); +} + +// Tests for Mitsubishi A/C methods. + +// Test sending typical data only. +TEST(TestSendMitsubishiAC, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t mitsub_code[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, + 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; + irsend.reset(); + irsend.sendMitsubishiAC(mitsub_code); + EXPECT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendMitsubishiAC, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t mitsub_code[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, + 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; + + irsend.sendMitsubishiAC(mitsub_code, kMitsubishiACStateLength, 0); + EXPECT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishiAC(mitsub_code, kMitsubishiACStateLength, 2); + EXPECT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendMitsubishiAC, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t mitsub_short_code[17] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, + 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t mitsub_long_code[19] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, + 0x06, 0x30, 0x45, 0x67, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x00}; + irsend.reset(); + irsend.sendMitsubishiAC(mitsub_short_code, 17); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishiAC(mitsub_long_code, 19); + ASSERT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m440s17100", + irsend.outputStr()); +} + +// Tests for IRMitsubishiAC class. + +TEST(TestMitsubishiACClass, Power) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.on(); + EXPECT_TRUE(mitsub.getPower()); + + mitsub.off(); + EXPECT_FALSE(mitsub.getPower()); + + mitsub.setPower(true); + EXPECT_TRUE(mitsub.getPower()); + + mitsub.setPower(false); + EXPECT_FALSE(mitsub.getPower()); +} + +TEST(TestMitsubishiACClass, Temperature) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.setTemp(0); + EXPECT_EQ(kMitsubishiAcMinTemp, mitsub.getTemp()); + + mitsub.setTemp(255); + EXPECT_EQ(kMitsubishiAcMaxTemp, mitsub.getTemp()); + + mitsub.setTemp(kMitsubishiAcMinTemp); + EXPECT_EQ(kMitsubishiAcMinTemp, mitsub.getTemp()); + + mitsub.setTemp(kMitsubishiAcMaxTemp); + EXPECT_EQ(kMitsubishiAcMaxTemp, mitsub.getTemp()); + + mitsub.setTemp(kMitsubishiAcMinTemp - 1); + EXPECT_EQ(kMitsubishiAcMinTemp, mitsub.getTemp()); + + mitsub.setTemp(kMitsubishiAcMaxTemp + 1); + EXPECT_EQ(kMitsubishiAcMaxTemp, mitsub.getTemp()); + + mitsub.setTemp(17); + EXPECT_EQ(17, mitsub.getTemp()); + + mitsub.setTemp(21); + EXPECT_EQ(21, mitsub.getTemp()); + + mitsub.setTemp(25); + EXPECT_EQ(25, mitsub.getTemp()); + + mitsub.setTemp(30); + EXPECT_EQ(30, mitsub.getTemp()); +} + +TEST(TestMitsubishiACClass, OperatingMode) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.setMode(kMitsubishiAcAuto); + EXPECT_EQ(kMitsubishiAcAuto, mitsub.getMode()); + + mitsub.setMode(kMitsubishiAcCool); + EXPECT_EQ(kMitsubishiAcCool, mitsub.getMode()); + + mitsub.setMode(kMitsubishiAcHeat); + EXPECT_EQ(kMitsubishiAcHeat, mitsub.getMode()); + + mitsub.setMode(kMitsubishiAcDry); + EXPECT_EQ(kMitsubishiAcDry, mitsub.getMode()); + + mitsub.setMode(kMitsubishiAcAuto + 1); + EXPECT_EQ(kMitsubishiAcAuto, mitsub.getMode()); + + mitsub.setMode(255); + EXPECT_EQ(kMitsubishiAcAuto, mitsub.getMode()); +} + +TEST(TestMitsubishiACClass, VaneMode) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.setVane(kMitsubishiAcVaneAuto); + EXPECT_EQ(kMitsubishiAcVaneAuto, mitsub.getVane()); + + mitsub.setVane(kMitsubishiAcVaneAuto + 1); + EXPECT_EQ(kMitsubishiAcVaneAuto + 1, mitsub.getVane()); + + mitsub.setVane(kMitsubishiAcVaneAutoMove); + EXPECT_EQ(kMitsubishiAcVaneAutoMove, mitsub.getVane()); + + mitsub.setVane(kMitsubishiAcVaneAutoMove + 1); + EXPECT_EQ(kMitsubishiAcVaneAutoMove, mitsub.getVane()); + + mitsub.setVane(kMitsubishiAcVaneAutoMove - 1); + EXPECT_EQ(kMitsubishiAcVaneAutoMove - 1, mitsub.getVane()); +} + +TEST(TestMitsubishiACClass, FanSpeed) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.setFan(kMitsubishiAcFanAuto); + EXPECT_EQ(kMitsubishiAcFanAuto, mitsub.getFan()); + + mitsub.setFan(255); + EXPECT_EQ(kMitsubishiAcFanRealMax, mitsub.getFan()); + + mitsub.setFan(kMitsubishiAcFanMax); + EXPECT_EQ(kMitsubishiAcFanRealMax, mitsub.getFan()); + + mitsub.setFan(kMitsubishiAcFanMax - 1); + EXPECT_EQ(kMitsubishiAcFanMax - 1, mitsub.getFan()); + + mitsub.setFan(1); + EXPECT_EQ(1, mitsub.getFan()); + + mitsub.setFan(2); + EXPECT_EQ(2, mitsub.getFan()); + + mitsub.setFan(3); + EXPECT_EQ(3, mitsub.getFan()); + + mitsub.setFan(4); + EXPECT_EQ(4, mitsub.getFan()); + + mitsub.setFan(kMitsubishiAcFanSilent); + EXPECT_EQ(kMitsubishiAcFanSilent, mitsub.getFan()); + + mitsub.setFan(kMitsubishiAcFanSilent + 1); + EXPECT_EQ(kMitsubishiAcFanRealMax, mitsub.getFan()); +} + +TEST(TestMitsubishiACClass, MessageConstuction) { + IRMitsubishiAC mitsub(0); + IRsendTest irsend(4); + mitsub.begin(); + irsend.begin(); + + mitsub.setFan(1); + mitsub.setMode(kMitsubishiAcCool); + mitsub.setTemp(27); + mitsub.setVane(3); + mitsub.on(); + + // Check everything for kicks. + EXPECT_EQ(1, mitsub.getFan()); + EXPECT_EQ(kMitsubishiAcCool, mitsub.getMode()); + EXPECT_EQ(27, mitsub.getTemp()); + EXPECT_EQ(3, mitsub.getVane()); + EXPECT_TRUE(mitsub.getPower()); + + irsend.reset(); + irsend.sendMitsubishiAC(mitsub.getRaw()); + EXPECT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s1300m450s1300m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s1300m450s1300m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s420" + "m440s17100", + irsend.outputStr()); +} + +// Tests for decodeMitsubishiAC() with real captured example. +TEST(TestDecodeMitsubishiAC, DecodeRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi AC "Power On, 16C, low fan, vane auto move". + uint16_t rawData[583] = { + 3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, + 444, 1236, 440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, + 442, 1264, 420, 394, 444, 394, 442, 1264, 422, 1260, 414, 398, + 440, 1266, 418, 1264, 420, 392, 446, 392, 444, 1264, 422, 392, + 446, 392, 446, 1260, 414, 400, 448, 390, 446, 392, 444, 394, + 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446, 392, + 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, + 440, 400, 438, 400, 448, 390, 446, 392, 444, 1236, 440, 1266, + 418, 394, 442, 396, 440, 398, 438, 402, 446, 1232, 444, 396, + 440, 1268, 418, 394, 442, 396, 440, 398, 440, 400, 448, 390, + 448, 1232, 442, 1266, 420, 394, 444, 1264, 422, 1260, 416, 396, + 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264, + 422, 1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, + 438, 400, 446, 392, 446, 392, 446, 392, 444, 396, 442, 396, + 440, 398, 438, 398, 438, 400, 448, 392, 446, 392, 444, 394, + 444, 396, 442, 396, 440, 398, 438, 400, 448, 390, 448, 392, + 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, + 440, 398, 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, + 442, 396, 440, 398, 440, 398, 438, 400, 448, 390, 446, 392, + 444, 394, 444, 394, 442, 396, 440, 398, 438, 400, 438, 400, + 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 1240, 444, 1264, 422, 390, 446, 392, 446, 1260, 414, 1268, + 418, 1264, 422, 12984, 3478, 1708, 418, 1264, 422, 1234, 442, 398, + 448, 390, 446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234, + 442, 1266, 420, 392, 444, 1264, 420, 392, 446, 394, 444, 1236, + 448, 1260, 416, 398, 440, 1266, 418, 1262, 422, 390, 446, 392, + 444, 1234, 440, 400, 448, 392, 446, 1234, 440, 398, 450, 390, + 446, 392, 444, 394, 444, 394, 442, 396, 442, 398, 440, 400, + 438, 400, 448, 390, 446, 392, 444, 394, 442, 396, 442, 396, + 440, 398, 438, 400, 448, 390, 446, 392, 446, 392, 444, 394, + 442, 396, 442, 396, 440, 398, 438, 400, 448, 416, 420, 392, + 444, 1234, 440, 1240, 446, 394, 442, 396, 440, 398, 438, 400, + 448, 1232, 444, 396, 440, 1240, 446, 394, 442, 396, 440, 398, + 440, 400, 448, 390, 446, 1232, 444, 1238, 446, 394, 444, 1236, + 448, 1232, 442, 396, 440, 398, 448, 1232, 444, 396, 440, 398, + 438, 1242, 444, 1238, 448, 1234, 442, 1240, 444, 394, 442, 396, + 440, 398, 438, 400, 448, 390, 446, 394, 444, 420, 416, 394, + 444, 396, 440, 398, 440, 398, 438, 400, 448, 418, 420, 418, + 418, 394, 442, 396, 442, 396, 440, 424, 412, 400, 448, 390, + 446, 392, 446, 420, 418, 420, 416, 396, 440, 398, 440, 424, + 412, 426, 420, 418, 420, 392, 444, 394, 444, 422, 416, 422, + 414, 398, 440, 426, 422, 388, 448, 416, 420, 418, 418, 422, + 416, 422, 414, 424, 414, 398, 438, 426, 422, 418, 420, 390, + 446, 418, 418, 420, 416, 396, 440, 424, 412, 426, 412, 400, + 446, 418, 420, 420, 418, 420, 416, 422, 414, 422, 414, 424, + 412, 426, 422, 390, 446, 1232, 442, 1240, 446, 394, 444, 394, + 442, 1238, 446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B + + irsend.sendRaw(rawData, 583, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI_AC, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiACBits, irsend.capture.bits); + uint8_t expected[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x00, 0x18, 0x0A, 0x36, + 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6}; + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits); +} + +// Tests for decodeMitsubishiAC() when the first payload has an error. +TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatNeeded) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi AC "Power On, 16C, low fan, vane auto move". + uint16_t rawData[583] = { + 3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, 444, 1236, + 440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, 442, 1264, 420, 394, + 444, 394, 442, 1264, 422, 1260, 414, 398, 440, 1266, 418, 1264, 420, 392, + 446, 392, 444, 1264, 422, 392, 446, 392, 446, 1260, 414, 400, 448, 390, + 446, 392, 444, 394, 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446, + 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, 448, 390, + 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 440, 400, 438, 400, 448, + 390, 446, 392, 444, 1236, 440, 1266, 418, 394, 442, 396, 440, 398, 438, + 402, 446, 1232, 444, 396, 440, 1268, 418, 394, 442, 396, 440, 398, + // space 699 is not recognizable: + 440, 400, 448, 390, 448, 1232, 442, 1266, 420, 394, 444, 1264, 699, 1260, + 416, 396, 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264, + 422, 1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, 438, 400, + 446, 392, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 438, 398, 438, + 400, 448, 392, 446, 392, 444, 394, 444, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 448, 392, 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438, + 400, 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 440, + 398, 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, + 438, 400, 438, 400, 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, + 398, 438, 1240, 444, 1264, 422, 390, 446, 392, 446, 1260, 414, 1268, 418, + 1264, 422, 12984, 3478, 1708, 418, 1264, 422, 1234, 442, 398, 448, 390, + 446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234, 442, 1266, 420, 392, + 444, 1264, 420, 392, 446, 394, 444, 1236, 448, 1260, 416, 398, 440, 1266, + 418, 1262, 422, 390, 446, 392, 444, 1234, 440, 400, 448, 392, 446, 1234, + 440, 398, 450, 390, 446, 392, 444, 394, 444, 394, 442, 396, 442, 398, 440, + 400, 438, 400, 448, 390, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 400, 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, + 398, 438, 400, 448, 416, 420, 392, 444, 1234, 440, 1240, 446, 394, 442, + 396, 440, 398, 438, 400, 448, 1232, 444, 396, 440, 1240, 446, 394, 442, + 396, 440, 398, 440, 400, 448, 390, 446, 1232, 444, 1238, 446, 394, 444, + 1236, 448, 1232, 442, 396, 440, 398, 448, 1232, 444, 396, 440, 398, 438, + 1242, 444, 1238, 448, 1234, 442, 1240, 444, 394, 442, 396, 440, 398, 438, + 400, 448, 390, 446, 394, 444, 420, 416, 394, 444, 396, 440, 398, 440, 398, + 438, 400, 448, 418, 420, 418, 418, 394, 442, 396, 442, 396, 440, 424, 412, + 400, 448, 390, 446, 392, 446, 420, 418, 420, 416, 396, 440, 398, 440, 424, + 412, 426, 420, 418, 420, 392, 444, 394, 444, 422, 416, 422, 414, 398, 440, + 426, 422, 388, 448, 416, 420, 418, 418, 422, 416, 422, 414, 424, 414, 398, + 438, 426, 422, 418, 420, 390, 446, 418, 418, 420, 416, 396, 440, 424, 412, + 426, 412, 400, 446, 418, 420, 420, 418, 420, 416, 422, 414, 422, 414, 424, + 412, 426, 422, 390, 446, 1232, 442, 1240, 446, 394, 444, 394, 442, 1238, + 446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B + + irsend.sendRaw(rawData, 583, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI_AC, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiACBits, irsend.capture.bits); + uint8_t expected[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x00, 0x18, 0x0A, 0x36, + 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6}; + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits); +} + +// Tests for decodeMitsubishiAC() when the repeat mark is wrong. +TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatMarkError) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi AC "Power On, 16C, low fan, vane auto move". + uint16_t rawData[583] = { + 3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, 444, 1236, + 440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, 442, 1264, 420, 394, + 444, 394, 442, 1264, 422, 1260, 414, 398, 440, 1266, 418, 1264, 420, 392, + 446, 392, 444, 1264, 422, 392, 446, 392, 446, 1260, 414, 400, 448, 390, + 446, 392, 444, 394, 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446, + 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, 448, 390, + 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 440, 400, 438, 400, 448, + 390, 446, 392, 444, 1236, 440, 1266, 418, 394, 442, 396, 440, 398, 438, + 402, 446, 1232, 444, 396, 440, 1268, 418, 394, 442, 396, 440, 398, 440, + 400, 448, 390, 448, 1232, 442, 1266, 420, 394, 444, 1264, 422, 1260, 416, + 396, 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264, 422, + 1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, 438, 400, 446, + 392, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 438, 398, 438, 400, + 448, 392, 446, 392, 444, 394, 444, 396, 442, 396, 440, 398, 438, 400, 448, + 390, 448, 392, 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, + 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 440, 398, + 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 438, + 400, 438, 400, 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 1240, 444, 1264, 422, 390, 446, 392, 446, + // Repeat mark (1111) wrong: + 1260, 414, 1268, 418, 1264, 422, 1111, 347, 1708, 418, 1264, 422, 1234, + 442, 398, 448, 390, 446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234, + 442, 1266, 420, 392, 444, 1264, 420, 392, 446, 394, 444, 1236, 448, 1260, + 416, 398, 440, 1266, 418, 1262, 422, 390, 446, 392, 444, 1234, 440, 400, + 448, 392, 446, 1234, 440, 398, 450, 390, 446, 392, 444, 394, 444, 394, + 442, 396, 442, 398, 440, 400, 438, 400, 448, 390, 446, 392, 444, 394, 442, + 396, 442, 396, 440, 398, 438, 400, 448, 390, 446, 392, 446, 392, 444, 394, + 442, 396, 442, 396, 440, 398, 438, 400, 448, 416, 420, 392, 444, 1234, + 440, 1240, 446, 394, 442, 396, 440, 398, 438, 400, 448, 1232, 444, 396, + 440, 1240, 446, 394, 442, 396, 440, 398, 440, 400, 448, 390, 446, 1232, + 444, 1238, 446, 394, 444, 1236, 448, 1232, 442, 396, 440, 398, 448, 1232, + 444, 396, 440, 398, 438, 1242, 444, 1238, 448, 1234, 442, 1240, 444, 394, + 442, 396, 440, 398, 438, 400, 448, 390, 446, 394, 444, 420, 416, 394, 444, + 396, 440, 398, 440, 398, 438, 400, 448, 418, 420, 418, 418, 394, 442, 396, + 442, 396, 440, 424, 412, 400, 448, 390, 446, 392, 446, 420, 418, 420, 416, + 396, 440, 398, 440, 424, 412, 426, 420, 418, 420, 392, 444, 394, 444, 422, + 416, 422, 414, 398, 440, 426, 422, 388, 448, 416, 420, 418, 418, 422, 416, + 422, 414, 424, 414, 398, 438, 426, 422, 418, 420, 390, 446, 418, 418, 420, + 416, 396, 440, 424, 412, 426, 412, 400, 446, 418, 420, 420, 418, 420, 416, + 422, 414, 422, 414, 424, 412, 426, 422, 390, 446, 1232, 442, 1240, 446, + 394, 444, 394, 442, 1238, 446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B + + irsend.sendRaw(rawData, 583, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI_AC, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiACBits, irsend.capture.bits); + uint8_t expected[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x00, 0x18, 0x0A, 0x36, + 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6}; + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits); +} + +// Tests for decodeMitsubishiAC() when first payload has an error and the +// repeat mark is wrong. +TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatNeededButError) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi AC "Power On, 16C, low fan, vane auto move". + uint16_t rawData[583] = { + 3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, 444, 1236, + 440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, 442, 1264, 420, 394, + 444, 394, 442, 1264, 422, 1260, 414, 398, 440, 1266, 418, 1264, 420, 392, + 446, 392, 444, 1264, 422, 392, 446, 392, 446, 1260, 414, 400, 448, 390, + 446, 392, 444, 394, 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446, + 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, 448, 390, + 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 440, 400, 438, 400, 448, + 390, 446, 392, 444, 1236, 440, 1266, 418, 394, 442, 396, 440, 398, 438, + 402, 446, 1232, 444, 396, 440, 1268, 418, 394, 442, 396, 440, 398, + // space 699 is not recognizable: + 440, 400, 448, 390, 448, 1232, 442, 1266, 420, 394, 444, 1264, 699, 1260, + 416, 396, 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264, + 422, 1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, 438, 400, + 446, 392, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 438, 398, 438, + 400, 448, 392, 446, 392, 444, 394, 444, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 448, 392, 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438, + 400, 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 440, + 398, 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, + 438, 400, 438, 400, 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, + 398, 438, 1240, 444, 1264, 422, 390, 446, 392, 446, + // 1111 is not a valid repeat mark: + 1260, 414, 1268, 418, 1264, 422, 1111, 3478, 1708, 418, 1264, 422, 1234, + 442, 398, 448, 390, 446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234, + 442, 1266, 420, 392, 444, 1264, 420, 392, 446, 394, 444, 1236, 448, 1260, + 416, 398, 440, 1266, 418, 1262, 422, 390, 446, 392, 444, 1234, 440, 400, + 448, 392, 446, 1234, 440, 398, 450, 390, 446, 392, 444, 394, 444, 394, + 442, 396, 442, 398, 440, 400, 438, 400, 448, 390, 446, 392, 444, 394, 442, + 396, 442, 396, 440, 398, 438, 400, 448, 390, 446, 392, 446, 392, 444, 394, + 442, 396, 442, 396, 440, 398, 438, 400, 448, 416, 420, 392, 444, 1234, + 440, 1240, 446, 394, 442, 396, 440, 398, 438, 400, 448, 1232, 444, 396, + 440, 1240, 446, 394, 442, 396, 440, 398, 440, 400, 448, 390, 446, 1232, + 444, 1238, 446, 394, 444, 1236, 448, 1232, 442, 396, 440, 398, 448, 1232, + 444, 396, 440, 398, 438, 1242, 444, 1238, 448, 1234, 442, 1240, 444, 394, + 442, 396, 440, 398, 438, 400, 448, 390, 446, 394, 444, 420, 416, 394, 444, + 396, 440, 398, 440, 398, 438, 400, 448, 418, 420, 418, 418, 394, 442, 396, + 442, 396, 440, 424, 412, 400, 448, 390, 446, 392, 446, 420, 418, 420, 416, + 396, 440, 398, 440, 424, 412, 426, 420, 418, 420, 392, 444, 394, 444, 422, + 416, 422, 414, 398, 440, 426, 422, 388, 448, 416, 420, 418, 418, 422, 416, + 422, 414, 424, 414, 398, 438, 426, 422, 418, 420, 390, 446, 418, 418, 420, + 416, 396, 440, 424, 412, 426, 412, 400, 446, 418, 420, 420, 418, 420, 416, + 422, 414, 422, 414, 424, 412, 426, 422, 390, 446, 1232, 442, 1240, 446, + 394, 444, 394, 442, 1238, 446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B + + irsend.sendRaw(rawData, 583, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(UNKNOWN, irsend.capture.decode_type); +} + +TEST(TestMitsubishiACClass, HumanReadable) { + IRMitsubishiAC irMitsu(0); + EXPECT_EQ( + "Power: On (HEAT), Temp: 22C, FAN: SILENT, VANE: AUTO, " + "Time: 17:10, On timer: 00:00, Off timer: 00:00, Timer: -", + irMitsu.toString()); +} + +// Test sending typical data only. +TEST(TestSendMitsubishi2, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi2(0xF82); + EXPECT_EQ( + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500" + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi2(0x0); + EXPECT_EQ( + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s520m560s520m560s520m560s520" + "m560s4200" + "m560s520m560s520m560s520m560s520m560s520m560s520m560s520m560s520" + "m560s28500" + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s520m560s520m560s520m560s520" + "m560s4200" + "m560s520m560s520m560s520m560s520m560s520m560s520m560s520m560s520" + "m560s28500", + irsend.outputStr()); +} + +// Test sending odd repeats. +TEST(TestSendMitsubishi2, Repeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi2(0xF82, kMitsubishiBits, 0); + EXPECT_EQ( + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi2(0xF82, kMitsubishiBits, 2); + EXPECT_EQ( + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500" + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500" + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500", + irsend.outputStr()); +} + +// Tests for decodeMitsubishi2(). + +// Decode synthetic examples. +TEST(TestDecodeMitsubishi2, DecodeSyntheticExamples) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi Projector "Power On" (16-bit). + irsend.sendMitsubishi2(0xF82); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xF82, irsend.capture.value); + EXPECT_EQ(0xF, irsend.capture.address); + EXPECT_EQ(0x82, irsend.capture.command); + + irsend.reset(); + irsend.sendMitsubishi2(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendMitsubishi2(0x1234); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + EXPECT_EQ(0x12, irsend.capture.address); + EXPECT_EQ(0x34, irsend.capture.command); +} + +// Decode a 'real' example from Issue #441 +TEST(TestDecodeMitsubishi2, DecodeRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi Projector "Power On" (16-bit). + uint16_t rawData[75] = { + 8402, 4172, 554, 490, 562, 484, 560, 514, 532, 512, 534, + 1566, 526, 1572, 526, 1542, 560, 1568, 532, 4192, 534, 1564, + 532, 484, 560, 512, 532, 512, 532, 514, 530, 514, 526, + 1570, 524, 520, 526, 28506, 8454, 4170, 560, 514, 528, 516, + 526, 520, 524, 490, 556, 1572, 534, 1534, 560, 1568, 530, + 1538, 558, 4166, 560, 1538, 558, 490, 560, 512, 530, 514, + 532, 484, 558, 514, 532, 1566, 530, 486, 554}; // UNKNOWN 96A1512F + + irsend.sendRaw(rawData, 75, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xF82, irsend.capture.value); + EXPECT_EQ(0xF, irsend.capture.address); + EXPECT_EQ(0x82, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_NEC_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_NEC_test.cpp similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_NEC_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_NEC_test.cpp index 781aa38d7..6b84b0ec9 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_NEC_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_NEC_test.cpp @@ -11,18 +11,21 @@ TEST(TestSendNEC, SendDataOnly) { IRsendTest irsend(4); irsend.begin(); irsend.sendNEC(0); - EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s108080", irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s58240", + irsend.outputStr()); irsend.sendNEC(0xAA00FF55); - EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s108080", - irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s40320", + irsend.outputStr()); } // Test sending different bit lengths. @@ -30,22 +33,26 @@ TEST(TestSendNEC, SendSmallData) { IRsendTest irsend(4); irsend.begin(); irsend.sendNEC(0xA, 4); // Send only 4 data bits. - EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s108080", + EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s87360", irsend.outputStr()); irsend.sendNEC(0, 8); // Send only 8 data bits. - EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s108080", irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s85120", + irsend.outputStr()); irsend.sendNEC(0x1234567890ABCDEF, 64); // Send 64 data bits. - EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s1680m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s1680m560s1680m560s560" - "m560s1680m560s560m560s560m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s1680" - "m560s1680m560s1680m560s560m560s560m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680" - "m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" - "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680" - "m560s1680m560s108080", irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s1680m560s1680m560s560" + "m560s1680m560s560m560s560m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680" + "m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680" + "m560s1680m560s22400", + irsend.outputStr()); } // Test sending with repeats. @@ -53,20 +60,24 @@ TEST(TestSendNEC, SendWithRepeats) { IRsendTest irsend(4); irsend.begin(); irsend.sendNEC(0, 8, 0); // Send a command with 0 repeats. - EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s108080", irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s85120", + irsend.outputStr()); irsend.sendNEC(0xAA, 8, 1); // Send a command with 1 repeat. - EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s108080" - "m8960s2240m560s108080", - irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s80640" + "m8960s2240m560s96320", + irsend.outputStr()); irsend.sendNEC(0xAA, 8, 3); // Send a command with 3 repeats. - EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s108080" - "m8960s2240m560s108080" - "m8960s2240m560s108080" - "m8960s2240m560s108080", - irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s80640" + "m8960s2240m560s96320" + "m8960s2240m560s96320" + "m8960s2240m560s96320", + irsend.outputStr()); } // Tests for encodeNEC(). @@ -101,7 +112,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x807F40BF, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x2, irsend.capture.command); @@ -112,7 +123,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0xC1A28877, irsend.capture.value); EXPECT_EQ(0x4583, irsend.capture.address); EXPECT_EQ(0x11, irsend.capture.command); @@ -129,7 +140,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x807F40BF, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x2, irsend.capture.command); @@ -146,7 +157,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithoutStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 32, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0, irsend.capture.value); EXPECT_EQ(0, irsend.capture.address); EXPECT_EQ(0, irsend.capture.command); @@ -156,7 +167,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithoutStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 32, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); EXPECT_EQ(0x2C48, irsend.capture.address); EXPECT_EQ(0, irsend.capture.command); @@ -225,18 +236,18 @@ TEST(TestDecodeNEC, NoTrailingGap_Issue243) { irsend.begin(); irsend.reset(); - uint16_t rawData[67] = {9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, - 600, 1650, 650, 550, 600, 1650, 650, 1650, 650, 1650, - 600, 550, 650, 1650, 650, 1650, 650, 550, 600, 1650, - 650, 1650, 650, 550, 650, 550, 650, 1650, 650, 550, - 650, 550, 650, 550, 600, 550, 650, 550, 650, 550, - 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, - 650, 1650, 650, 1650, 650, 1650, 600}; + uint16_t rawData[67] = { + 9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, 600, 1650, + 650, 550, 600, 1650, 650, 1650, 650, 1650, 600, 550, 650, 1650, + 650, 1650, 650, 550, 600, 1650, 650, 1650, 650, 550, 650, 550, + 650, 1650, 650, 550, 650, 550, 650, 550, 600, 550, 650, 550, + 650, 550, 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, + 650, 1650, 650, 1650, 650, 1650, 600}; irsend.sendRaw(rawData, 67, 38); irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x4BB640BF, irsend.capture.value); EXPECT_EQ(0x6DD2, irsend.capture.address); EXPECT_EQ(0x2, irsend.capture.command); @@ -246,16 +257,16 @@ TEST(TestDecodeNEC, NoTrailingGap_Issue243) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x4BB640BF, irsend.capture.value); // Add a zero length space to the message to test how it handles that as - // a end of command gap. + // an end of command gap. irsend.addGap(0); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x4BB640BF, irsend.capture.value); } @@ -270,18 +281,18 @@ TEST(TestDecodeNEC, NonStrictNECDecode_Issue264) { irsend.reset(); // Slightly modified example than reported due to poor timings that are too // far out of spec. - uint16_t rawData[67] = {9150, 4650, 550, 600, 550, 1800, 600, 1750, 600, 1800, - 550, 600, 550, 1800, 550, 1750, 600, 1750, 600, 1750, - 600, 1750, 600, 1700, 600, 600, 600, 600, 550, 600, - 600, 600, 600, 1750, 600, 1750, 600, 600, 550, 1800, - 600, 600, 600, 600, 600, 600, 500, 600, 600, 600, - 600, 600, 600, 1750, 600, 600, 600, 550, 600, 600, - 600, 600, 600, 600, 600, 550, 600}; + uint16_t rawData[67] = { + 9150, 4650, 550, 600, 550, 1800, 600, 1750, 600, 1800, 550, 600, + 550, 1800, 550, 1750, 600, 1750, 600, 1750, 600, 1750, 600, 1700, + 600, 600, 600, 600, 550, 600, 600, 600, 600, 1750, 600, 1750, + 600, 600, 550, 1800, 600, 600, 600, 600, 600, 600, 500, 600, + 600, 600, 600, 600, 600, 1750, 600, 600, 600, 550, 600, 600, + 600, 600, 600, 600, 600, 550, 600}; irsend.sendRaw(rawData, 67, 38); irsend.makeDecodeResult(); EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture)); // Not strictly NEC - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, NEC_BITS, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); EXPECT_EQ(0x77E1A040, irsend.capture.value); // Do it all again, but with a normal decode. @@ -290,7 +301,7 @@ TEST(TestDecodeNEC, NonStrictNECDecode_Issue264) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(NEC_LIKE, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x77E1A040, irsend.capture.value); } @@ -303,18 +314,18 @@ TEST(TestDecodeNEC, AutoReceiveCalibration) { // Data from Issue #264, for a remote that is slightly off spec. // Should be matched as a NEC-like message however without self-calibrating // the timings of the short spaces is out. - uint16_t rawData[67] = {9150, 4600, 650, 600, 650, 1650, 650, 1700, 650, 1750, - 650, 600, 650, 1700, 650, 1750, 650, 1750, 650, 1700, - 650, 1700, 650, 1700, 650, 600, 650, 600, 650, 600, - 600, 600, 650, 1750, 650, 1750, 650, 600, 650, 1700, - 600, 600, 700, 550, 650, 550, 650, 600, 650, 600, - 650, 600, 650, 1750, 600, 600, 650, 600, 650, 550, - 650, 600, 650, 600, 650, 600, 600}; + uint16_t rawData[67] = { + 9150, 4600, 650, 600, 650, 1650, 650, 1700, 650, 1750, 650, 600, + 650, 1700, 650, 1750, 650, 1750, 650, 1700, 650, 1700, 650, 1700, + 650, 600, 650, 600, 650, 600, 600, 600, 650, 1750, 650, 1750, + 650, 600, 650, 1700, 600, 600, 700, 550, 650, 550, 650, 600, + 650, 600, 650, 600, 650, 1750, 600, 600, 650, 600, 650, 550, + 650, 600, 650, 600, 650, 600, 600}; irsend.sendRaw(rawData, 67, 38); irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, NEC_BITS, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x77E1A040, irsend.capture.value); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp new file mode 100644 index 000000000..4a4ea05bb --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp @@ -0,0 +1,212 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendNikai(). +// Test sending typical data only. +TEST(TestSendNikai, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendNikai(0xD5F2A); // Nikai TV Power Off. + EXPECT_EQ( + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500", + irsend.outputStr()); + + irsend.reset(); +} + +// Test sending with different repeats. +TEST(TestSendNikai, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendNikai(0xD5F2A, kNikaiBits, 1); // 1 repeat. + EXPECT_EQ( + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500" + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500", + irsend.outputStr()); + irsend.sendNikai(0xD5F2A, kNikaiBits, 2); // 2 repeat. + EXPECT_EQ( + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500" + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500" + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500", + irsend.outputStr()); +} + +// Tests for decodeNikai(). + +// Decode normal Nikai messages. +TEST(TestDecodeNikai, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Nikai 24-bit message. + irsend.reset(); + irsend.sendNikai(0x123456); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0x123456, irsend.capture.value); + + irsend.reset(); + irsend.sendNikai(0x101); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0x101, irsend.capture.value); +} + +// Decode normal repeated Nikai messages. +TEST(TestDecodeNikai, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Nikai 24-bit message. + irsend.reset(); + irsend.sendNikai(0xD5F2A, kNikaiBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0xD5F2A, irsend.capture.value); +} + +TEST(TestDecodeNikai, NormalDecodeWithNonStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Illegal under length (16-bit) message + irsend.reset(); + irsend.sendNikai(0x0, 16); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + // And it should fail when we expect more bits. + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, false)); + + // Should pass if strict off if we ask for correct nr. of bits sent. + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 16, false)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(16, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + + // Should fail as we are expecting less bits than there are. + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, 12, false)); +} + +// Decode (non-standard) 64-bit messages. +// Decode unsupported Nikai messages. +TEST(TestDecodeNikai, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal size Nikai 64-bit message. + irsend.sendNikai(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 64, false)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); +} + +// Decode real example via Issue #309 +TEST(TestDecodeNikai, DecodeExamples) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Nikai TV Power Off from Issue #309 + uint16_t rawdata_off[100] = { + 4060, 3918, 508, 2004, 508, 2002, 510, 2002, 508, 2004, 506, + 1050, 508, 1048, 510, 2004, 508, 1048, 508, 2002, 510, 1050, + 508, 2004, 510, 1048, 508, 1050, 508, 1048, 508, 1050, 508, + 1050, 508, 2004, 508, 2002, 510, 1048, 508, 2004, 508, 1050, + 506, 2004, 508, 1048, 510, 2002, 456, 8446, 3956, 3998, 508, + 2004, 508, 2002, 508, 2004, 508, 1978, 532, 1050, 508, 1050, + 508, 2002, 508, 1050, 508, 2004, 508, 1050, 508, 2002, 510, + 1050, 508, 1050, 508, 1048, 508, 1050, 508, 1050, 508, 2002, + 510, 2002, 508, 1050, 508, 2002, 510, 1050, 508, 2002, 508}; + irsend.sendRaw(rawdata_off, 100, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0xD5F2A, irsend.capture.value); + + // Nikai TV Volume Up from Issue #309 + uint16_t rawdata_volup[52] = { + 3972, 4002, 504, 1982, 526, 2010, 502, 2010, 502, 2010, 500, + 1056, 502, 1056, 502, 2010, 500, 1056, 502, 2010, 502, 2010, + 500, 2010, 502, 2010, 502, 1056, 502, 1056, 502, 1056, 500, + 1056, 502, 2010, 502, 2010, 500, 1056, 502, 2008, 502, 1054, + 504, 1054, 504, 1054, 500, 1056, 450}; + + irsend.reset(); + irsend.sendRaw(rawdata_volup, 52, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0xD0F2F, irsend.capture.value); +} + +// Fail to decode a non-Nikai example via GlobalCache +TEST(TestDecodeNikai, FailToDecodeNonNikaiExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 21, 22, 11, 22, 21, 22, 128, 22, + 64, 22, 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 64, 22, 21, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 1820}; + irsend.sendGC(gc_test, 71); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, false)); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp new file mode 100644 index 000000000..a1d8a7979 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp @@ -0,0 +1,1135 @@ +// Copyright 2017, 2018 David Conran + +#include "ir_Panasonic.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" +#include "gtest/gtest.h" + +// Tests for encodePanasonic(). + +TEST(TestEncodePanasonic, General) { + IRsendTest irsend(4); + EXPECT_EQ(0x0, irsend.encodePanasonic(0, 0, 0, 0)); + EXPECT_EQ(0x101010101, irsend.encodePanasonic(1, 1, 1, 1)); + EXPECT_EQ(0xFFFF, irsend.encodePanasonic(0, 0, 0, 0xFF)); + EXPECT_EQ(0xFF00FF, irsend.encodePanasonic(0, 0, 0xFF, 0)); + EXPECT_EQ(0xFF0000FF, irsend.encodePanasonic(0, 0xFF, 0, 0)); + EXPECT_EQ(0xFFFF00000000, irsend.encodePanasonic(0xFFFF, 0, 0, 0)); + EXPECT_EQ(0xFFFFFFFFFFFF, irsend.encodePanasonic(0xFFFF, 0xFF, 0xFF, 0xFF)); + EXPECT_EQ(0x40040190ED7C, irsend.encodePanasonic(0x4004, 0x01, 0x90, 0xED)); +} + +// Tests for sendPanasonic64(). + +// Test sending typical data only. +TEST(TestSendPanasonic64, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x0); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s116208", + irsend.outputStr()); + + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384", + irsend.outputStr()); + + irsend.reset(); + irsend.sendPanasonic64(0xFFFFFFFFFFFF); + EXPECT_EQ( + "m3456s1728" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s74736", + irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendPanasonic64, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 0); // 0 repeats. + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384", + irsend.outputStr()); + + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 1); // 1 repeat. + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384" + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384", + irsend.outputStr()); + + irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 2); // 2 repeats. + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384" + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384" + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384", + irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendPanasonic64, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x0, 8); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s150768", + irsend.outputStr()); + + irsend.reset(); + irsend.sendPanasonic64(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s432m432s1296m432s432m432s432m432s1296m432s432" + "m432s432m432s432m432s1296m432s1296m432s432m432s1296m432s432m432s432" + "m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296m432s432" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s432m432s432m432s432" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296" + "m432s1296m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s1296" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s1296m432s1296" + "m432s74736", + irsend.outputStr()); +} + +// Tests for sendPanasonic(). + +TEST(TestSendPanasonic, CompareToSendPanasonic64) { + IRsendTest panasonic(4); + IRsendTest panasonic64(0); + + panasonic.begin(); + panasonic64.begin(); + + panasonic.reset(); + panasonic64.reset(); + + panasonic.sendPanasonic(0x4004, 0x0190ED7C); + panasonic64.sendPanasonic64(0x40040190ED7C); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); + + panasonic.sendPanasonic(0x0, 0x0); + panasonic64.sendPanasonic64(0x0); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); + + panasonic.sendPanasonic(0x0, 0x0, 8); + panasonic64.sendPanasonic64(0x0, 8); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); + + panasonic.sendPanasonic(0x1234, 0x567890AB, 64); + panasonic64.sendPanasonic64(0x1234567890AB, 64); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); + + panasonic.sendPanasonic(0x1234, 0x567890AB, kPanasonicBits, 2); + panasonic64.sendPanasonic64(0x1234567890AB, kPanasonicBits, 2); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); +} + +// Tests for decodePanasonic(). + +// Decode normal Panasonic messages. +TEST(TestDecodePanasonic, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Panasonic 48-bit message. + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x0190ED7C, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal Panasonic 48-bit message. + irsend.reset(); + irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x12, 0x34, 0x56)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x400412345670, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x12345670, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal Panasonic 48-bit message. + irsend.reset(); + irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x1, 0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x400401010101, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x1010101, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated Panasonic messages. +TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Panasonic 48-bit message with 2 repeats. + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x190ED7C, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.makeDecodeResult(2 * kPanasonicBits + 4); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + + irsend.makeDecodeResult(2 * (2 * kPanasonicBits + 4)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); +} + +// Decode Panasonic messages with unsupported values. +TEST(TestDecodePanasonic, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x0); // Illegal value Panasonic 48-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + // Illegal address/Manufacturer code. The rest is legal. + irsend.sendPanasonic64(irsend.encodePanasonic(0, 1, 2, 3)); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x1020300, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x1020300, irsend.capture.command); +} + +// Decode Panasonic messages with unsupported size/lengths. +TEST(TestDecodePanasonic, DecodeWithNonStrictSize) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x12345678, 32); // Illegal size Panasonic message. + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 32, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x12345678, irsend.capture.command); + + // Illegal over length (56-bit) message. + irsend.reset(); + irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 1, 2, 3), 56); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + // Shouldn't pass if strict off and wrong bit size. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + // Re-decode with correct bit size. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 56, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 56, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(56, irsend.capture.bits); + EXPECT_EQ(0x400401020300, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x01020300, irsend.capture.command); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodePanasonic, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size Panasonic 64-bit message. + irsend.sendPanasonic64(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 64, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 64, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0xFFFFFFFF, irsend.capture.address); + EXPECT_EQ(0xFFFFFFFF, irsend.capture.command); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodePanasonic, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Panasonic code from Global Cache. + uint16_t gc_test[103] = { + 37000, 1, 1, 126, 64, 16, 17, 16, 49, 15, 16, 16, 16, 16, 16, + 16, 17, 15, 17, 15, 17, 15, 17, 15, 16, 16, 16, 16, 16, 16, + 17, 15, 49, 16, 16, 16, 16, 16, 17, 15, 17, 15, 17, 15, 17, + 15, 16, 16, 16, 16, 16, 16, 49, 15, 49, 16, 17, 15, 17, 15, + 49, 16, 16, 16, 17, 16, 17, 15, 17, 15, 49, 16, 49, 15, 49, + 16, 17, 16, 49, 15, 49, 16, 17, 15, 48, 16, 16, 16, 49, 15, + 48, 16, 49, 15, 49, 16, 49, 15, 17, 15, 16, 16, 2721}; + irsend.sendGC(gc_test, 103); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x0190ED7C, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x0190ED7C, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Fail to decode a non-Panasonic example via GlobalCache +TEST(TestDecodePanasonic, FailToDecodeNonPanasonicExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Modified a few entries to unexpected values, based on previous test case. + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; + irsend.sendGC(gc_test, 39); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); +} + +// Failing to decode Panasonic in Issue #245 +TEST(TestDecodePanasonic, DecodeIssue245) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + + uint16_t rawData[100] = { + 3550, 1750, 500, 450, 500, 1300, 500, 450, 500, 450, 500, 450, + 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, + 500, 450, 500, 450, 500, 1300, 500, 450, 500, 450, 500, 450, + 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, + 500, 1300, 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, + 500, 450, 500, 450, 500, 450, 500, 1300, 500, 450, 500, 1300, + 500, 1300, 500, 1300, 500, 1300, 500, 450, 500, 450, 500, 1300, + 500, 450, 500, 1300, 500, 1300, 500, 1300, 500, 1300, 500, 450, + 500, 1300, 500, 5000}; + + irsend.sendRaw(rawData, 100, 37); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040100BCBD, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x100BCBD, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendRaw(rawData, 99, 37); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040100BCBD, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x100BCBD, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Tests for sendPanasonicAC(). + +// Test sending typical data only. +TEST(TestSendPanasonicAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + + uint8_t state[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + irsend.sendPanasonicAC(state); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s1296m432s1296" + "m432s432m432s432m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s10000" + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s1296m432s1296" + "m432s432m432s432m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s432m432s1296m432s432m432s1296" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s1296m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s100000", + irsend.outputStr()); +} + +// Tests for the IRPanasonicAc class. + +TEST(TestIRPanasonicAcClass, ChecksumCalculation) { + IRPanasonicAc pana(0); + + const uint8_t originalstate[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + uint8_t examplestate[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + + EXPECT_TRUE(IRPanasonicAc::validChecksum(examplestate)); + EXPECT_EQ(0x83, IRPanasonicAc::calcChecksum(examplestate)); + + examplestate[kPanasonicAcStateLength - 1] = 0x0; // Set incoorect checksum. + EXPECT_FALSE(IRPanasonicAc::validChecksum(examplestate)); + EXPECT_EQ(0x83, IRPanasonicAc::calcChecksum(examplestate)); + pana.setRaw(examplestate); + // Extracting the state from the object should have a correct checksum. + EXPECT_TRUE(IRPanasonicAc::validChecksum(pana.getRaw())); + EXPECT_STATE_EQ(originalstate, pana.getRaw(), kPanasonicAcBits); + examplestate[kPanasonicAcStateLength - 1] = 0x83; // Restore old checksum. + + // Change the state to force a different checksum. + examplestate[6] = 0x01; // Should increase checksum by 1. + EXPECT_FALSE(IRPanasonicAc::validChecksum(examplestate)); + EXPECT_EQ(0x84, IRPanasonicAc::calcChecksum(examplestate)); +} + +TEST(TestIRPanasonicAcClass, SetAndGetPower) { + IRPanasonicAc pana(0); + pana.on(); + EXPECT_TRUE(pana.getPower()); + pana.off(); + EXPECT_FALSE(pana.getPower()); + pana.setPower(true); + EXPECT_TRUE(pana.getPower()); + pana.setPower(false); + EXPECT_FALSE(pana.getPower()); +} + +TEST(TestIRPanasonicAcClass, SetAndGetModel) { + IRPanasonicAc pana(0); + EXPECT_EQ(kPanasonicJke, pana.getModel()); + pana.setModel(kPanasonicDke); + EXPECT_EQ(kPanasonicDke, pana.getModel()); + pana.setModel(kPanasonicLke); + EXPECT_EQ(kPanasonicLke, pana.getModel()); + pana.setModel(kPanasonicNke); + EXPECT_EQ(kPanasonicNke, pana.getModel()); + pana.setModel(kPanasonicUnknown); // shouldn't change. + EXPECT_EQ(kPanasonicNke, pana.getModel()); + pana.setModel((panasonic_ac_remote_model_t)255); // shouldn't change. + EXPECT_EQ(kPanasonicNke, pana.getModel()); + pana.setModel(kPanasonicJke); + EXPECT_EQ(kPanasonicJke, pana.getModel()); + + // This state tickled a bug in getModel(). Should read as a JKE. + uint8_t jkeState[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x32, 0x2E, 0x80, 0xA2, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x74}; + pana.setModel(kPanasonicDke); // Make sure it isn't somehow set to JKE + pana.setRaw(jkeState); + EXPECT_EQ(kPanasonicJke, pana.getModel()); + EXPECT_STATE_EQ(jkeState, pana.getRaw(), kPanasonicAcBits); + + // This state tickled a bug in getModel(). Should read as CKP. + uint8_t ckpState[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x67, 0x2E, 0x80, 0xAF, 0x00, + 0xC0, 0x6B, 0x98, 0x10, 0x00, 0x81, 0x64, 0x05, 0x87}; + pana.setModel(kPanasonicDke); // Make sure it isn't somehow set to CKP + pana.setRaw(ckpState); + EXPECT_EQ(kPanasonicCkp, pana.getModel()); + EXPECT_STATE_EQ(ckpState, pana.getRaw(), kPanasonicAcBits); +} + +TEST(TestIRPanasonicAcClass, SetAndGetMode) { + IRPanasonicAc pana(0); + pana.setMode(kPanasonicAcCool); + pana.setTemp(21); + EXPECT_EQ(kPanasonicAcCool, pana.getMode()); + pana.setMode(kPanasonicAcHeat); + EXPECT_EQ(kPanasonicAcHeat, pana.getMode()); + pana.setMode(kPanasonicAcAuto); + EXPECT_EQ(kPanasonicAcAuto, pana.getMode()); + pana.setMode(kPanasonicAcDry); + EXPECT_EQ(kPanasonicAcDry, pana.getMode()); + EXPECT_EQ(21, pana.getTemp()); // Temp should be unchanged. + pana.setMode(kPanasonicAcFan); + EXPECT_EQ(kPanasonicAcFan, pana.getMode()); + EXPECT_EQ(kPanasonicAcFanModeTemp, pana.getTemp()); // Temp should change. + pana.setMode(kPanasonicAcCool); + EXPECT_EQ(kPanasonicAcCool, pana.getMode()); + // Temp should be unchanged from the last manual change. + EXPECT_EQ(21, pana.getTemp()); +} + +TEST(TestIRPanasonicAcClass, SetAndGetTemp) { + IRPanasonicAc pana(0); + pana.setTemp(25); + EXPECT_EQ(25, pana.getTemp()); + pana.setTemp(kPanasonicAcMinTemp); + EXPECT_EQ(kPanasonicAcMinTemp, pana.getTemp()); + pana.setTemp(kPanasonicAcMinTemp - 1); + EXPECT_EQ(kPanasonicAcMinTemp, pana.getTemp()); + pana.setTemp(kPanasonicAcMaxTemp); + EXPECT_EQ(kPanasonicAcMaxTemp, pana.getTemp()); + pana.setTemp(kPanasonicAcMaxTemp + 1); + EXPECT_EQ(kPanasonicAcMaxTemp, pana.getTemp()); +} + +TEST(TestIRPanasonicAcClass, SetAndGetFan) { + IRPanasonicAc pana(0); + pana.setFan(kPanasonicAcFanAuto); + EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan()); + pana.setFan(kPanasonicAcFanMin); + EXPECT_EQ(kPanasonicAcFanMin, pana.getFan()); + pana.setFan(kPanasonicAcFanMin - 1); + EXPECT_EQ(kPanasonicAcFanMin, pana.getFan()); + pana.setFan(kPanasonicAcFanMin + 1); + EXPECT_EQ(kPanasonicAcFanMin + 1, pana.getFan()); + pana.setFan(kPanasonicAcFanMax); + EXPECT_EQ(kPanasonicAcFanMax, pana.getFan()); + pana.setFan(kPanasonicAcFanMax + 1); + EXPECT_EQ(kPanasonicAcFanMax, pana.getFan()); + pana.setFan(kPanasonicAcFanMax - 1); + EXPECT_EQ(kPanasonicAcFanMax - 1, pana.getFan()); +} + +TEST(TestIRPanasonicAcClass, SetAndGetSwings) { + IRPanasonicAc pana(0); + + // Vertical + pana.setSwingVertical(kPanasonicAcSwingVAuto); + EXPECT_EQ(kPanasonicAcSwingVAuto, pana.getSwingVertical()); + + pana.setSwingVertical(kPanasonicAcSwingVUp); + EXPECT_EQ(kPanasonicAcSwingVUp, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVUp - 1); + EXPECT_EQ(kPanasonicAcSwingVUp, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVUp + 1); + EXPECT_EQ(kPanasonicAcSwingVUp + 1, pana.getSwingVertical()); + + pana.setSwingVertical(kPanasonicAcSwingVDown); + EXPECT_EQ(kPanasonicAcSwingVDown, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVDown + 1); + EXPECT_EQ(kPanasonicAcSwingVDown, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVDown - 1); + EXPECT_EQ(kPanasonicAcSwingVDown - 1, pana.getSwingVertical()); + + pana.setSwingVertical(kPanasonicAcSwingVAuto); + EXPECT_EQ(kPanasonicAcSwingVAuto, pana.getSwingVertical()); + + // Horizontal is model dependant. + pana.setModel(kPanasonicNke); // NKE is always fixed in the middle. + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + pana.setSwingHorizontal(kPanasonicAcSwingHAuto); + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + + pana.setModel(kPanasonicJke); // JKE has no H swing. + EXPECT_EQ(0, pana.getSwingHorizontal()); + pana.setSwingHorizontal(kPanasonicAcSwingHMiddle); + EXPECT_EQ(0, pana.getSwingHorizontal()); + + pana.setModel(kPanasonicLke); // LKE is always fixed in the middle. + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + pana.setSwingHorizontal(kPanasonicAcSwingHAuto); + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + + pana.setModel(kPanasonicDke); // DKE has full control. + ASSERT_EQ(kPanasonicDke, pana.getModel()); + // Auto was last requested. + EXPECT_EQ(kPanasonicAcSwingHAuto, pana.getSwingHorizontal()); + pana.setSwingHorizontal(kPanasonicAcSwingHLeft); + EXPECT_EQ(kPanasonicAcSwingHLeft, pana.getSwingHorizontal()); + // Changing models from DKE to something else, then back should not change + // the intended swing. + pana.setModel(kPanasonicLke); + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + pana.setModel(kPanasonicDke); + EXPECT_EQ(kPanasonicAcSwingHLeft, pana.getSwingHorizontal()); +} + +TEST(TestIRPanasonicAcClass, QuietAndPowerful) { + IRPanasonicAc pana(0); + pana.setQuiet(false); + EXPECT_FALSE(pana.getQuiet()); + pana.setQuiet(true); + EXPECT_TRUE(pana.getQuiet()); + EXPECT_FALSE(pana.getPowerful()); + pana.setPowerful(false); + EXPECT_FALSE(pana.getPowerful()); + EXPECT_TRUE(pana.getQuiet()); + pana.setPowerful(true); + EXPECT_TRUE(pana.getPowerful()); + EXPECT_FALSE(pana.getQuiet()); + pana.setPowerful(false); + EXPECT_FALSE(pana.getPowerful()); + EXPECT_FALSE(pana.getQuiet()); + pana.setPowerful(true); + pana.setQuiet(true); + EXPECT_TRUE(pana.getQuiet()); + EXPECT_FALSE(pana.getPowerful()); +} + +TEST(TestIRPanasonicAcClass, HumanReadable) { + IRPanasonicAc pana(0); + EXPECT_EQ( + "Model: 4 (JKE), Power: Off, Mode: 0 (AUTO), Temp: 0C, " + "Fan: 253 (UNKNOWN), Swing (Vertical): 0 (UNKNOWN), Quiet: Off, " + "Powerful: Off, Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); + pana.setPower(true); + pana.setTemp(kPanasonicAcMaxTemp); + pana.setMode(kPanasonicAcHeat); + pana.setFan(kPanasonicAcFanMax); + pana.setSwingVertical(kPanasonicAcSwingVAuto); + pana.setPowerful(true); + EXPECT_EQ( + "Model: 4 (JKE), Power: On, Mode: 4 (HEAT), Temp: 30C, " + "Fan: 4 (MAX), Swing (Vertical): 15 (AUTO), Quiet: Off, " + "Powerful: On, Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); + pana.setQuiet(true); + pana.setModel(kPanasonicLke); + EXPECT_EQ( + "Model: 1 (LKE), Power: Off, Mode: 4 (HEAT), Temp: 30C, " + "Fan: 4 (MAX), Swing (Vertical): 15 (AUTO), " + "Swing (Horizontal): 6 (Middle), Quiet: On, Powerful: Off, " + "Clock: 0:00, On Timer: 0:00, Off Timer: Off", + pana.toString()); + pana.setModel(kPanasonicDke); + pana.setSwingHorizontal(kPanasonicAcSwingHRight); + EXPECT_EQ( + "Model: 3 (DKE), Power: Off, Mode: 4 (HEAT), Temp: 30C, " + "Fan: 4 (MAX), Swing (Vertical): 15 (AUTO), " + "Swing (Horizontal): 11 (Right), Quiet: On, Powerful: Off, " + "Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); +} + +// Tests for decodePanasonicAC(). + +// Decode normal Panasonic AC messages. +TEST(TestDecodePanasonicAC, RealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Data from Issue #525 + uint16_t rawData[439] = { + 3582, 1686, 488, 378, 488, 1238, 488, 378, 488, 378, 488, 378, + 488, 378, 488, 378, 488, 384, 488, 378, 488, 378, 488, 378, + 488, 378, 488, 378, 488, 1242, 486, 378, 488, 384, 488, 378, + 488, 378, 488, 380, 486, 382, 484, 382, 484, 1264, 464, 1266, + 460, 1272, 462, 378, 488, 406, 460, 1266, 462, 380, 488, 382, + 484, 388, 478, 406, 462, 410, 462, 404, 462, 406, 462, 396, + 470, 406, 462, 404, 462, 406, 460, 404, 462, 410, 462, 404, + 462, 404, 462, 406, 464, 406, 462, 404, 462, 406, 462, 404, + 462, 410, 462, 404, 462, 406, 462, 404, 462, 404, 462, 404, + 462, 406, 460, 406, 462, 410, 462, 404, 462, 1264, 484, 1244, + 486, 382, 482, 382, 486, 382, 486, 378, 486, 382, 488, 9924, + 3554, 1686, 488, 378, 490, 1240, 486, 378, 488, 378, 488, 378, + 488, 378, 488, 382, 484, 386, 486, 378, 488, 382, 486, 378, + 488, 382, 486, 382, 484, 1242, 486, 380, 488, 386, 484, 382, + 486, 380, 486, 382, 486, 380, 486, 380, 486, 1242, 486, 1242, + 484, 1248, 484, 380, 488, 382, 484, 1242, 486, 382, 484, 382, + 484, 382, 484, 382, 486, 386, 484, 382, 486, 382, 484, 382, + 486, 382, 486, 380, 484, 382, 486, 382, 488, 380, 486, 382, + 484, 380, 462, 406, 488, 376, 484, 1246, 482, 1246, 460, 404, + 480, 392, 484, 386, 482, 1244, 484, 382, 484, 382, 484, 1242, + 482, 1244, 484, 382, 464, 410, 460, 404, 462, 406, 462, 404, + 462, 404, 470, 396, 462, 406, 462, 404, 462, 1286, 460, 1268, + 458, 1268, 460, 1266, 460, 1266, 460, 406, 460, 1266, 462, 406, + 460, 1272, 462, 406, 460, 406, 460, 406, 460, 406, 462, 404, + 462, 406, 460, 406, 462, 410, 462, 404, 462, 406, 460, 406, + 460, 406, 462, 404, 462, 406, 460, 406, 460, 410, 462, 406, + 460, 1268, 460, 1266, 460, 404, 460, 406, 462, 406, 460, 406, + 460, 412, 456, 410, 460, 410, 438, 428, 460, 410, 456, 410, + 456, 1272, 436, 1288, 438, 434, 438, 428, 438, 428, 438, 428, + 438, 428, 438, 428, 438, 428, 438, 428, 438, 434, 438, 428, + 438, 428, 438, 428, 438, 428, 438, 428, 440, 428, 438, 428, + 438, 432, 438, 428, 438, 428, 438, 428, 438, 428, 438, 428, + 438, 428, 438, 430, 438, 1294, 438, 428, 438, 428, 438, 428, + 438, 428, 438, 428, 438, 428, 438, 428, 438, 434, 438, 428, + 438, 1288, 438, 1290, 438, 428, 438, 428, 438, 428, 438, 428, + 438, 432, 438, 1288, 438, 1290, 438, 430, 438, 428, 438, 428, + 438, 428, 438, 428, 438, 1292, 438}; + uint8_t expectedState[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + + irsend.sendRaw(rawData, 439, kPanasonicFreq); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode synthetic Panasonic AC message. +TEST(TestDecodePanasonicAC, SyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Data from Issue #525 + uint8_t expectedState[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + + irsend.sendPanasonicAC(expectedState); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + + IRPanasonicAc pana(0); + pana.setRaw(irsend.capture.state); + EXPECT_EQ( + "Model: 4 (JKE), Power: Off, Mode: 3 (COOL), Temp: 25C, " + "Fan: 7 (AUTO), Swing (Vertical): 15 (AUTO), Quiet: Off, " + "Powerful: Off, Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); +} + +// Tests for general utility functions. +TEST(TestGeneralPanasonic, hasACState) { + EXPECT_TRUE(hasACState(PANASONIC_AC)); + ASSERT_FALSE(hasACState(PANASONIC)); +} + +TEST(TestGeneralPanasonic, typeToString) { + EXPECT_EQ("PANASONIC_AC", typeToString(PANASONIC_AC)); + EXPECT_EQ("PANASONIC", typeToString(PANASONIC)); +} + +// Decode a problematic Panasonic AC message +TEST(TestDecodePanasonicAC, Issue540) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Data from Issue #540 + uint16_t rawData[439] = { + 3512, 1714, 466, 408, 466, 1280, 470, 408, 466, 412, 466, 408, + 466, 412, 462, 412, 466, 414, 466, 408, 466, 412, 462, 412, + 466, 412, 466, 408, 466, 1280, 466, 412, 462, 416, 462, 412, + 466, 408, 466, 412, 462, 416, 462, 412, 462, 1282, 462, 1284, + 462, 1288, 466, 412, 462, 412, 462, 1284, 462, 416, 440, 438, + 462, 412, 462, 412, 462, 416, 466, 412, 462, 412, 462, 412, + 440, 442, 462, 412, 462, 412, 460, 418, 462, 416, 462, 412, + 462, 418, 462, 412, 462, 416, 462, 412, 436, 442, 462, 412, + 460, 418, 462, 416, 462, 412, 460, 412, 462, 420, 436, 438, + 462, 412, 462, 416, 432, 448, 436, 438, 436, 1310, 436, 1310, + 462, 420, 432, 442, 436, 438, 462, 416, 432, 444, 432, 10008, + 3480, 1744, 492, 382, 492, 1254, 492, 386, 488, 390, 492, 382, + 492, 386, 488, 386, 492, 386, 492, 386, 488, 386, 488, 386, + 492, 386, 492, 382, 492, 1258, 488, 386, 488, 390, 492, 386, + 488, 386, 488, 386, 492, 390, 488, 386, 488, 1256, 488, 1258, + 488, 1262, 488, 390, 488, 386, 488, 1258, 488, 390, 488, 392, + 488, 386, 488, 386, 488, 394, 488, 386, 488, 386, 488, 390, + 488, 390, 488, 386, 488, 390, 462, 412, 488, 390, 462, 1282, + 488, 390, 456, 416, 458, 1292, 456, 1288, 488, 1258, 488, 392, + 456, 422, 488, 390, 484, 392, 484, 1262, 458, 420, 484, 1262, + 482, 1262, 488, 392, 484, 394, 484, 416, 436, 442, 458, 416, + 458, 422, 430, 448, 432, 442, 458, 416, 458, 1296, 432, 1314, + 458, 1288, 432, 1312, 432, 1322, 428, 446, 428, 1318, 432, 442, + 432, 1318, 432, 1318, 428, 446, 428, 1318, 428, 1322, 430, 448, + 426, 448, 428, 452, 426, 452, 426, 448, 428, 472, 400, 478, + 402, 478, 402, 472, 402, 476, 402, 472, 402, 478, 402, 472, + 402, 1348, 398, 1348, 398, 1352, 398, 508, 370, 478, 398, 476, + 398, 512, 366, 508, 370, 502, 372, 508, 340, 538, 372, 504, + 344, 1400, 344, 1400, 346, 1434, 314, 560, 316, 588, 290, 560, + 314, 564, 396, 400, 474, 400, 480, 394, 480, 404, 474, 400, + 454, 446, 454, 426, 448, 430, 424, 450, 428, 452, 448, 426, + 426, 452, 424, 1322, 454, 426, 450, 424, 426, 452, 428, 452, + 450, 424, 428, 446, 426, 1322, 454, 426, 422, 450, 454, 426, + 448, 430, 454, 426, 448, 426, 428, 446, 454, 430, 454, 422, + 452, 424, 424, 452, 452, 430, 424, 452, 452, 426, 448, 426, + 426, 456, 448, 426, 448, 1296, 424, 1322, 426, 1326, 450, 1270, + 478, 422, 454, 424, 424, 450, 454}; + uint8_t expectedState[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x39, 0x34, 0x80, 0xAF, 0x0D, + 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x81, 0x00, 0x00, 0x1E}; + + irsend.sendRaw(rawData, 439, kPanasonicFreq); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + IRPanasonicAc pana(0); + pana.setRaw(irsend.capture.state); + // TODO(crankyoldgit): Try to figure out what model this should be. + EXPECT_EQ( + "Model: 0 (UNKNOWN), Power: On, Mode: 3 (COOL), Temp: 26C, " + "Fan: 7 (AUTO), Swing (Vertical): 15 (AUTO), " + "Swing (Horizontal): 13 (AUTO), Quiet: Off, Powerful: Off, " + "Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); +} + +TEST(TestIRPanasonicAcClass, TimeBasics) { + EXPECT_EQ(0x186, IRPanasonicAc::encodeTime(6, 30)); + EXPECT_EQ(0x3CA, IRPanasonicAc::encodeTime(16, 10)); + EXPECT_EQ(0x448, IRPanasonicAc::encodeTime(18, 16)); + EXPECT_EQ(0, IRPanasonicAc::encodeTime(0, 0)); + EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(23, 59)); + EXPECT_EQ("16:10", + IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(16, 10))); + EXPECT_EQ("6:30", + IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(6, 30))); + EXPECT_EQ("18:16", + IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(18, 16))); + EXPECT_EQ("1:01", + IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(1, 1))); + EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(23, 59)); + EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(25, 72)); + EXPECT_EQ(59, IRPanasonicAc::encodeTime(0, 72)); + EXPECT_EQ(23 * 60, IRPanasonicAc::encodeTime(27, 0)); + EXPECT_EQ("0:00", IRPanasonicAc::timeToString(0)); + EXPECT_EQ("23:59", IRPanasonicAc::timeToString(kPanasonicAcTimeMax)); +} + +TEST(TestIRPanasonicAcClass, TimersAndClock) { + IRPanasonicAc pana(0); + // Data from Issue #544 + uint8_t state[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00, + 0xCA, 0x6B, 0x98, 0x10, 0x00, 0x01, 0x48, 0x04, 0xDB}; + pana.setRaw(state); + EXPECT_TRUE(pana.isOnTimerEnabled()); + EXPECT_EQ(0x3CA, pana.getOnTimer()); + EXPECT_TRUE(pana.isOffTimerEnabled()); + EXPECT_EQ(0x186, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.cancelOnTimer(); + EXPECT_FALSE(pana.isOnTimerEnabled()); + EXPECT_EQ(0, pana.getOnTimer()); + EXPECT_TRUE(pana.isOffTimerEnabled()); + EXPECT_EQ(0x186, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.cancelOffTimer(); + EXPECT_FALSE(pana.isOnTimerEnabled()); + EXPECT_EQ(0, pana.getOnTimer()); + EXPECT_FALSE(pana.isOffTimerEnabled()); + EXPECT_EQ(0, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.setOnTimer(7 * 60 + 50); + EXPECT_TRUE(pana.isOnTimerEnabled()); + EXPECT_EQ(7 * 60 + 50, pana.getOnTimer()); + EXPECT_FALSE(pana.isOffTimerEnabled()); + EXPECT_EQ(0, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.setOnTimer(7 * 60 + 57); // It should round down. + EXPECT_EQ(7 * 60 + 50, pana.getOnTimer()); + pana.setOnTimer(28 * 60); // It should round down. + EXPECT_EQ(kPanasonicAcTimeMax - 9, pana.getOnTimer()); + pana.setOnTimer(kPanasonicAcTimeSpecial); + EXPECT_EQ(0, pana.getOnTimer()); + + pana.setOnTimer(7 * 60 + 50); + pana.setOffTimer(19 * 60 + 30); + + EXPECT_TRUE(pana.isOnTimerEnabled()); + EXPECT_EQ(7 * 60 + 50, pana.getOnTimer()); + EXPECT_TRUE(pana.isOffTimerEnabled()); + EXPECT_EQ(19 * 60 + 30, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.setOffTimer(19 * 60 + 57); // It should round down. + EXPECT_EQ(19 * 60 + 50, pana.getOffTimer()); + pana.setOffTimer(28 * 60); // It should round down. + EXPECT_EQ(kPanasonicAcTimeMax - 9, pana.getOffTimer()); + pana.setOffTimer(kPanasonicAcTimeSpecial); + EXPECT_EQ(0, pana.getOffTimer()); + + pana.setClock(0); + EXPECT_EQ(0, pana.getClock()); + pana.setClock(kPanasonicAcTimeMax); + EXPECT_EQ(kPanasonicAcTimeMax, pana.getClock()); + pana.setClock(kPanasonicAcTimeMax - 1); + EXPECT_EQ(kPanasonicAcTimeMax - 1, pana.getClock()); + pana.setClock(kPanasonicAcTimeMax + 1); + EXPECT_EQ(kPanasonicAcTimeMax, pana.getClock()); + pana.setClock(kPanasonicAcTimeSpecial); + EXPECT_EQ(0, pana.getClock()); +} + +// Decode a real short Panasonic AC message +TEST(TestDecodePanasonicAC, RealExampleOfShortMessage) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Data from Issue #544 (Odour Wash) + uint16_t rawData[263] = { + 3496, 1734, 506, 366, 448, 1294, 504, 368, 498, 374, 452, 418, + 448, 424, 444, 428, 450, 422, 446, 426, 450, 420, 448, 424, + 452, 418, 448, 422, 444, 1300, 498, 374, 504, 368, 448, 424, + 452, 418, 448, 424, 444, 428, 450, 422, 446, 1296, 500, 1242, + 502, 1242, 504, 368, 498, 374, 452, 1292, 504, 366, 450, 422, + 444, 426, 450, 420, 446, 424, 452, 418, 448, 424, 444, 428, + 450, 422, 444, 426, 450, 420, 446, 424, 452, 418, 448, 422, + 444, 428, 450, 422, 446, 426, 452, 420, 446, 426, 452, 418, + 448, 424, 442, 428, 448, 422, 444, 426, 450, 420, 446, 426, + 452, 418, 448, 424, 444, 428, 450, 422, 444, 1298, 500, 1244, + 500, 372, 444, 428, 450, 422, 446, 426, 452, 418, 448, 10020, + 3500, 1732, 498, 372, 452, 1290, 506, 366, 450, 422, 446, 426, + 452, 420, 448, 424, 452, 418, 448, 422, 444, 426, 450, 420, + 446, 426, 452, 420, 446, 1296, 500, 370, 444, 428, 450, 422, + 446, 426, 452, 420, 446, 424, 442, 428, 448, 1294, 502, 1240, + 504, 1238, 506, 366, 448, 422, 444, 1298, 498, 374, 452, 418, + 448, 424, 444, 428, 450, 422, 446, 426, 450, 420, 446, 424, + 452, 418, 448, 422, 444, 428, 450, 420, 446, 1298, 498, 1244, + 500, 1242, 502, 368, 446, 1298, 500, 1244, 500, 372, 444, 428, + 450, 1292, 504, 368, 446, 1296, 502, 370, 444, 426, 452, 1290, + 504, 1238, 506, 366, 450, 422, 446, 1298, 498, 1246, 500, 372, + 444, 428, 450, 1294, 452, 420, 446, 1296, 448, 422, 444}; // UNKNOWN + // 1FB51F79 + + uint8_t expectedState[kPanasonicAcStateShortLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, + 0x02, 0x20, 0xE0, 0x04, 0x80, 0x9B, 0x32, 0x53}; + + irsend.sendRaw(rawData, 263, kPanasonicFreq); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcShortBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Create and decode a short Panasonic AC message +TEST(TestDecodePanasonicAC, SyntheticShortMessage) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t odourWash[kPanasonicAcStateShortLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, + 0x02, 0x20, 0xE0, 0x04, 0x80, 0x9B, 0x32, 0x53}; + + irsend.sendPanasonicAC(odourWash, kPanasonicAcStateShortLength); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcShortBits, irsend.capture.bits); + EXPECT_STATE_EQ(odourWash, irsend.capture.state, irsend.capture.bits); +} +// +// Test for CKP model / see issue #544 +TEST(TestDecodePanasonicAC, CkpModelSpecifics) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Data from Issue #544 + uint8_t ckpPowerfulOn[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00, + 0x00, 0x0E, 0xE0, 0x11, 0x00, 0x01, 0x00, 0x06, 0xB7}; + uint8_t ckpQuietOn[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00, + 0x00, 0x0E, 0xE0, 0x30, 0x00, 0x01, 0x00, 0x06, 0xD6}; + + irsend.sendPanasonicAC(ckpPowerfulOn); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(ckpPowerfulOn, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + + IRPanasonicAc pana(0); + pana.setRaw(irsend.capture.state); + EXPECT_EQ( + "Model: 5 (CKP), Power: Off, Mode: 4 (HEAT), Temp: 23C, " + "Fan: 7 (AUTO), Swing (Vertical): 15 (AUTO), Quiet: Off, " + "Powerful: On, Clock: 0:00, On Timer: 0:00, Off Timer: 0:00", + pana.toString()); + + pana.setQuiet(true); + EXPECT_FALSE(pana.getPowerful()); + EXPECT_TRUE(pana.getQuiet()); + EXPECT_EQ(kPanasonicCkp, pana.getModel()); + EXPECT_STATE_EQ(ckpQuietOn, pana.getRaw(), kPanasonicAcBits); + + pana.setPowerful(true); + EXPECT_TRUE(pana.getPowerful()); + EXPECT_FALSE(pana.getQuiet()); + EXPECT_EQ(kPanasonicCkp, pana.getModel()); + EXPECT_STATE_EQ(ckpPowerfulOn, pana.getRaw(), kPanasonicAcBits); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp new file mode 100644 index 000000000..b78469add --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp @@ -0,0 +1,152 @@ +// Copyright 2018 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" +#include "gtest/gtest.h" + +// Tests for sendPioneer(). + +// Test sending typical data only. +TEST(TestSendPioneer, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + irsend.sendPioneer(0); + EXPECT_EQ( + "m8960s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s58240" + "m8960s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s58240", + irsend.outputStr()); + irsend.sendPioneer(0x55FF00AAAA00FF55); + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s40320" + "m8960s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s40320", + irsend.outputStr()); +} + +// Tests for IRutils. + +TEST(TestIRUtils, TypeToString) { EXPECT_EQ("PIONEER", typeToString(PIONEER)); } + +// Tests for encodePioneer(). + +TEST(TestEncodePioneer, SimpleEncoding) { + IRsendTest irsend(0); + IRrecv irrecv(0); + + // Spotify button (A556+AF20) + // via + // https://www.pioneerelectronics.com/StaticFiles/PUSA/Files/Home%20Custom%20Install/2015%20Pioneer%20&%20Elite%20AVR%20IR%20with%20Hex_1.xls + EXPECT_EQ(0xA55A6A95F50A04FB, irsend.encodePioneer(0xA556, 0xAF20)); + + // "Source" from + // https://github.com/markszabo/IRremoteESP8266/pull/547#issuecomment-429616582 + EXPECT_EQ(0x659A05FAF50AC53A, irsend.encodePioneer(0xA6A0, 0xAFA3)); +} + +// Tests for decodePioneer(). + +// Synthesised Normal Pioneer message. +TEST(TestDecodePioneer, SyntheticPioneerDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendPioneer(0x659A05FAF50AC53A); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PIONEER, irsend.capture.decode_type); + EXPECT_EQ(kPioneerBits, irsend.capture.bits); + EXPECT_EQ(0x659A05FAF50AC53A, irsend.capture.value); + EXPECT_EQ(0xA6A0, irsend.capture.address); + EXPECT_EQ(0xAFA3, irsend.capture.command); +} + +// Real long Pioneer message. +TEST(TestDecodePioneer, RealExampleLongDecodeSourceButton) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // "Source" button. + // https://github.com/markszabo/IRremoteESP8266/pull/547#issuecomment-429616582 + uint16_t rawData[135] = { + 8552, 4184, 596, 472, 592, 1524, 594, 1524, 594, 472, 592, 472, + 598, 1520, 596, 472, 594, 1524, 592, 1524, 592, 472, 592, 472, + 596, 1520, 598, 1520, 596, 472, 592, 1524, 592, 472, 592, 476, + 592, 472, 592, 472, 592, 476, 592, 472, 592, 1524, 592, 472, + 598, 1518, 598, 1520, 596, 1520, 596, 1520, 596, 1520, 596, 1520, + 596, 472, 592, 1524, 592, 472, 598, 25282, 8552, 4182, 596, 1520, + 598, 1518, 598, 1520, 596, 1520, 596, 472, 592, 1524, 592, 472, + 598, 1520, 596, 472, 594, 472, 592, 472, 596, 472, 592, 1524, + 592, 472, 592, 1524, 596, 472, 594, 1520, 596, 1520, 598, 472, + 592, 472, 598, 472, 594, 1522, 594, 472, 592, 1524, 594, 472, + 596, 472, 594, 1524, 592, 1524, 592, 1524, 592, 472, 594, 1524, + 598, 472, 592}; + + irsend.sendRaw(rawData, 135, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PIONEER, irsend.capture.decode_type); + EXPECT_EQ(kPioneerBits, irsend.capture.bits); + EXPECT_EQ(0x659A05FAF50AC53A, irsend.capture.value); + EXPECT_EQ(0xA6A0, irsend.capture.address); + EXPECT_EQ(0xAFA3, irsend.capture.command); +} + +// Synthetic Pioneer message. +// For: +// https://github.com/markszabo/IRremoteESP8266/pull/547#issuecomment-430800734 +TEST(TestDecodePioneer, SyntheticPioneerMessage) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendPioneer(0x659A857AF50A3DC2, 64, 0); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PIONEER, irsend.capture.decode_type); + EXPECT_EQ(kPioneerBits, irsend.capture.bits); + EXPECT_EQ(0x659A857AF50A3DC2, irsend.capture.value); + EXPECT_EQ(0xA6A1, irsend.capture.address); + EXPECT_EQ(0xAFBC, irsend.capture.command); + + irsend.reset(); + irsend.sendPioneer(0x659A857AF50A3DC2, 64, 0); + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560" + "m560s40320" + "m8960s4480" + "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560" + "m560s40320", + irsend.outputStr()); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Pronto_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Pronto_test.cpp similarity index 81% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Pronto_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Pronto_test.cpp index 7fbe39554..e52c6dd90 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Pronto_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Pronto_test.cpp @@ -79,8 +79,8 @@ TEST(TestSendPronto, MoreDataThanNeededInBoth) { irsend.reset(); // We should handle when we are given more data than needed. (repeat seq.) - uint16_t pronto_test[10] = {0x0000, 0x0067, 0x0001, 0x0001, - 0x0001, 0x0002, 0x0003, 0x0004, 0x5, 0x6}; + uint16_t pronto_test[10] = {0x0000, 0x0067, 0x0001, 0x0001, 0x0001, + 0x0002, 0x0003, 0x0004, 0x5, 0x6}; irsend.sendPronto(pronto_test, 10); EXPECT_EQ("m25s50", irsend.outputStr()); // Only send the data required. irsend.sendPronto(pronto_test, 10, 1); @@ -110,25 +110,29 @@ TEST(TestSendPronto, NonRepeatingCode) { // It was an example of a poor Pronto code. // It turned out to be a 4 copies of a Sony 12-bit code. Who knew!?! uint16_t pronto_test[108] = { - 0x0000, 0x0067, 0x0034, 0x0000, - 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0452, 0x0060, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018}; + 0x0000, 0x0067, 0x0034, 0x0000, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018}; // Send the Pronto code without any repeats set. irsend.reset(); irsend.sendPronto(pronto_test, 108); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); + EXPECT_EQ(0x10, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); EXPECT_EQ( "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" @@ -141,19 +145,20 @@ TEST(TestSendPronto, NonRepeatingCode) { "m600s600m600s600m600s600m600s27650" "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m600s600m600s600", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); - EXPECT_EQ(0x10, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); + "m600s600m600s600m600s600m600s600", + irsend.outputStr()); // Now try repeating it. // As it has no repeat sequence, we shouldn't repeat it. (I think) irsend.reset(); irsend.sendPronto(pronto_test, 108, 3); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); + EXPECT_EQ(0x10, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); EXPECT_EQ( "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" @@ -166,13 +171,8 @@ TEST(TestSendPronto, NonRepeatingCode) { "m600s600m600s600m600s600m600s27650" "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m600s600m600s600", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); - EXPECT_EQ(0x10, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); + "m600s600m600s600m600s600m600s600", + irsend.outputStr()); } // Test sending a Pronto code that only has a repeat sequence (Sony). @@ -183,34 +183,40 @@ TEST(TestSendPronto, RepeatSequenceOnlyForSony) { // Sony 20-bit command. uint16_t pronto_test[46] = { - 0x0000, 0x0067, 0x0000, 0x0015, - 0x0060, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0030, 0x0018, - 0x0030, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, - 0x0030, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0000, 0x0067, 0x0000, 0x0015, 0x0060, 0x0018, 0x0018, 0x0018, + 0x0030, 0x0018, 0x0030, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, - 0x0018, 0x03f6}; + 0x0018, 0x0018, 0x0030, 0x0018, 0x0030, 0x0018, 0x0030, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x03f6}; // Send the Pronto code without any repeats set. irsend.reset(); irsend.sendPronto(pronto_test, 46); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); + EXPECT_EQ(0x74B92, irsend.capture.value); + EXPECT_EQ(0x1A, irsend.capture.address); + EXPECT_EQ(0x24AE, irsend.capture.command); EXPECT_EQ( "m2400s600" "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" "m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s25350", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); - EXPECT_EQ(0x74B92, irsend.capture.value); - EXPECT_EQ(0x1A, irsend.capture.address); - EXPECT_EQ(0x24AE, irsend.capture.command); + "m600s600m600s600m1200s600m600s25350", + irsend.outputStr()); // Send the Pronto code with 2 repeats. irsend.reset(); - irsend.sendPronto(pronto_test, 46, SONY_MIN_REPEAT); + irsend.sendPronto(pronto_test, 46, kSonyMinRepeat); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); + EXPECT_EQ(0x74B92, irsend.capture.value); + EXPECT_EQ(0x1A, irsend.capture.address); + EXPECT_EQ(0x24AE, irsend.capture.command); EXPECT_EQ( "m2400s600" "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" @@ -223,14 +229,8 @@ TEST(TestSendPronto, RepeatSequenceOnlyForSony) { "m2400s600" "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" "m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s25350", irsend.outputStr()); - - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); - EXPECT_EQ(0x74B92, irsend.capture.value); - EXPECT_EQ(0x1A, irsend.capture.address); - EXPECT_EQ(0x24AE, irsend.capture.command); + "m600s600m600s600m1200s600m600s25350", + irsend.outputStr()); } // Test sending a Pronto code that only has a repeat sequence (Panasonic). @@ -241,25 +241,29 @@ TEST(TestSendPronto, RepeatSequenceOnlyForPanasonic) { // Panasonic Plasma TV Descrete code (Power On). uint16_t pronto_test[104] = { - 0x0000, 0x0071, 0x0000, 0x0032, - 0x0080, 0x003F, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0030, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0030, - 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0030, - 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0010, - 0x0010, 0x0030, 0x0010, 0x0A98}; + 0x0000, 0x0071, 0x0000, 0x0032, 0x0080, 0x003F, 0x0010, 0x0010, 0x0010, + 0x0030, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, + 0x0030, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, + 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, + 0x0010, 0x0010, 0x0030, 0x0010, 0x0A98}; // Send the Pronto code without any repeats set. irsend.reset(); irsend.sendPronto(pronto_test, 104); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x400401007C7D, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x1007C7D, irsend.capture.command); EXPECT_EQ( "m3456s1701" "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" @@ -268,17 +272,10 @@ TEST(TestSendPronto, RepeatSequenceOnlyForPanasonic) { "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s1296" - "m432s73224", irsend.outputStr()); - - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x400401007C7D, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x1007C7D, irsend.capture.command); + "m432s73224", + irsend.outputStr()); } - // Test sending a Pronto code that has a normal & arepeat sequence (NEC). TEST(TestSendPronto, NormalPlusRepeatSequence) { IRsendTest irsend(4); @@ -287,40 +284,45 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { // NEC 32 bit power on command. uint16_t pronto_test[76] = { - 0x0000, 0x006D, 0x0022, 0x0002, - 0x0156, 0x00AB, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, - 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, - 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, - 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, - 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, - 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, - 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, - 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, - 0x0015, 0x0040, 0x0015, 0x05FD, + 0x0000, 0x006D, 0x0022, 0x0002, 0x0156, 0x00AB, 0x0015, 0x0015, 0x0015, + 0x0015, 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0015, + 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, + 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, + 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, + 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, + 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, + 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x05FD, 0x0156, 0x0055, 0x0015, 0x0E4E}; // Send the Pronto code without any repeats set. irsend.reset(); irsend.sendPronto(pronto_test, 76); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x18E710EF, irsend.capture.value); + EXPECT_EQ(0x18, irsend.capture.address); + EXPECT_EQ(0x8, irsend.capture.command); EXPECT_EQ( "m8892s4446" "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" "m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664" "m546s546m546s546m546s546m546s1664m546s546m546s546m546s546m546s546" "m546s1664m546s1664m546s1664m546s546m546s1664m546s1664m546s1664m546s1664" - "m546s39858", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0x18E710EF, irsend.capture.value); - EXPECT_EQ(0x18, irsend.capture.address); - EXPECT_EQ(0x8, irsend.capture.command); + "m546s39858", + irsend.outputStr()); // Send it again with a single repeat. irsend.reset(); irsend.sendPronto(pronto_test, 76, 1); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x18E710EF, irsend.capture.value); + EXPECT_EQ(0x18, irsend.capture.address); + EXPECT_EQ(0x8, irsend.capture.command); EXPECT_EQ( "m8892s4446" "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" @@ -328,18 +330,19 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { "m546s546m546s546m546s546m546s1664m546s546m546s546m546s546m546s546" "m546s1664m546s1664m546s1664m546s546m546s1664m546s1664m546s1664m546s1664" "m546s39858" - "m8892s2210m546s95212", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0x18E710EF, irsend.capture.value); - EXPECT_EQ(0x18, irsend.capture.address); - EXPECT_EQ(0x8, irsend.capture.command); + "m8892s2210m546s95212", + irsend.outputStr()); // Send it again with a two repeats. irsend.reset(); irsend.sendPronto(pronto_test, 76, 2); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x18E710EF, irsend.capture.value); + EXPECT_EQ(0x18, irsend.capture.address); + EXPECT_EQ(0x8, irsend.capture.command); EXPECT_EQ( "m8892s4446" "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" @@ -348,11 +351,6 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { "m546s1664m546s1664m546s1664m546s546m546s1664m546s1664m546s1664m546s1664" "m546s39858" "m8892s2210m546s95212" - "m8892s2210m546s95212", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0x18E710EF, irsend.capture.value); - EXPECT_EQ(0x18, irsend.capture.address); - EXPECT_EQ(0x8, irsend.capture.command); + "m8892s2210m546s95212", + irsend.outputStr()); } diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_RC5_RC6_test.cpp similarity index 70% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_RC5_RC6_test.cpp index ef508e40e..e8aa9bfc1 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_RC5_RC6_test.cpp @@ -77,55 +77,59 @@ TEST(TestSendRC5, SendDataOnly) { irsend.begin(); irsend.reset(); - irsend.sendRC5(0x0, RC5_BITS); + irsend.sendRC5(0x0, kRC5Bits); EXPECT_EQ( "m889s889m1778s889m889s889m889s889m889s889m889s889m889" - "s889m889s889m889s889m889s889m889s889m889s889m889s114667", + "s889m889s889m889s889m889s889m889s889m889s889m889s90664", irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x1AAA, RC5_BITS); + irsend.sendRC5(0x1AAA, kRC5Bits); EXPECT_EQ( "m889s889m889s889m1778s1778m1778s1778m1778s1778" - "m1778s1778m1778s1778m1778s114667", irsend.outputStr()); + "m1778s1778m1778s1778m1778s90664", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x175, RC5_BITS); + irsend.sendRC5(0x175, kRC5Bits); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s89775", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x3FFF, RC5_BITS); + irsend.sendRC5(0x3FFF, kRC5Bits); EXPECT_EQ( "m889s889m889s889m889s889m889s889m889s889m889s889m889s889" - "m889s889m889s889m889s889m889s889m889s889m889s889m889s113778", + "m889s889m889s889m889s889m889s889m889s889m889s889m889s89775", irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x0, RC5X_BITS); + irsend.sendRC5(0x0, kRC5XBits); EXPECT_EQ( "m889s889m1778s889m889s889m889s889m889s889m889s889m889" - "s889m889s889m889s889m889s889m889s889m889s889m889s114667", + "s889m889s889m889s889m889s889m889s889m889s889m889s90664", irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x1AAA, RC5X_BITS); + irsend.sendRC5(0x1AAA, kRC5XBits); EXPECT_EQ( "m1778s1778m1778s1778m1778s1778m1778" - "s1778m1778s1778m1778s1778m1778s114667", irsend.outputStr()); + "s1778m1778s1778m1778s1778m1778s90664", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x175, RC5X_BITS); + irsend.sendRC5(0x175, kRC5XBits); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s89775", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x3FFF, RC5X_BITS); + irsend.sendRC5(0x3FFF, kRC5XBits); EXPECT_EQ( "m1778s1778m889s889m889s889m889s889m889s889m889s889m889" - "s889m889s889m889s889m889s889m889s889m889s889m889s113778", + "s889m889s889m889s889m889s889m889s889m889s889m889s89775", irsend.outputStr()); } @@ -135,40 +139,44 @@ TEST(TestSendRC5, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendRC5(0x175, RC5_BITS, 1); + irsend.sendRC5(0x175, kRC5Bits, 1); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s90664" "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s88886", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x175, RC5_BITS, 2); + irsend.sendRC5(0x175, kRC5Bits, 2); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s90664" "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s89775" "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s88886", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x175, RC5X_BITS, 1); + irsend.sendRC5(0x175, kRC5XBits, 1); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s90664" "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s88886", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x1175, RC5X_BITS, 2); + irsend.sendRC5(0x1175, kRC5XBits, 2); EXPECT_EQ( "m1778s889m889s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s90664" "m1778s889m889s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s89775" "m1778s889m889s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s88886", + irsend.outputStr()); } // Tests for decodeRC5(). @@ -182,9 +190,9 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(0x175); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x35, irsend.capture.command); @@ -194,9 +202,9 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(0x175); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x35, irsend.capture.command); @@ -205,11 +213,11 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { // A RC-5X 13-bit message but with a value that is valid for RC-5 decoded // as RC5-X. irsend.reset(); - irsend.sendRC5(0x175, RC5X_BITS); + irsend.sendRC5(0x175, kRC5XBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x35, irsend.capture.command); @@ -219,9 +227,9 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(irsend.encodeRC5(0x00, 0x0B, true)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x80B, irsend.capture.value); EXPECT_EQ(0x00, irsend.capture.address); EXPECT_EQ(0x0B, irsend.capture.command); @@ -229,11 +237,11 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { // Synthesised Normal RC-5X 13-bit message. irsend.reset(); - irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), RC5X_BITS); + irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); EXPECT_EQ(RC5X, irsend.capture.decode_type); - EXPECT_EQ(RC5X_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5XBits, irsend.capture.bits); EXPECT_EQ(0x1881, irsend.capture.value); EXPECT_EQ(0x02, irsend.capture.address); EXPECT_EQ(0x41, irsend.capture.command); @@ -242,9 +250,9 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { // Synthesised Normal RC-5X 13-bit message should fail at being decoded // as a normal RC-5 (12 bit) message. irsend.reset(); - irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), RC5X_BITS); + irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); } // Decode normal repeated RC5 messages. @@ -255,33 +263,33 @@ TEST(TestDecodeRC5, NormalDecodeWithRepeatAndStrict) { // Normal RC-5 12-bit (even) message with one repeat. irsend.reset(); - irsend.sendRC5(0x174, RC5_BITS, 1); + irsend.sendRC5(0x174, kRC5Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x34, irsend.capture.command); // Normal RC-5 12-bit (odd) message with one repeat. irsend.reset(); - irsend.sendRC5(0x175, RC5_BITS, 1); + irsend.sendRC5(0x175, kRC5Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x35, irsend.capture.command); // Synthesised Normal RC-5X 13-bit message with 2 repeats. irsend.reset(); - irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), RC5X_BITS, 2); + irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); EXPECT_EQ(RC5X, irsend.capture.decode_type); - EXPECT_EQ(RC5X_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5XBits, irsend.capture.bits); EXPECT_EQ(0x1881, irsend.capture.value); EXPECT_EQ(0x02, irsend.capture.address); EXPECT_EQ(0x41, irsend.capture.command); @@ -297,8 +305,8 @@ TEST(TestDecodeRC5, DecodeWithNonStrictValues) { irsend.sendRC5(0xFA, 8); // Illegal value RC5 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 8, false)); EXPECT_EQ(RC5, irsend.capture.decode_type); @@ -311,8 +319,8 @@ TEST(TestDecodeRC5, DecodeWithNonStrictValues) { irsend.sendRC5(0x12345678, 32); // Illegal size RC5 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -327,8 +335,8 @@ TEST(TestDecodeRC5, DecodeWithNonStrictValues) { irsend.sendRC5(0x87654321, 32); // Illegal size RC5 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -364,14 +372,15 @@ TEST(TestDecodeRC5, FailToDecodeNonRC5Example) { irsend.begin(); irsend.reset(); - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, false)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, false)); } // RRRRRR CCCCC 666 @@ -383,24 +392,24 @@ TEST(TestDecodeRC5, FailToDecodeNonRC5Example) { // Tests for encodeRC6(). TEST(TestEncodeRC6, Mode0Encoding) { IRsendTest irsend(4); - EXPECT_EQ(0x0, irsend.encodeRC6(0, 0, RC6_MODE0_BITS)); - EXPECT_EQ(0x1234, irsend.encodeRC6(0x12, 0x34, RC6_MODE0_BITS)); - EXPECT_EQ(0x12345, irsend.encodeRC6(0x123, 0x45, RC6_MODE0_BITS)); - EXPECT_EQ(0xFFFFF, irsend.encodeRC6(0xFFF, 0xFF, RC6_MODE0_BITS)); - EXPECT_EQ(0xFFF00, irsend.encodeRC6(0xFFFF, 0x00, RC6_MODE0_BITS)); - EXPECT_EQ(0xFF, irsend.encodeRC6(0x00, 0xFF, RC6_MODE0_BITS)); + EXPECT_EQ(0x0, irsend.encodeRC6(0, 0, kRC6Mode0Bits)); + EXPECT_EQ(0x1234, irsend.encodeRC6(0x12, 0x34, kRC6Mode0Bits)); + EXPECT_EQ(0x12345, irsend.encodeRC6(0x123, 0x45, kRC6Mode0Bits)); + EXPECT_EQ(0xFFFFF, irsend.encodeRC6(0xFFF, 0xFF, kRC6Mode0Bits)); + EXPECT_EQ(0xFFF00, irsend.encodeRC6(0xFFFF, 0x00, kRC6Mode0Bits)); + EXPECT_EQ(0xFF, irsend.encodeRC6(0x00, 0xFF, kRC6Mode0Bits)); } TEST(TestEncodeRC6, 36BitEncoding) { IRsendTest irsend(4); - EXPECT_EQ(0x0, irsend.encodeRC6(0, 0, RC6_36_BITS)); - EXPECT_EQ(0x1234, irsend.encodeRC6(0x12, 0x34, RC6_36_BITS)); - EXPECT_EQ(0x123456789, irsend.encodeRC6(0x1234567, 0x89, RC6_36_BITS)); - EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFF, 0xFF, RC6_36_BITS)); - EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFFF, 0xFF, RC6_36_BITS)); - EXPECT_EQ(0xFFFFFFF00, irsend.encodeRC6(0xFFFFFFF, 0x00, RC6_36_BITS)); - EXPECT_EQ(0xFF, irsend.encodeRC6(0x0, 0xFF, RC6_36_BITS)); - EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFFF, 0xFF, RC6_36_BITS)); + EXPECT_EQ(0x0, irsend.encodeRC6(0, 0, kRC6_36Bits)); + EXPECT_EQ(0x1234, irsend.encodeRC6(0x12, 0x34, kRC6_36Bits)); + EXPECT_EQ(0x123456789, irsend.encodeRC6(0x1234567, 0x89, kRC6_36Bits)); + EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFF, 0xFF, kRC6_36Bits)); + EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFFF, 0xFF, kRC6_36Bits)); + EXPECT_EQ(0xFFFFFFF00, irsend.encodeRC6(0xFFFFFFF, 0x00, kRC6_36Bits)); + EXPECT_EQ(0xFF, irsend.encodeRC6(0x0, 0xFF, kRC6_36Bits)); + EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFFF, 0xFF, kRC6_36Bits)); } // Tests for toggleRC6(). @@ -410,7 +419,7 @@ TEST(TestToggleRC6, Mode0) { IRsendTest irsend(4); EXPECT_EQ(0x10000, irsend.toggleRC6(0x0)); - EXPECT_EQ(irsend.toggleRC6(0x0), irsend.toggleRC6(0x0, RC6_MODE0_BITS)); + EXPECT_EQ(irsend.toggleRC6(0x0), irsend.toggleRC6(0x0, kRC6Mode0Bits)); EXPECT_EQ(0x0, irsend.toggleRC6(0x10000)); EXPECT_EQ(0x0, irsend.toggleRC6(irsend.toggleRC6(0x0))); } @@ -419,10 +428,10 @@ TEST(TestToggleRC6, Mode0) { TEST(TestToggleRC6, 36BitUse) { IRsendTest irsend(4); - EXPECT_EQ(0x8000, irsend.toggleRC6(0x0, RC6_36_BITS)); - EXPECT_EQ(0x0, irsend.toggleRC6(0x8000, RC6_36_BITS)); - EXPECT_EQ(0x0, irsend.toggleRC6(irsend.toggleRC6(0x0, RC6_36_BITS), - RC6_36_BITS)); + EXPECT_EQ(0x8000, irsend.toggleRC6(0x0, kRC6_36Bits)); + EXPECT_EQ(0x0, irsend.toggleRC6(0x8000, kRC6_36Bits)); + EXPECT_EQ(0x0, + irsend.toggleRC6(irsend.toggleRC6(0x0, kRC6_36Bits), kRC6_36Bits)); } // Tests for sendRC6(). @@ -439,7 +448,8 @@ TEST(TestSendRC6, SendMode0DataOnly) { "m444s888m444s444m444s444m444s888m888s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444" - "s83028", irsend.outputStr()); + "s83028", + irsend.outputStr()); irsend.reset(); irsend.sendRC6(0x1FFFF); @@ -448,7 +458,8 @@ TEST(TestSendRC6, SendMode0DataOnly) { "m444s888m444s444m444s444m1332s888m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444" - "s83472", irsend.outputStr()); + "s83472", + irsend.outputStr()); irsend.reset(); irsend.sendRC6(0x15555); @@ -456,7 +467,8 @@ TEST(TestSendRC6, SendMode0DataOnly) { "m2664s888" "m444s888m444s444m444s444m1332s1332m888s888m888s888" "m888s888m888s888m888s888m888s888m888s888m888" - "s83472", irsend.outputStr()); + "s83472", + irsend.outputStr()); } // Test sending typical RC-6 36-bit data only. @@ -465,7 +477,7 @@ TEST(TestSendRC6, Send36BitDataOnly) { irsend.begin(); irsend.reset(); - irsend.sendRC6(0x0, RC6_36_BITS); + irsend.sendRC6(0x0, kRC6_36Bits); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -474,10 +486,11 @@ TEST(TestSendRC6, Send36BitDataOnly) { "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" - "s83028", irsend.outputStr()); + "s83028", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0xFFFFFFFFF, RC6_36_BITS); + irsend.sendRC6(0xFFFFFFFFF, kRC6_36Bits); EXPECT_EQ( "m2664s888" "m444s444m444s444m444s444m444s444" @@ -486,10 +499,11 @@ TEST(TestSendRC6, Send36BitDataOnly) { "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" - "s83472", irsend.outputStr()); + "s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0xAAAAAAAAAA, RC6_36_BITS); + irsend.sendRC6(0xAAAAAAAAAA, kRC6_36Bits); EXPECT_EQ( "m2664s888m444s444m444s888m888" "s1332m1332" @@ -498,7 +512,7 @@ TEST(TestSendRC6, Send36BitDataOnly) { irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0xC800F740C, RC6_36_BITS); // Xbox 360 OnOff code + irsend.sendRC6(0xC800F740C, kRC6_36Bits); // Xbox 360 OnOff code EXPECT_EQ( "m2664s888" "m444s444m444s444m444s888m444" @@ -506,10 +520,11 @@ TEST(TestSendRC6, Send36BitDataOnly) { "s888m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m888s444m444s444m444s444m444s888m888s444m444" "s444m444s888m888s888m444s444m444s444m444s444m444s444m444s444m888" - "s444m444s888m444s444m444s83028", irsend.outputStr()); + "s444m444s888m444s444m444s83028", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(irsend.toggleRC6(0xC800F740C, RC6_36_BITS), - RC6_36_BITS); // Xbox 360 OnOff code (toggled) + irsend.sendRC6(irsend.toggleRC6(0xC800F740C, kRC6_36Bits), + kRC6_36Bits); // Xbox 360 OnOff code (toggled) EXPECT_EQ( "m2664s888" "m444s444m444s444m444s888m444" @@ -517,7 +532,8 @@ TEST(TestSendRC6, Send36BitDataOnly) { "s888m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m888s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s888m888s888m444s444m444s444m444s444m444s444m444" - "s444m888s444m444s888m444s444m444s83028", irsend.outputStr()); + "s444m888s444m444s888m444s444m444s83028", + irsend.outputStr()); } // Test sending RC-6 Mode 0 with different repeats. @@ -526,16 +542,17 @@ TEST(TestSendRC6, SendMode0WithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS, 0); + irsend.sendRC6(0x175, kRC6Mode0Bits, 0); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" "s888m888" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS, 1); + irsend.sendRC6(0x175, kRC6Mode0Bits, 1); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -546,10 +563,11 @@ TEST(TestSendRC6, SendMode0WithRepeats) { "m444s888m444s444m444s444m444" "s888m888" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS, 2); + irsend.sendRC6(0x175, kRC6Mode0Bits, 2); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -565,7 +583,8 @@ TEST(TestSendRC6, SendMode0WithRepeats) { "m444s888m444s444m444s444m444" "s888m888" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); } // Test sending RC-6 36-bit with different repeats. @@ -574,7 +593,7 @@ TEST(TestSendRC6, Send36BitWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS, 0); + irsend.sendRC6(0x175, kRC6_36Bits, 0); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -582,10 +601,11 @@ TEST(TestSendRC6, Send36BitWithRepeats) { "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS, 1); + irsend.sendRC6(0x175, kRC6_36Bits, 1); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -600,10 +620,11 @@ TEST(TestSendRC6, Send36BitWithRepeats) { "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS, 2); + irsend.sendRC6(0x175, kRC6_36Bits, 2); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -625,7 +646,8 @@ TEST(TestSendRC6, Send36BitWithRepeats) { "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); } // Tests for decodeRC6(). @@ -640,9 +662,9 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { irsend.reset(); irsend.sendRC6(0x175); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); @@ -650,11 +672,11 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { // Normal Synthesised RC-6 Mode 0 (20-bit) message. irsend.reset(); - irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, RC6_MODE0_BITS)); + irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, kRC6Mode0Bits)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x56789, irsend.capture.value); EXPECT_EQ(0x567, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -662,11 +684,11 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { // Same again, but encoded manually. irsend.reset(); - irsend.sendRC6(0x123456789, RC6_MODE0_BITS); + irsend.sendRC6(0x123456789, kRC6Mode0Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x56789, irsend.capture.value); EXPECT_EQ(0x567, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -681,11 +703,11 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithStrict) { // Normal RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS); + irsend.sendRC6(0x175, kRC6_36Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); @@ -693,11 +715,11 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithStrict) { // Normal Synthesised RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, RC6_36_BITS), RC6_36_BITS); + irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, kRC6_36Bits), kRC6_36Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x123456789, irsend.capture.value); EXPECT_EQ(0x1234567, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -712,22 +734,22 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithRepeatAndStrict) { // Normal RC-6 Mode 0 (20-bit) even message with one repeat. irsend.reset(); - irsend.sendRC6(0x174, RC6_MODE0_BITS, 1); + irsend.sendRC6(0x174, kRC6Mode0Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x74, irsend.capture.command); // Normal RC-6 Mode 0 (20-bit) odd message with one repeat. irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS, 1); + irsend.sendRC6(0x175, kRC6Mode0Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); @@ -741,22 +763,22 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithRepeatAndStrict) { // Normal RC-6 36-bit odd message with one repeat. irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS, 1); + irsend.sendRC6(0x175, kRC6_36Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); // Normal RC-6 36-bit even message with one repeat. irsend.reset(); - irsend.sendRC6(0x174, RC6_36_BITS, 1); + irsend.sendRC6(0x174, kRC6_36Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x74, irsend.capture.command); @@ -770,11 +792,11 @@ TEST(TestDecodeRC6, NormalDecodeWithoutStrict) { // Normal RC-6 Mode 0 (20-bit) message. irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS); + irsend.sendRC6(0x175, kRC6Mode0Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); @@ -782,11 +804,11 @@ TEST(TestDecodeRC6, NormalDecodeWithoutStrict) { // Normal RC-6 Mode 0 (20-bit) message. irsend.reset(); - irsend.sendRC6(0x174, RC6_MODE0_BITS); + irsend.sendRC6(0x174, kRC6Mode0Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x74, irsend.capture.command); @@ -794,11 +816,11 @@ TEST(TestDecodeRC6, NormalDecodeWithoutStrict) { // Normal RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(0x174, RC6_36_BITS); + irsend.sendRC6(0x174, kRC6_36Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x74, irsend.capture.command); @@ -806,11 +828,11 @@ TEST(TestDecodeRC6, NormalDecodeWithoutStrict) { // Normal Synthesised RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, RC6_36_BITS), RC6_36_BITS); + irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, kRC6_36Bits), kRC6_36Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x123456789, irsend.capture.value); EXPECT_EQ(0x1234567, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -825,17 +847,17 @@ TEST(TestDecodeRC6, Decode36BitGlobalCacheExample) { irsend.reset(); // Xbox-360 Power On from Global Cache. - uint16_t gc_test[65] = {36000, 1, 1, 96, 32, 16, 16, 16, 16, 16, 32, 16, 32, - 48, 32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 16, 16, 16, - 16, 16, 16, 32, 32, 16, 16, 16, 16, 32, 32, 32, 16, - 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 16, 2476}; + uint16_t gc_test[65] = { + 36000, 1, 1, 96, 32, 16, 16, 16, 16, 16, 32, 16, 32, 48, 32, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 32, 16, 16, 16, 16, 16, 16, 32, 32, 16, 16, 16, 16, 32, 32, 32, + 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 16, 2476}; irsend.sendGC(gc_test, 65); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0xC800F742A, irsend.capture.value); EXPECT_EQ(0xC800F74, irsend.capture.address); EXPECT_EQ(0x2A, irsend.capture.command); @@ -849,25 +871,26 @@ TEST(TestDecodeRC5, FailToDecodeNonRC6Example) { irsend.begin(); irsend.reset(); - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, false)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, false)); irsend.reset(); irsend.sendRC5(0x0); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, false)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, false)); } diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_RCMM_test.cpp similarity index 72% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_RCMM_test.cpp index 2115dcb2e..028dbd8b3 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_RCMM_test.cpp @@ -13,16 +13,20 @@ TEST(TestSendRCMM, SendDataOnly) { irsend.reset(); irsend.sendRCMM(0xe0a600); - EXPECT_EQ("m416s277" - "m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s19600", + irsend.outputStr()); irsend.reset(); irsend.sendRCMM(0x28e0a600UL, 32); - EXPECT_EQ("m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s17160", + irsend.outputStr()); } // Test sending with different repeats. @@ -32,36 +36,42 @@ TEST(TestSendRCMM, SendWithRepeats) { irsend.reset(); irsend.sendRCMM(0x28e0a600, 32, 2); // 2 repeats. - EXPECT_EQ("m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778" - "m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778" - "m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s17160" + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s17160" + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s17160", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendRCMM, SendUsualSize) { +TEST(TestSendRCMM, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); irsend.reset(); irsend.sendRCMM(0xE0, 8); - EXPECT_EQ("m416s277" - "m166s777m166s611m166s277m166s277" - "m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s777m166s611m166s277m166s277" + "m166s24313", + irsend.outputStr()); irsend.reset(); irsend.sendRCMM(0x28e0a60000UL, 40); - EXPECT_EQ("m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s277m166s277m166s277m166s277m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s277m166s277m166s277m166s277m166s15388", + irsend.outputStr()); } // Tests for decodeRCMM(). @@ -76,9 +86,9 @@ TEST(TestDecodeRCMM, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRCMM(0xe0a600); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, RCMM_BITS, true)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kRCMMBits, true)); EXPECT_EQ(RCMM, irsend.capture.decode_type); - EXPECT_EQ(RCMM_BITS, irsend.capture.bits); + EXPECT_EQ(kRCMMBits, irsend.capture.bits); EXPECT_EQ(0xe0a600, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -203,14 +213,15 @@ TEST(TestDecodeRCMM, FailToDecodeNonRCMMExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, RCMM_BITS, false)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, kRCMMBits, false)); } // Issue 281 Debugging @@ -220,11 +231,12 @@ TEST(TestDecodeRCMM, DebugIssue281) { irsend.begin(); // Data from Issue #281 (shortened version) - uint16_t rawData[36] = {448, 276, 150, 285, 164, 613, 163, 447, 162, 613, - 164, 445, 164, 776, 167, 278, 163, 280, 163, 280, - 162, 611, 168, 444, 163, 612, 164, 277, 168, 447, - 157, 282, 165, 276, - 165, 65535}; // Last value modified from 89729 + uint16_t + rawData[36] = {448, 276, 150, 285, 164, 613, 163, 447, 162, 613, + 164, 445, 164, 776, 167, 278, 163, 280, 163, 280, + 162, 611, 168, 444, 163, 612, 164, 277, 168, 447, + 157, 282, 165, 276, 165, 65535}; // Last value modified + // from 89729 irsend.reset(); irsend.sendRaw(rawData, 36, 36); diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp new file mode 100644 index 000000000..9ee1fcabb --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp @@ -0,0 +1,907 @@ +// Copyright 2017 David Conran + +#include "ir_Samsung.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendSAMSUNG(). + +// Test sending typical data only. +TEST(TestSendSamsung, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSAMSUNG(0xE0E09966); // Samsung TV Power On. + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040", + irsend.outputStr()); + + irsend.reset(); +} + +// Test sending with different repeats. +TEST(TestSendSamsung, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSAMSUNG(0xE0E09966, kSamsungBits, 1); // 1 repeat. + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040", + irsend.outputStr()); + irsend.sendSAMSUNG(0xE0E09966, kSamsungBits, 2); // 2 repeats. + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040", + irsend.outputStr()); +} + +// Tests for encodeSAMSUNG(). + +TEST(TestEncodeSamsung, NormalEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0xFF, irsend.encodeSAMSUNG(0, 0)); + EXPECT_EQ(0x8080807F, irsend.encodeSAMSUNG(1, 1)); + EXPECT_EQ(0xF8F805FA, irsend.encodeSAMSUNG(0x1F, 0xA0)); + EXPECT_EQ(0xA0A0CC33, irsend.encodeSAMSUNG(0x05, 0x33)); + EXPECT_EQ(0xFFFFFF00, irsend.encodeSAMSUNG(0xFF, 0xFF)); + EXPECT_EQ(0xE0E09966, irsend.encodeSAMSUNG(0x07, 0x99)); +} + +// Tests for decodeSAMSUNG(). + +// Decode normal Samsung messages. +TEST(TestDecodeSamsung, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Samsung 32-bit message. + irsend.reset(); + irsend.sendSAMSUNG(0xE0E09966); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + + // Synthesised Normal Samsung 32-bit message. + irsend.reset(); + irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x07, 0x99)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + + // Synthesised Normal Samsung 32-bit message. + irsend.reset(); + irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0x8080807F, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x1, irsend.capture.command); +} + +// Decode normal repeated Samsung messages. +TEST(TestDecodeSamsung, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Samsung 32-bit message. + irsend.reset(); + irsend.sendSAMSUNG(0xE0E09966, kSamsungBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); +} + +// Decode unsupported Samsung messages. +TEST(TestDecodeSamsung, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSAMSUNG(0x0); // Illegal value Samsung 32-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendSAMSUNG(0x12345678); // Illegal value Samsung 32-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + EXPECT_EQ(0x48, irsend.capture.address); + EXPECT_EQ(0x6A, irsend.capture.command); + + // Illegal over length (36-bit) message. + irsend.reset(); + irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0, 0), 36); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // Shouldn't pass if strict off and wrong expected bit size. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + // Re-decode with correct bit size. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 36, true)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 36, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(36, irsend.capture.bits); + EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 8 bits less. + EXPECT_EQ(0x00, irsend.capture.address); + EXPECT_EQ(0x00, irsend.capture.command); + + // Illegal under length (16-bit) message + irsend.reset(); + irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x0, 0x0), 16); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // And it should fail when we expect more bits. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + + // Should pass if strict off if we ask for correct nr. of bits sent. + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 16, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(16, irsend.capture.bits); + EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 4 bits less. + EXPECT_EQ(0x00, irsend.capture.address); + EXPECT_EQ(0x00, irsend.capture.command); + + // Should fail as we are expecting less bits than there are. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 12, false)); +} + +// Decode (non-standard) 64-bit messages. +// Decode unsupported Samsung messages. +TEST(TestDecodeSamsung, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size Samsung 64-bit message. + irsend.sendSAMSUNG(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 64, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0xFF, irsend.capture.address); + EXPECT_EQ(0xFF, irsend.capture.command); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeSamsung, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Samsung TV Power On from Global Cache. + uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, 22, + 64, 22, 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 64, 22, 21, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 1820}; + irsend.sendGC(gc_test, 71); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); +} + +// Fail to decode a non-Samsung example via GlobalCache +TEST(TestDecodeSamsung, FailToDecodeNonSamsungExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Modified a few entries to unexpected values, based on previous test case. + uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 21, 22, 11, 22, 21, 22, 128, 22, + 64, 22, 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 64, 22, 21, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 1820}; + irsend.sendGC(gc_test, 71); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); +} + +// Tests for sendSamsungAC(). + +// Test sending typical data only. +TEST(TestSendSamsungAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + uint8_t data[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x00, 0x15, 0xF0}; + irsend.sendSamsungAC(data); + EXPECT_EQ( + "m690s17844" + "m3086s8864" + "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s1432m586s436m586s436m586s1432" + "m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432" + "m586s2886" + "m3086s8864" + "m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s1432m586s1432m586s1432m586s1432m586s436m586s1432m586s436m586s1432" + "m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s1432m586s436m586s1432m586s436m586s1432m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432" + "m586s100000", + irsend.outputStr()); +} + +// Test sending extended data. +TEST(TestSendSamsungAC, SendExtendedData) { + IRsendTest irsend(0); + irsend.begin(); + // "Off" message. + uint8_t data[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; + irsend.sendSamsungAC(data, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "m690s17844" + "m3086s8864" + "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s1432m586s1432m586s436m586s1432" + "m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s1432m586s1432" + "m586s2886" + "m3086s8864" + "m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432" + "m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s2886" + "m3086s8864" + "m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432" + "m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s1432" + "m586s1432m586s436m586s436m586s436m586s1432m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s1432m586s1432" + "m586s100000", + irsend.outputStr()); +} + +// Tests for IRSamsungAc class. + +TEST(TestIRSamsungAcClass, SetAndGetRaw) { + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0xE2, 0xFE, + 0x71, 0x40, 0x11, 0xF0}; + IRSamsungAc samsung(0); + samsung.setRaw(expectedState); + EXPECT_STATE_EQ(expectedState, samsung.getRaw(), kSamsungAcBits); + uint8_t extendedState[kSamsungAcExtendedStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; + samsung.setRaw(extendedState, kSamsungAcExtendedStateLength); + // We should NOT get the extended state back. + EXPECT_STATE_EQ(expectedState, samsung.getRaw(), kSamsungAcBits); +} + +TEST(TestIRSamsungAcClass, SetAndGetPower) { + IRSamsungAc samsung(0); + samsung.on(); + EXPECT_TRUE(samsung.getPower()); + samsung.off(); + EXPECT_FALSE(samsung.getPower()); + samsung.setPower(true); + EXPECT_TRUE(samsung.getPower()); + samsung.setPower(false); + EXPECT_FALSE(samsung.getPower()); +} + +TEST(TestIRSamsungAcClass, SetAndGetSwing) { + IRSamsungAc samsung(0); + samsung.setSwing(true); + EXPECT_TRUE(samsung.getSwing()); + samsung.setSwing(false); + EXPECT_FALSE(samsung.getSwing()); + samsung.setSwing(true); + EXPECT_TRUE(samsung.getSwing()); + + // Real examples from: + // https://github.com/markszabo/IRremoteESP8266/issues/505#issuecomment-424036602 + // TODO(Hollako): Explain why state[9] lowest bit changes between on and off. + const uint8_t expected_off[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; + samsung.setRaw(expected_off); + EXPECT_FALSE(samsung.getSwing()); + const uint8_t expected_on[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x80, 0x11, 0xF0}; + samsung.setRaw(expected_on); + EXPECT_TRUE(samsung.getSwing()); +} + +TEST(TestIRSamsungAcClass, SetAndGetClean) { + IRSamsungAc samsung(0); + samsung.setClean(true); + EXPECT_TRUE(samsung.getClean()); + samsung.setClean(false); + EXPECT_FALSE(samsung.getClean()); + samsung.setClean(true); + EXPECT_TRUE(samsung.getClean()); +} + +TEST(TestIRSamsungAcClass, SetAndGetBeep) { + IRSamsungAc samsung(0); + samsung.setBeep(false); + EXPECT_FALSE(samsung.getBeep()); + samsung.setBeep(true); + EXPECT_TRUE(samsung.getBeep()); + samsung.setBeep(false); + EXPECT_FALSE(samsung.getBeep()); + samsung.setBeep(true); + EXPECT_TRUE(samsung.getBeep()); +} + +TEST(TestIRSamsungAcClass, SetAndGetTemp) { + IRSamsungAc samsung(0); + samsung.setTemp(25); + EXPECT_EQ(25, samsung.getTemp()); + samsung.setTemp(kSamsungAcMinTemp); + EXPECT_EQ(kSamsungAcMinTemp, samsung.getTemp()); + samsung.setTemp(kSamsungAcMinTemp - 1); + EXPECT_EQ(kSamsungAcMinTemp, samsung.getTemp()); + samsung.setTemp(kSamsungAcMaxTemp); + EXPECT_EQ(kSamsungAcMaxTemp, samsung.getTemp()); + samsung.setTemp(kSamsungAcMaxTemp + 1); + EXPECT_EQ(kSamsungAcMaxTemp, samsung.getTemp()); +} + +TEST(TestIRSamsungAcClass, SetAndGetMode) { + IRSamsungAc samsung(0); + samsung.setMode(kSamsungAcCool); + EXPECT_EQ(kSamsungAcCool, samsung.getMode()); + EXPECT_NE(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setMode(kSamsungAcHeat); + EXPECT_EQ(kSamsungAcHeat, samsung.getMode()); + EXPECT_NE(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setMode(kSamsungAcAuto); + EXPECT_EQ(kSamsungAcAuto, samsung.getMode()); + EXPECT_EQ(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setMode(kSamsungAcDry); + EXPECT_EQ(kSamsungAcDry, samsung.getMode()); + EXPECT_NE(kSamsungAcFanAuto2, samsung.getFan()); +} + +TEST(TestIRSamsungAcClass, SetAndGetFan) { + IRSamsungAc samsung(0); + samsung.setMode(kSamsungAcCool); // Most fan modes avail in this setting. + samsung.setFan(kSamsungAcFanAuto); + EXPECT_EQ(kSamsungAcFanAuto, samsung.getFan()); + samsung.setFan(kSamsungAcFanLow); + EXPECT_EQ(kSamsungAcFanLow, samsung.getFan()); + samsung.setFan(kSamsungAcFanAuto2); // Not available in Cool mode. + EXPECT_EQ(kSamsungAcFanLow, samsung.getFan()); // Shouldn't change. + samsung.setMode(kSamsungAcAuto); // Has special fan setting. + EXPECT_EQ(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setFan(kSamsungAcFanLow); // Shouldn't be available in Auto mode. + EXPECT_EQ(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setMode(kSamsungAcHeat); // Most fan modes avail in this setting. + samsung.setFan(kSamsungAcFanHigh); + EXPECT_EQ(kSamsungAcFanHigh, samsung.getFan()); +} + +TEST(TestIRSamsungAcClass, SetAndGetQuiet) { + IRSamsungAc samsung(0); + samsung.setQuiet(false); + EXPECT_FALSE(samsung.getQuiet()); + samsung.setFan(kSamsungAcFanHigh); + samsung.setQuiet(true); + EXPECT_TRUE(samsung.getQuiet()); + EXPECT_EQ(kSamsungAcFanAuto, samsung.getFan()); + samsung.setQuiet(false); + EXPECT_FALSE(samsung.getQuiet()); +} + +TEST(TestIRSamsungAcClass, ChecksumCalculation) { + IRSamsungAc samsung(0); + + const uint8_t originalstate[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x00, 0x15, 0xF0}; + uint8_t examplestate[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x00, 0x15, 0xF0}; + + EXPECT_TRUE(IRSamsungAc::validChecksum(examplestate)); + EXPECT_EQ(0, IRSamsungAc::calcChecksum(examplestate)); + + examplestate[8] = 0x12; // Set an incoorect checksum. + EXPECT_FALSE(IRSamsungAc::validChecksum(examplestate)); + EXPECT_EQ(0, IRSamsungAc::calcChecksum(examplestate)); + samsung.setRaw(examplestate); + // Extracting the state from the object should have a correct checksum. + EXPECT_TRUE(IRSamsungAc::validChecksum(samsung.getRaw())); + EXPECT_STATE_EQ(originalstate, samsung.getRaw(), kSamsungAcBits); + examplestate[8] = 0x02; // Restore old checksum value. + + // Change the state to force a different checksum. + examplestate[11] = 0x01; + EXPECT_FALSE(IRSamsungAc::validChecksum(examplestate)); + EXPECT_EQ(0xF, IRSamsungAc::calcChecksum(examplestate)); +} + +TEST(TestIRSamsungAcClass, HumanReadable) { + IRSamsungAc samsung(0); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (LOW), Swing: On, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); + samsung.setTemp(kSamsungAcMaxTemp); + samsung.setMode(kSamsungAcHeat); + samsung.off(); + samsung.setFan(kSamsungAcFanHigh); + samsung.setSwing(false); + samsung.setBeep(true); + samsung.setClean(true); + EXPECT_EQ( + "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 5 (HIGH), Swing: Off, " + "Beep: On, Clean: On, Quiet: Off", + samsung.toString()); + samsung.setQuiet(true); + EXPECT_EQ( + "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 0 (AUTO), Swing: Off, " + "Beep: On, Clean: On, Quiet: On", + samsung.toString()); +} + +TEST(TestIRSamsungAcClass, GeneralConstruction) { + IRSamsungAc samsung(0); + + uint8_t OnCoolFAutoBOffCOffQOffT20Soff[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; + + samsung.setPower(true); + samsung.setMode(kSamsungAcCool); + samsung.setFan(kSamsungAcFanAuto); + samsung.setSwing(false); + samsung.setBeep(false); + samsung.setClean(false); + samsung.setQuiet(false); + samsung.setTemp(20); + EXPECT_STATE_EQ(OnCoolFAutoBOffCOffQOffT20Soff, samsung.getRaw(), + kSamsungAcBits); + /* Disabled until we understand why LSB bit of the swing byte changes. + // TODO(Hollako): Explain why sometimes the LSB of state[9] is a 1. + // e.g. 0xAE or 0XAF for swing move. + uint8_t OnHeatFAutoBOffCOffQOffT17Son[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x10, 0x41, 0xF0}; + samsung.setPower(true); + samsung.setMode(kSamsungAcHeat); + samsung.setFan(kSamsungAcFanAuto); + samsung.setSwing(true); + samsung.setBeep(false); + samsung.setClean(false); + samsung.setQuiet(false); + samsung.setTemp(17); + EXPECT_STATE_EQ(OnHeatFAutoBOffCOffQOffT17Son, samsung.getRaw(), + kSamsungAcBits); + */ +} +// Tests for decodeSamsungAC(). + +// Decode normal SamsungAC messages. +TEST(TestDecodeSamsungAC, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + irsend.reset(); + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x00, 0x15, 0xF0}; + // Synthesised Normal Samsung A/C message. + irsend.sendSamsungAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a real Samsung A/C example from Issue #505 +TEST(TestDecodeSamsungAC, DecodeRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Samsung A/C example from Issue #505 + uint16_t rawData[233] = { + 690, 17844, 3084, 8864, 606, 406, 586, 1410, 580, 436, 570, 424, + 570, 426, 570, 404, 596, 418, 580, 416, 584, 410, 586, 1402, + 588, 408, 586, 410, 584, 1380, 610, 408, 586, 408, 586, 1404, + 586, 1404, 586, 1408, 594, 1396, 596, 1394, 602, 418, 582, 410, + 586, 408, 584, 408, 586, 408, 586, 410, 586, 408, 586, 410, + 586, 408, 586, 408, 586, 408, 586, 408, 586, 410, 584, 436, + 558, 436, 570, 424, 570, 424, 574, 420, 578, 416, 582, 412, + 586, 410, 586, 408, 584, 410, 586, 408, 586, 410, 584, 410, + 584, 408, 586, 408, 586, 410, 586, 408, 586, 412, 584, 436, + 556, 1410, 592, 1396, 602, 1390, 608, 1384, 608, 2886, 3086, 8858, + 610, 1380, 610, 410, 586, 408, 586, 410, 586, 408, 586, 410, + 586, 408, 586, 436, 558, 436, 554, 1410, 594, 426, 572, 422, + 578, 418, 582, 412, 586, 410, 584, 410, 586, 1380, 610, 1382, + 608, 1404, 586, 1404, 586, 408, 586, 1432, 558, 436, 554, 1414, + 590, 1398, 602, 418, 580, 414, 586, 410, 584, 1382, 606, 1382, + 608, 1382, 608, 408, 586, 408, 586, 408, 586, 408, 586, 410, + 584, 436, 560, 434, 570, 426, 566, 430, 568, 1400, 600, 416, + 584, 1406, 586, 410, 584, 1384, 606, 410, 586, 410, 584, 408, + 586, 408, 586, 408, 586, 408, 588, 410, 584, 1408, 590, 1400, + 592, 1398, 602, 1388, 612}; + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x00, 0x15, 0xF0}; + + irsend.sendRaw(rawData, 233, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (LOW), Swing: On, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +// Decode a real Samsung A/C example from Issue #505 +TEST(TestDecodeSamsungAC, DecodeRealExample2) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Samsung A/C example from Issue #505 + uint16_t rawData[233] = { + 668, 17834, 3092, 8862, 608, 410, 586, 1378, 612, 410, 584, 410, + 586, 410, 584, 410, 586, 408, 586, 408, 586, 410, 586, 1404, + 588, 436, 558, 436, 570, 1398, 592, 424, 576, 420, 578, 1388, + 608, 1382, 610, 1382, 608, 1380, 610, 1384, 606, 408, 586, 408, + 588, 408, 588, 408, 586, 436, 558, 436, 570, 424, 570, 426, + 572, 422, 578, 418, 582, 412, 586, 408, 586, 410, 584, 410, + 584, 410, 584, 410, 586, 410, 586, 408, 586, 408, 586, 408, + 586, 408, 586, 408, 586, 438, 558, 436, 568, 426, 570, 424, + 574, 422, 576, 418, 582, 414, 584, 410, 586, 410, 584, 410, + 586, 1380, 610, 1382, 608, 1404, 586, 1404, 602, 2872, 3096, 8878, + 582, 1432, 570, 426, 568, 426, 574, 420, 578, 416, 582, 412, + 586, 410, 584, 410, 586, 410, 586, 1382, 608, 410, 586, 410, + 586, 408, 586, 1404, 586, 1408, 582, 1410, 590, 428, 568, 1400, + 598, 1394, 606, 1382, 610, 1382, 608, 1378, 612, 1382, 608, 1384, + 606, 1404, 586, 408, 586, 414, 582, 436, 558, 1410, 590, 1422, + 576, 1390, 608, 410, 586, 410, 586, 410, 584, 410, 584, 410, + 586, 410, 586, 410, 584, 410, 586, 1404, 586, 1404, 588, 436, + 560, 436, 486, 510, 566, 1400, 598, 420, 576, 418, 582, 414, + 586, 410, 584, 410, 584, 410, 586, 410, 584, 1382, 608, 1384, + 606, 1384, 606, 1408, 600}; + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0xE2, 0xFE, + 0x71, 0x80, 0x11, 0xF0}; + + irsend.sendRaw(rawData, 233, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +// Decode a real Samsung A/C example from: +// https://github.com/markszabo/IRremoteESP8266/issues/505#issuecomment-424036602 +TEST(TestDecodeSamsungAC, DecodePowerOnSample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[349] = { + 662, 17870, 3026, 8966, 540, 484, 514, 1482, 518, 482, 514, 482, + 518, 482, 516, 510, 490, 508, 490, 508, 572, 428, 576, 1398, + 542, 482, 514, 484, 514, 1460, 540, 482, 518, 482, 516, 1456, + 544, 1480, 518, 1480, 518, 1480, 518, 1484, 514, 510, 566, 432, + 576, 424, 574, 426, 540, 458, 516, 482, 516, 482, 516, 482, + 518, 480, 518, 482, 518, 482, 518, 482, 516, 482, 518, 482, + 516, 482, 518, 480, 516, 508, 492, 508, 490, 508, 572, 428, + 576, 422, 572, 428, 542, 456, 514, 484, 518, 480, 518, 480, + 518, 480, 516, 482, 516, 482, 520, 478, 518, 482, 518, 480, + 518, 1480, 518, 1480, 516, 1484, 594, 1428, 518, 2964, 3032, 8964, + 540, 1458, 542, 480, 518, 480, 520, 480, 518, 482, 520, 480, + 520, 478, 518, 480, 520, 478, 520, 1478, 522, 478, 518, 506, + 494, 1484, 594, 426, 574, 1400, 564, 1434, 540, 1454, 544, 1478, + 520, 1454, 544, 1458, 540, 480, 520, 480, 518, 480, 520, 480, + 518, 508, 490, 506, 568, 432, 572, 426, 576, 424, 544, 454, + 518, 480, 516, 482, 520, 478, 520, 478, 522, 478, 518, 480, + 520, 478, 520, 478, 520, 478, 520, 478, 520, 478, 518, 478, + 522, 506, 494, 504, 566, 432, 576, 424, 576, 424, 570, 428, + 518, 482, 518, 480, 518, 482, 520, 478, 520, 478, 520, 480, + 520, 478, 520, 478, 520, 2964, 3032, 8986, 520, 1478, 520, 506, + 492, 506, 492, 506, 568, 430, 574, 424, 546, 454, 516, 482, + 518, 482, 518, 1456, 544, 478, 546, 452, 520, 478, 544, 1432, + 542, 1478, 520, 1478, 520, 478, 520, 1482, 586, 1412, 598, 1400, + 564, 1432, 540, 1458, 544, 1454, 544, 1454, 544, 1456, 542, 480, + 518, 480, 520, 480, 520, 1462, 536, 1482, 588, 1410, 598, 424, + 572, 426, 542, 456, 518, 482, 520, 478, 520, 478, 522, 478, + 520, 478, 520, 1456, 542, 1458, 540, 478, 520, 478, 520, 478, + 520, 1482, 540, 482, 568, 430, 576, 424, 570, 428, 542, 458, + 518, 480, 520, 480, 520, 1454, 568, 1430, 566, 1432, 566, 1454, + 594}; + uint8_t expectedState[kSamsungAcExtendedStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; + + irsend.sendRaw(rawData, 349, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcExtendedBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +// Decode a real Samsung A/C example from: +// https://github.com/markszabo/IRremoteESP8266/issues/505#issuecomment-424036602 +TEST(TestDecodeSamsungAC, DecodePowerOffSample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[349] = { + 670, 17802, 3096, 8898, 602, 420, 580, 1418, 582, 418, 582, 416, + 582, 416, 584, 442, 550, 448, 568, 430, 570, 430, 576, 1396, + 600, 424, 546, 452, 578, 1394, 604, 1396, 600, 420, 580, 1398, + 602, 1416, 586, 1412, 582, 1420, 576, 1422, 592, 428, 574, 424, + 576, 422, 578, 420, 548, 452, 578, 420, 578, 420, 584, 416, + 580, 418, 580, 418, 582, 418, 580, 418, 582, 414, 584, 414, + 584, 416, 582, 418, 584, 442, 558, 442, 568, 430, 576, 424, + 578, 420, 576, 424, 576, 422, 580, 420, 584, 414, 584, 416, + 584, 414, 582, 418, 580, 418, 582, 416, 582, 416, 584, 414, + 584, 414, 586, 442, 554, 1420, 570, 1452, 578, 2884, 3120, 8898, + 596, 1400, 602, 422, 582, 418, 584, 414, 582, 416, 584, 414, + 584, 416, 582, 416, 584, 416, 584, 1410, 586, 414, 582, 444, + 556, 1420, 590, 432, 572, 1402, 602, 1396, 600, 1398, 606, 1414, + 582, 1394, 604, 1394, 604, 414, 584, 414, 586, 412, 586, 410, + 586, 442, 556, 440, 544, 456, 568, 430, 576, 424, 578, 420, + 578, 420, 576, 424, 584, 412, 586, 412, 586, 412, 584, 414, + 586, 412, 584, 414, 586, 412, 586, 412, 586, 414, 586, 412, + 584, 442, 558, 442, 558, 440, 566, 432, 574, 424, 578, 422, + 576, 422, 578, 420, 586, 414, 586, 414, 586, 412, 584, 414, + 586, 414, 586, 414, 586, 2902, 3096, 8900, 600, 1416, 586, 442, + 556, 442, 558, 440, 564, 434, 572, 428, 578, 420, 580, 420, + 578, 420, 584, 1392, 608, 414, 586, 414, 582, 414, 586, 412, + 586, 412, 586, 414, 584, 1394, 606, 1416, 580, 1418, 568, 1432, + 594, 1402, 602, 1398, 606, 1392, 606, 1390, 608, 1390, 608, 414, + 584, 414, 586, 414, 584, 1412, 586, 1398, 600, 1418, 590, 430, + 566, 432, 576, 422, 578, 420, 578, 422, 582, 416, 586, 414, + 586, 412, 584, 1390, 606, 1392, 608, 414, 586, 412, 584, 412, + 588, 1410, 586, 442, 558, 440, 568, 430, 566, 434, 574, 426, + 578, 420, 578, 420, 582, 416, 586, 412, 586, 1390, 608, 1390, + 608}; + + uint8_t expectedState[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; + + irsend.sendRaw(rawData, 349, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcExtendedBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +TEST(TestDecodeSamsungAC, DecodeHeatSample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[233] = { + 650, 16260, 3014, 8934, 534, 486, 508, 1478, 514, 484, 510, 486, + 508, 512, 484, 510, 562, 432, 572, 422, 540, 454, 514, 1452, + 534, 486, 510, 484, 510, 1456, 536, 484, 510, 484, 510, 1454, + 536, 1478, 512, 1476, 514, 1482, 508, 1482, 592, 428, 570, 424, + 538, 456, 508, 486, 510, 484, 512, 484, 510, 486, 510, 484, + 510, 484, 510, 486, 510, 484, 510, 484, 510, 484, 510, 484, + 510, 484, 510, 486, 508, 510, 484, 510, 568, 428, 570, 424, + 538, 458, 512, 482, 510, 486, 510, 484, 510, 484, 510, 484, + 510, 484, 510, 484, 510, 484, 510, 484, 510, 484, 510, 484, + 510, 1474, 516, 1502, 534, 1432, 594, 1398, 536, 2954, 3018, 8932, + 536, 1458, 532, 484, 510, 484, 512, 484, 510, 484, 510, 484, + 510, 484, 512, 484, 510, 484, 510, 1480, 508, 510, 530, 464, + 568, 426, 568, 426, 514, 480, 508, 486, 508, 1456, 534, 1478, + 514, 1452, 538, 1478, 512, 484, 510, 1456, 534, 486, 510, 1478, + 512, 1480, 570, 450, 570, 424, 540, 454, 512, 1452, 534, 1458, + 534, 1454, 536, 484, 512, 482, 512, 484, 512, 484, 512, 482, + 512, 1474, 514, 484, 512, 510, 486, 508, 534, 1430, 594, 426, + 512, 482, 512, 482, 510, 484, 512, 482, 512, 1452, 538, 482, + 512, 482, 512, 482, 510, 484, 510, 484, 510, 1478, 512, 1504, + 488, 1480, 560, 1454, 514}; + + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x10, 0x41, 0xF0}; + + irsend.sendRaw(rawData, 233, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 17C, Fan: 0 (AUTO), Swing: On, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +TEST(TestDecodeSamsungAC, DecodeCoolSample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[233] = { + 690, 17854, 3086, 8862, 610, 410, 584, 1382, 610, 410, 586, 408, + 586, 408, 586, 408, 588, 410, 584, 436, 558, 436, 570, 1396, + 598, 422, 576, 418, 580, 1384, 612, 410, 586, 410, 584, 1380, + 612, 1382, 608, 1384, 606, 1404, 586, 1404, 586, 436, 558, 438, + 566, 428, 568, 426, 570, 424, 576, 418, 578, 416, 584, 410, + 586, 408, 584, 410, 586, 408, 586, 408, 586, 410, 586, 408, + 586, 408, 588, 408, 586, 408, 588, 408, 586, 438, 558, 436, + 568, 426, 568, 428, 568, 426, 576, 418, 578, 416, 584, 412, + 584, 410, 586, 408, 586, 410, 586, 410, 584, 410, 586, 408, + 586, 1384, 606, 1402, 588, 1410, 580, 1410, 608, 2864, 3108, 8864, + 594, 1394, 604, 416, 584, 410, 586, 410, 586, 410, 586, 410, + 584, 410, 586, 410, 586, 408, 586, 1404, 588, 408, 586, 408, + 586, 436, 560, 1408, 592, 1400, 596, 1396, 600, 416, 584, 1382, + 608, 1380, 610, 1404, 586, 1384, 608, 1384, 606, 1402, 588, 1408, + 582, 1410, 564, 452, 568, 428, 572, 424, 576, 1414, 582, 1386, + 608, 1382, 608, 410, 584, 410, 584, 410, 586, 408, 586, 408, + 586, 408, 586, 408, 588, 1408, 582, 436, 540, 1426, 590, 428, + 574, 420, 578, 418, 580, 1384, 610, 410, 584, 410, 584, 410, + 584, 412, 584, 408, 586, 410, 586, 408, 586, 1404, 586, 1408, + 582, 1410, 562, 1426, 610}; + + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0xE2, 0xFE, + 0x71, 0x40, 0x11, 0xF0}; + + irsend.sendRaw(rawData, 233, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sanyo_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sanyo_test.cpp similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Sanyo_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Sanyo_test.cpp index 9442f3db5..14c1c7da0 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sanyo_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sanyo_test.cpp @@ -4,7 +4,6 @@ #include "IRsend_test.h" #include "gtest/gtest.h" - // Tests for encodeSanyoLC7461(). TEST(TestEncodeSanyoLC7461, NormalEncoding) { @@ -34,7 +33,8 @@ TEST(TestEncodeSanyoLC7461, SendDataOnly) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520", + irsend.outputStr()); } // Test sending with different repeats. @@ -43,7 +43,7 @@ TEST(TestEncodeSanyoLC7461, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendSanyoLC7461(0x1D8113F00FF, SANYO_LC7461_BITS, 1); // 1 repeat. + irsend.sendSanyoLC7461(0x1D8113F00FF, kSanyoLC7461Bits, 1); // 1 repeat. EXPECT_EQ( "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" @@ -51,8 +51,9 @@ TEST(TestEncodeSanyoLC7461, SendWithRepeats) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520" + "m8960s2240m560s96320", + irsend.outputStr()); } // Tests for decodeSanyoLC7461(). @@ -67,10 +68,10 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSanyoLC7461(0x1D8113F00FF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); EXPECT_EQ(0xEC0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -80,10 +81,10 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSanyoLC7461(irsend.encodeSanyoLC7461(0x1234, 0x56)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x2468DCB56A9, irsend.capture.value); EXPECT_EQ(0x1234, irsend.capture.address); EXPECT_EQ(0x56, irsend.capture.command); @@ -93,10 +94,10 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSanyoLC7461(irsend.encodeSanyoLC7461(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x3FFE01FE, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x1, irsend.capture.command); @@ -111,12 +112,12 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithRepeatAndStrict) { // Normal Sanyo LC7461 16-bit message with 1 repeat. irsend.reset(); - irsend.sendSanyoLC7461(0x3FFE01FE, SANYO_LC7461_BITS, 1); + irsend.sendSanyoLC7461(0x3FFE01FE, kSanyoLC7461Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x3FFE01FE, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x1, irsend.capture.command); @@ -133,13 +134,13 @@ TEST(TestDecodeSanyoLC7461, DecodeWithNonStrictValues) { irsend.sendSanyoLC7461(0x0); // Illegal value Sanyo LC7461 message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_FALSE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - false)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, false)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -148,22 +149,20 @@ TEST(TestDecodeSanyoLC7461, DecodeWithNonStrictValues) { // Illegal value Sanyo LC7461 42-bit message. irsend.sendSanyoLC7461(0x1234567890A); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_FALSE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 32, - true)); - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 64, - true)); + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 64, true)); // And should fail for a bad value. - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_FALSE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - false)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, false)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x1234567890A, irsend.capture.value); EXPECT_EQ(0x91A, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -193,33 +192,33 @@ TEST(TestDecodeSanyoLC7461, Decode64BitMessages) { // Decode a 'real' example via GlobalCache TEST(TestDecodeSanyoLC7461, DecodeGlobalCacheExample) { -IRsendTest irsend(4); -IRrecv irrecv(4); -irsend.begin(); + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); -irsend.reset(); -uint16_t gc_test[95] = {38000, 1, 89, 342, 171, 21, 21, 21, 64, 21, 64, - 21, 64, 21, 21, 21, 64, 21, 64, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, - 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, - 21, 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 64, 21, 64, 21, 64, 21, 64, 21, 64, - 21, 64, 21, 64, 21, 64, 21, 875, 342, 171, 21, 3565}; -irsend.sendGC(gc_test, 95); -irsend.makeDecodeResult(); + irsend.reset(); + uint16_t gc_test[95] = { + 38000, 1, 89, 342, 171, 21, 21, 21, 64, 21, 64, 21, 64, 21, 21, 21, + 64, 21, 64, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, 21, + 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 64, 21, 64, 21, + 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 875, 342, 171, 21, 3565}; + irsend.sendGC(gc_test, 95); + irsend.makeDecodeResult(); -ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, true)); -EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); -EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); -EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); -EXPECT_EQ(0xEC0, irsend.capture.address); -EXPECT_EQ(0x0, irsend.capture.command); -EXPECT_FALSE(irsend.capture.repeat); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); + EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); + EXPECT_EQ(0xEC0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); -// Confirm what the 42-bit NEC decode is. -ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, 42, false)); -EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); + // Confirm what the 42-bit NEC decode is. + ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, 42, false)); + EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); } // Fail to decode a non-Sanyo LC7461 example via GlobalCache @@ -230,13 +229,14 @@ TEST(TestDecodeSanyoLC7461, FailToDecodeNonSanyoLC7461Example) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, false)); } diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sharp_test.cpp similarity index 79% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Sharp_test.cpp index 0329b4e27..8481a4649 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sharp_test.cpp @@ -37,7 +37,6 @@ TEST(TestEncodeSharp, AdvancedEncoding) { EXPECT_EQ(0x454A, irsend.encodeSharp(0x11, 0x52, 1, 0, true)); } - // Tests for sendSharp(). // Test sending typical data only. @@ -53,7 +52,8 @@ TEST(TestSendSharp, SendDataOnly) { "m260s43602" "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Test sending with different repeats. @@ -62,7 +62,7 @@ TEST(TestSendSharp, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendSharp(0x11, 0x52, SHARP_BITS, 1); // 1 repeat. + irsend.sendSharp(0x11, 0x52, kSharpBits, 1); // 1 repeat. EXPECT_EQ( "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" @@ -75,7 +75,8 @@ TEST(TestSendSharp, SendWithRepeats) { "m260s43602" "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Test sending an atypical data size. @@ -89,7 +90,8 @@ TEST(TestSendSharp, SendUnusualSize) { "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" "m260s43602" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.reset(); irsend.sendSharp(0x0, 0x0, 16); @@ -99,7 +101,8 @@ TEST(TestSendSharp, SendUnusualSize) { "m260s43602" "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Tests for sendSharpRaw(). @@ -117,7 +120,8 @@ TEST(TestSendSharpRaw, SendDataOnly) { "m260s43602" "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Test sending with different repeats. @@ -126,7 +130,7 @@ TEST(TestSendSharpRaw, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendSharpRaw(0x454A, SHARP_BITS, 1); // 1 repeat. + irsend.sendSharpRaw(0x454A, kSharpBits, 1); // 1 repeat. EXPECT_EQ( "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" @@ -139,7 +143,8 @@ TEST(TestSendSharpRaw, SendWithRepeats) { "m260s43602" "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Test sending an atypical data size. @@ -153,7 +158,8 @@ TEST(TestSendSharpRaw, SendUnusualSize) { "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" "m260s43602" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.reset(); irsend.sendSharpRaw(0x2, 16); @@ -163,7 +169,8 @@ TEST(TestSendSharpRaw, SendUnusualSize) { "m260s43602" "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Tests for decodeSharp(). @@ -178,9 +185,9 @@ TEST(TestDecodeSharp, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSharpRaw(0x454A); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x454A, irsend.capture.value); EXPECT_EQ(0x11, irsend.capture.address); EXPECT_EQ(0x4A, irsend.capture.command); @@ -190,9 +197,9 @@ TEST(TestDecodeSharp, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSharpRaw(irsend.encodeSharp(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x7266, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -202,9 +209,9 @@ TEST(TestDecodeSharp, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSharpRaw(irsend.encodeSharp(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x4202, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x1, irsend.capture.command); @@ -219,19 +226,19 @@ TEST(TestDecodeSharp, NormalDecodeWithRepeatAndStrict) { // Normal Sharp 15-bit message with 1 repeat. irsend.reset(); - irsend.sendSharpRaw(0x7266, SHARP_BITS, 1); + irsend.sendSharpRaw(0x7266, kSharpBits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x7266, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); - irsend.makeDecodeResult(2 * (2 * SHARP_BITS + FOOTER)); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + irsend.makeDecodeResult(2 * (2 * kSharpBits + kFooter)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x7266, irsend.capture.value); } @@ -245,7 +252,7 @@ TEST(TestDecodeSharp, DecodeWithNonStrict) { irsend.sendSharpRaw(0x0, 8); // Illegal length Sharp 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, 8, false)); EXPECT_EQ(SHARP, irsend.capture.decode_type); @@ -258,7 +265,7 @@ TEST(TestDecodeSharp, DecodeWithNonStrict) { irsend.sendSharpRaw(0x12345678, 32); // Illegal length Sharp 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); // Should fail with strict when we ask for the wrong bit size. ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, 32, true)); @@ -298,21 +305,17 @@ TEST(TestDecodeSharp, DecodeGlobalCacheExample) { irsend.reset(); // Sharp Power On from Global Cache. - uint16_t gc_test[67] = {38000, 1, 1, - 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, - 10, 70, 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, - 10, 30, 10, 70, 10, 30, - 10, 1657, - 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, - 10, 30, 10, 70, 10, 30, 10, 70, 10, 70, 10, 30, - 10, 70, 10, 30, 10, 70, - 10, 1657}; + uint16_t gc_test[67] = { + 38000, 1, 1, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, 10, 70, + 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, 10, 30, 10, 70, 10, 30, 10, + 1657, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, 10, 30, 10, 70, + 10, 30, 10, 70, 10, 70, 10, 30, 10, 70, 10, 30, 10, 70, 10, 1657}; irsend.sendGC(gc_test, 67); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x454A, irsend.capture.value); EXPECT_EQ(0x11, irsend.capture.address); EXPECT_EQ(0x4A, irsend.capture.command); @@ -327,31 +330,25 @@ TEST(TestDecodeSharp, FailToDecodeNonSharpExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[67] = {38000, 1, 1, - 10, 70, 30, 30, 10, 30, 10, 30, 10, 70, 10, 30, - 10, 70, 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, - 10, 30, 10, 70, 10, 30, - 10, 1657, - 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, - 10, 30, 10, 60, 10, 30, 10, 70, 10, 70, 10, 30, - 10, 10, 70, 30, 10, 70, - 10, 1657}; + uint16_t gc_test[67] = { + 38000, 1, 1, 10, 70, 30, 30, 10, 30, 10, 30, 10, 70, 10, 30, 10, 70, + 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, 10, 30, 10, 70, 10, 30, 10, + 1657, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, 10, 30, 10, 60, + 10, 30, 10, 70, 10, 70, 10, 30, 10, 10, 70, 30, 10, 70, 10, 1657}; irsend.sendGC(gc_test, 67); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, false)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, false)); // Test only half of a good message, as it is sent (sort of) twice. - uint16_t gc_half[35] = {38000, 1, 1, - 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, - 10, 70, 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, - 10, 30, 10, 70, 10, 30, - 10, 1657}; + uint16_t gc_half[35] = {38000, 1, 1, 10, 70, 10, 30, 10, 30, 10, 30, 10, + 70, 10, 30, 10, 70, 10, 30, 10, 70, 10, 30, 10, + 30, 10, 70, 10, 30, 10, 70, 10, 30, 10, 1657}; irsend.sendGC(gc_half, 35); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, false)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, false)); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp new file mode 100644 index 000000000..22d9ead38 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp @@ -0,0 +1,78 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendSherwood(). + +// Test sending typical data only. +TEST(TestSendSherwood, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSherwood(0xC1A28877); + EXPECT_EQ( + "m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s1680m560s1680m560s42560" + "m8960s2240m560s96320", + irsend.outputStr()); +} + +// Test sending typical data with extra repeats. +TEST(TestSendSherwood, SendDataWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSherwood(0xC1A28877, 32, 2); + EXPECT_EQ( + "m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s1680m560s1680m560s42560" + "m8960s2240m560s96320" + "m8960s2240m560s96320", + irsend.outputStr()); +} + +// Test sending typical data with explicit no repeats. +TEST(TestSendSherwood, SendDataWithZeroRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSherwood(0xC1A28877, 32, 0); + // Should have a single NEC repeat, as we always send one. + EXPECT_EQ( + "m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s1680m560s1680m560s42560" + "m8960s2240m560s96320", + irsend.outputStr()); +} + +// Test that a typical Sherwood send decodes as the appropriate NEC value. +TEST(TestSendSherwood, DecodesAsNEC) { + IRsendTest irsend(4); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendSherwood(0xC1A28877); + irsend.makeDecodeResult(); + + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0xC1A28877, irsend.capture.value); + EXPECT_EQ(0x4583, irsend.capture.address); + EXPECT_EQ(0x11, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp new file mode 100644 index 000000000..c79ff6175 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp @@ -0,0 +1,357 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendSony(). + +// Test sending typical data only. +TEST(TestSendSony, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSony(0); + // We expect three 20-bit commands to be sent. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendSony(0x240C, kSony20Bits); + // We expect three 20-bit commands to be sent. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200", + irsend.outputStr()); + + irsend.reset(); + irsend.sendSony(0x240C, kSony15Bits); + // We expect three 15-bit commands to be sent. + EXPECT_EQ( + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200" + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200" + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200", + irsend.outputStr()); + + irsend.reset(); + irsend.sendSony(0xA90, kSony12Bits); + // We expect three 15-bit commands to be sent. + EXPECT_EQ( + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800" + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800" + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800", + irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendSony, SendWithDiffRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSony(0x240C, kSony20Bits, 0); // Send a command with 0 repeats. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200", + irsend.outputStr()); + irsend.sendSony(0x240C, kSony20Bits, 1); // Send a command with 1 repeat. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200", + irsend.outputStr()); + irsend.sendSony(0x240C, kSony20Bits, 3); // Send a command with 3 repeats. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200", + irsend.outputStr()); +} + +// Tests for encodeSony(). + +TEST(TestEncodeSony, NormalSonyEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0x0, irsend.encodeSony(kSony12Bits, 0, 0)); + EXPECT_EQ(0xA90, irsend.encodeSony(kSony12Bits, 21, 1)); + EXPECT_EQ(0xFFF, irsend.encodeSony(kSony12Bits, 0x7F, 0x1F)); + + EXPECT_EQ(0x0, irsend.encodeSony(kSony15Bits, 0, 0)); + EXPECT_EQ(0x5480, irsend.encodeSony(kSony15Bits, 21, 1)); + EXPECT_EQ(0x5455, irsend.encodeSony(kSony15Bits, 21, 0xAA)); + EXPECT_EQ(0x7FFF, irsend.encodeSony(kSony15Bits, 0x7F, 0xFF)); + + EXPECT_EQ(0x0, irsend.encodeSony(kSony20Bits, 0, 0, 0)); + EXPECT_EQ(0x81080, irsend.encodeSony(kSony20Bits, 1, 1, 1)); + EXPECT_EQ(0xFFFFF, irsend.encodeSony(kSony20Bits, 0x7F, 0x1F, 0xFF)); +} + +TEST(TestEncodeSony, SonyEncodingWithOversizedValues) { + IRsendTest irsend(4); + EXPECT_EQ(0xFFF, irsend.encodeSony(kSony12Bits, 0xFFFF, 0xFFFF)); + + EXPECT_EQ(0x7FFF, irsend.encodeSony(kSony15Bits, 0xFFFF, 0xFFFF)); + + EXPECT_EQ(0xFFFFF, irsend.encodeSony(kSony20Bits, 0xFFFF, 0xFFFF, 0xFFFF)); +} + +// Tests for decodeSony(). + +// Decode normal Sony messages. +TEST(TestDecodeSony, NormalSonyDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Synthesised Normal Sony 20-bit message. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); + EXPECT_EQ(0x81080, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x81, irsend.capture.command); + + // Synthesised Normal Sony 15-bit message. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony15Bits, irsend.capture.bits); + EXPECT_EQ(0x5480, irsend.capture.value); + EXPECT_EQ(1, irsend.capture.address); + EXPECT_EQ(21, irsend.capture.command); + + // Synthesised Normal Sony 12-bit message. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); + EXPECT_EQ(0xA90, irsend.capture.value); + EXPECT_EQ(1, irsend.capture.address); + EXPECT_EQ(21, irsend.capture.command); +} + +// Decode unexpected Sony messages. i.e longer than minimum etc. +TEST(TestDecodeSony, SonyDecodeWithUnexpectedLegalSize) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Synthesised Normal Sony 20-bit message decoded when looking for 12-bits + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSonyMinBits)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); + EXPECT_EQ(0x81080, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x81, irsend.capture.command); + + // Synthesised Normal Sony 12-bit message when expecting 20-bits. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony20Bits)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); + EXPECT_EQ(0xA90, irsend.capture.value); + EXPECT_EQ(1, irsend.capture.address); + EXPECT_EQ(21, irsend.capture.command); + + // 12-bit message should be regected when using strict and a different size. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + + // 15-bit message should be regected when using strict and a different size. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + + // 20-bit message should be regected when using strict and a different size. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony20Bits, 1, 1, 1), kSony20Bits); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); +} + +// Decode unsupported Sony messages. i.e non-standard sizes. +TEST(TestDecodeSony, SonyDecodeWithIllegalSize) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSony(0xFF, 8); // Illegal 8-bit Sony-like message. + irsend.makeDecodeResult(); + // Should fail with strict on. + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0xFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendSony(0x1FFF, 13); // Illegal 13-bit Sony-like message. + irsend.makeDecodeResult(); + // Should fail with strict on. + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(13, irsend.capture.bits); + EXPECT_EQ(0x1FFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendSony(0x1FFFF, 17); // Illegal 17-bit Sony-like message. + irsend.makeDecodeResult(); + // Should fail with strict on. + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(17, irsend.capture.bits); + EXPECT_EQ(0x1FFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendSony(0x1FFFFF, 21); // Illegal 21-bit Sony-like message. + irsend.makeDecodeResult(); + // Should fail with strict on. + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(21, irsend.capture.bits); + EXPECT_EQ(0x1FFFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + // Illegal 64-bit (max) Sony-like message. + irsend.sendSony(0xFFFFFFFFFFFFFFFF, 64, 0); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +// Decode unsupported Sony messages. i.e non-standard sizes. +TEST(TestDecodeSony, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Sony "Power On" from Global Cache. + uint16_t gc_test[29] = {40000, 1, 1, 96, 24, 24, 24, 48, 24, 48, + 24, 48, 24, 24, 24, 48, 24, 24, 24, 48, + 24, 24, 24, 24, 24, 24, 24, 24, 1013}; + irsend.sendGC(gc_test, 29); + irsend.makeDecodeResult(); + + // Without strict. + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(12, irsend.capture.bits); + EXPECT_EQ(0x750, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x2E, irsend.capture.command); + // With strict and correct size. + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); +} + +// Encoding & Decode 20 bit Sony messages. Issue #476 +TEST(TestEncodeSony, Issue476) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendSony(0x6AB47, 20); + irsend.makeDecodeResult(); + + // Without strict. + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(20, irsend.capture.bits); + EXPECT_EQ(0x6AB47, irsend.capture.value); // 20 bits + EXPECT_EQ(0x1A, irsend.capture.address); // 5 bits + EXPECT_EQ(0x7156, irsend.capture.command); // 15 bits + EXPECT_EQ(0x56, 0x7156 & 0x7F); // command (lower 7 bits) + EXPECT_EQ(0xE2, (0x7156 >> 7) & 0xFF); // extended (top 8 of 15 bits) + EXPECT_EQ(0x6AB47, irsend.encodeSony(20, 0x56, 0x1A, 0xE2)); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp new file mode 100644 index 000000000..b5e1e07a9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp @@ -0,0 +1,664 @@ +// Copyright 2017 David Conran +#include "ir_Toshiba.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for Toshiba A/C methods. + +// Test sending typical data only. +TEST(TestSendToshibaAC, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t toshiba_code[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x00}; + irsend.reset(); + irsend.sendToshibaAC(toshiba_code); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendToshibaAC, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t toshiba_code[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x00}; + + irsend.sendToshibaAC(toshiba_code, kToshibaACStateLength, 0); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba_code, kToshibaACStateLength, 2); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendToshibaAC, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t toshiba_short_code[8] = {0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08}; + uint8_t toshiba_long_code[10] = {0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A}; + irsend.reset(); + irsend.sendToshibaAC(toshiba_short_code, kToshibaACStateLength - 1); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba_long_code, kToshibaACStateLength + 1); + ASSERT_EQ( + "m4400s4300" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s1623m543s472" + "m543s7048" + "m4400s4300" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s1623m543s472" + "m543s7048", + irsend.outputStr()); +} + +// Tests for IRToshibaAC class. + +TEST(TestToshibaACClass, Power) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + toshiba.on(); + EXPECT_TRUE(toshiba.getPower()); + + toshiba.off(); + EXPECT_FALSE(toshiba.getPower()); + + toshiba.setPower(true); + EXPECT_TRUE(toshiba.getPower()); + + toshiba.setPower(false); + EXPECT_FALSE(toshiba.getPower()); +} + +TEST(TestToshibaACClass, Temperature) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + toshiba.setTemp(0); + EXPECT_EQ(kToshibaAcMinTemp, toshiba.getTemp()); + + toshiba.setTemp(255); + EXPECT_EQ(kToshibaAcMaxTemp, toshiba.getTemp()); + + toshiba.setTemp(kToshibaAcMinTemp); + EXPECT_EQ(kToshibaAcMinTemp, toshiba.getTemp()); + + toshiba.setTemp(kToshibaAcMaxTemp); + EXPECT_EQ(kToshibaAcMaxTemp, toshiba.getTemp()); + + toshiba.setTemp(kToshibaAcMinTemp - 1); + EXPECT_EQ(kToshibaAcMinTemp, toshiba.getTemp()); + + toshiba.setTemp(kToshibaAcMaxTemp + 1); + EXPECT_EQ(kToshibaAcMaxTemp, toshiba.getTemp()); + + toshiba.setTemp(17); + EXPECT_EQ(17, toshiba.getTemp()); + + toshiba.setTemp(21); + EXPECT_EQ(21, toshiba.getTemp()); + + toshiba.setTemp(25); + EXPECT_EQ(25, toshiba.getTemp()); + + toshiba.setTemp(30); + EXPECT_EQ(30, toshiba.getTemp()); +} + +TEST(TestToshibaACClass, OperatingMode) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + toshiba.setMode(kToshibaAcAuto); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + + toshiba.setMode(kToshibaAcCool); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + + toshiba.setMode(kToshibaAcHeat); + EXPECT_EQ(kToshibaAcHeat, toshiba.getMode()); + + toshiba.setMode(kToshibaAcDry); + EXPECT_EQ(kToshibaAcDry, toshiba.getMode()); + + toshiba.setMode(kToshibaAcHeat + 1); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + + toshiba.setMode(255); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + + // Setting the power off changes the underlying mode in the state to heat. + toshiba.setPower(true); + toshiba.setMode(kToshibaAcCool); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode(true)); + toshiba.setPower(false); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(kToshibaAcHeat, toshiba.getMode(true)); +} + +TEST(TestToshibaACClass, FanSpeed) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + toshiba.setFan(kToshibaAcFanAuto); + EXPECT_EQ(kToshibaAcFanAuto, toshiba.getFan()); + + toshiba.setFan(255); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); + + toshiba.setFan(kToshibaAcFanMax); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); + + toshiba.setFan(kToshibaAcFanMax - 1); + EXPECT_EQ(kToshibaAcFanMax - 1, toshiba.getFan()); + + toshiba.setFan(1); + EXPECT_EQ(1, toshiba.getFan()); + + toshiba.setFan(2); + EXPECT_EQ(2, toshiba.getFan()); + + toshiba.setFan(3); + EXPECT_EQ(3, toshiba.getFan()); + + toshiba.setFan(4); + EXPECT_EQ(4, toshiba.getFan()); + + toshiba.setFan(kToshibaAcFanMax + 1); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); +} + +TEST(TestToshibaACClass, RawState) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + uint8_t initial_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + uint8_t modified_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0xC1, 0x00, 0xC0}; + + // Verify the starting state. + EXPECT_STATE_EQ(initial_state, toshiba.getRaw(), kToshibaACBits); + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + EXPECT_EQ(kToshibaAcFanAuto, toshiba.getFan()); + + // Change some settings. + toshiba.setMode(kToshibaAcCool); + toshiba.setFan(kToshibaAcFanMax); + toshiba.setTemp(kToshibaAcMinTemp); + // Verify those were set. + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); + EXPECT_EQ(kToshibaAcMinTemp, toshiba.getTemp()); + // Retrieve the modified state. + EXPECT_STATE_EQ(modified_state, toshiba.getRaw(), kToshibaACBits); + + // Set it back to the initial state. + toshiba.setRaw(initial_state); + + // Check the new state was set correctly. + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + EXPECT_EQ(kToshibaAcFanAuto, toshiba.getFan()); + EXPECT_STATE_EQ(initial_state, toshiba.getRaw(), kToshibaACBits); +} + +TEST(TestToshibaACClass, Checksums) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + uint8_t initial_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + uint8_t modified_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0xC1, 0x00, 0xC0}; + uint8_t invalid_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x00}; + + EXPECT_EQ(0x01, toshiba.calcChecksum(initial_state)); + EXPECT_EQ(0xC0, toshiba.calcChecksum(modified_state)); + // Check we can call it without instantiating the object. + EXPECT_EQ(0x01, IRToshibaAC::calcChecksum(initial_state)); + // Use different lengths. + EXPECT_EQ(0x01, IRToshibaAC::calcChecksum(initial_state, + kToshibaACStateLength - 1)); + EXPECT_EQ(0xFF, IRToshibaAC::calcChecksum(initial_state, 3)); + // Minimum length that actually means anything. + EXPECT_EQ(0xF2, IRToshibaAC::calcChecksum(initial_state, 2)); + // Technically, there is no such thing as a checksum for a length of < 2 + // But test it anyway + EXPECT_EQ(0x00, IRToshibaAC::calcChecksum(initial_state, 1)); + EXPECT_EQ(0x00, IRToshibaAC::calcChecksum(initial_state, 0)); + + // Validity tests. + EXPECT_TRUE(IRToshibaAC::validChecksum(initial_state)); + EXPECT_TRUE(IRToshibaAC::validChecksum(modified_state)); + EXPECT_FALSE(IRToshibaAC::validChecksum(invalid_state)); + EXPECT_FALSE(IRToshibaAC::validChecksum(initial_state, 0)); + EXPECT_FALSE(IRToshibaAC::validChecksum(initial_state, 1)); + EXPECT_FALSE(IRToshibaAC::validChecksum(initial_state, 2)); +} + +TEST(TestToshibaACClass, HumanReadableOutput) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + uint8_t initial_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + uint8_t modified_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0xC1, 0x00, 0xC0}; + + toshiba.setRaw(initial_state); + EXPECT_EQ("Power: On, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (AUTO)", + toshiba.toString()); + toshiba.setRaw(modified_state); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 17C, Fan: 5 (MAX)", + toshiba.toString()); + toshiba.off(); + toshiba.setTemp(25); + toshiba.setFan(3); + toshiba.setMode(kToshibaAcDry); + EXPECT_EQ("Power: Off, Mode: 2 (DRY), Temp: 25C, Fan: 3", toshiba.toString()); +} + +TEST(TestToshibaACClass, MessageConstuction) { + IRToshibaAC toshiba(0); + IRsendTest irsend(4); + toshiba.begin(); + irsend.begin(); + + toshiba.setFan(1); + toshiba.setMode(kToshibaAcCool); + toshiba.setTemp(27); + toshiba.on(); + + // Check everything for kicks. + EXPECT_EQ(1, toshiba.getFan()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(27, toshiba.getTemp()); + EXPECT_TRUE(toshiba.getPower()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba.getRaw()); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); + + // Turn off the power and re-check. + toshiba.setPower(false); + // Check everything for kicks. + EXPECT_EQ(1, toshiba.getFan()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(27, toshiba.getTemp()); + EXPECT_FALSE(toshiba.getPower()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba.getRaw()); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s1623m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s1623m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s1623m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s1623m543s472" + "m543s7048", + irsend.outputStr()); + + // Turn the power back on, and check nothing changed. + toshiba.on(); + + EXPECT_EQ(1, toshiba.getFan()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(27, toshiba.getTemp()); + EXPECT_TRUE(toshiba.getPower()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba.getRaw()); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeToshibaAC, SyntheticExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t expectedState[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + + irsend.reset(); + irsend.sendToshibaAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Test decoding against captures from a real Toshiba A/C remote. +// Recorded by @mwildbolz +TEST(TestDecodeToshibaAC, RealExamples) { + IRToshibaAC toshiba(0); + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint16_t rawData1[295] = { + 4442, 4292, 612, 1544, 616, 1544, 616, 1544, 612, 1548, 610, 468, + 612, 468, 662, 1494, 640, 438, 616, 464, 614, 464, 616, 464, + 612, 468, 610, 1544, 616, 1544, 616, 468, 612, 1544, 616, 464, + 694, 386, 616, 464, 612, 468, 612, 468, 636, 444, 610, 1546, + 616, 1544, 612, 1546, 614, 1546, 616, 1546, 740, 1420, 612, 1544, + 616, 1546, 616, 464, 610, 468, 610, 470, 612, 468, 610, 468, + 610, 470, 636, 438, 616, 464, 616, 464, 616, 1546, 636, 442, + 612, 1546, 614, 1544, 616, 464, 614, 464, 610, 468, 612, 468, + 612, 468, 612, 468, 636, 440, 614, 464, 616, 464, 616, 464, + 612, 468, 636, 442, 638, 442, 662, 418, 610, 464, 616, 464, + 616, 464, 610, 468, 612, 468, 636, 444, 610, 468, 638, 438, + 614, 1546, 612, 1548, 612, 470, 610, 468, 636, 442, 612, 468, + 612, 1544, 612, 7396, 4442, 4292, 610, 1546, 616, 1544, 612, 1548, + 612, 1546, 616, 464, 616, 464, 616, 1544, 612, 468, 662, 418, + 610, 468, 638, 442, 638, 438, 616, 1546, 616, 1544, 612, 468, + 610, 1546, 616, 464, 616, 464, 642, 438, 616, 464, 612, 468, + 610, 470, 610, 1546, 616, 1544, 612, 1546, 616, 1546, 614, 1546, + 612, 1550, 610, 1544, 616, 1546, 614, 464, 642, 438, 610, 468, + 612, 468, 612, 468, 612, 468, 610, 468, 638, 438, 614, 464, + 616, 1544, 636, 444, 636, 1520, 616, 1544, 616, 464, 616, 464, + 612, 468, 612, 468, 612, 468, 612, 468, 612, 464, 612, 470, + 636, 442, 638, 442, 612, 470, 692, 384, 614, 464, 616, 464, + 612, 468, 610, 468, 612, 468, 610, 470, 610, 464, 616, 464, + 616, 464, 616, 464, 610, 1550, 610, 1546, 640, 444, 688, 386, + 616, 464, 612, 468, 612, 1544, 642}; + + irsend.reset(); + irsend.sendRaw(rawData1, 295, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + toshiba.setRaw(irsend.capture.state); + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(23, toshiba.getTemp()); + EXPECT_EQ(kToshibaAcFanAuto, toshiba.getFan()); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + + uint16_t rawData2[295] = { + 4500, 4236, 636, 1520, 642, 1520, 640, 1520, 664, 1492, 642, 440, + 668, 412, 642, 1518, 638, 438, 666, 414, 640, 438, 642, 438, + 638, 442, 642, 1516, 640, 1520, 642, 438, 642, 1520, 636, 438, + 668, 412, 640, 440, 666, 412, 642, 438, 668, 412, 640, 1516, + 668, 1492, 642, 1520, 666, 1494, 638, 1520, 642, 1520, 668, 1490, + 666, 1494, 642, 438, 638, 438, 668, 412, 668, 412, 642, 438, + 642, 438, 664, 412, 642, 438, 642, 438, 642, 1518, 642, 434, + 668, 412, 642, 438, 668, 412, 692, 388, 666, 412, 642, 434, + 642, 438, 642, 1518, 668, 412, 668, 412, 640, 438, 638, 438, + 642, 438, 640, 438, 668, 1492, 642, 440, 666, 412, 640, 438, + 642, 438, 642, 434, 668, 412, 668, 412, 666, 414, 666, 1494, + 640, 438, 642, 434, 668, 412, 642, 438, 642, 438, 668, 412, + 668, 414, 640, 7362, 4474, 4262, 642, 1518, 638, 1520, 640, 1520, + 668, 1494, 640, 434, 642, 438, 640, 1520, 642, 438, 642, 438, + 642, 438, 642, 438, 642, 434, 668, 1494, 642, 1518, 638, 442, + 638, 1520, 642, 438, 642, 438, 668, 414, 664, 408, 642, 438, + 668, 412, 642, 1520, 666, 1494, 642, 1514, 642, 1518, 642, 1520, + 636, 1520, 668, 1494, 666, 1494, 638, 438, 666, 414, 640, 440, + 666, 412, 668, 412, 668, 412, 642, 434, 668, 412, 668, 412, + 668, 1494, 642, 438, 642, 434, 642, 438, 642, 438, 642, 438, + 642, 438, 642, 434, 646, 434, 642, 1518, 668, 412, 642, 438, + 642, 434, 666, 414, 640, 438, 642, 438, 642, 1518, 642, 438, + 642, 434, 668, 412, 642, 438, 642, 438, 642, 438, 642, 438, + 642, 438, 640, 1520, 636, 438, 642, 438, 642, 438, 666, 414, + 668, 412, 642, 440, 640, 438, 640}; + + irsend.reset(); + irsend.sendRaw(rawData2, 295, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + toshiba.setRaw(irsend.capture.state); + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(17, toshiba.getTemp()); + EXPECT_EQ(3, toshiba.getFan()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + + uint16_t rawData3[295] = { + 4474, 4262, 642, 1514, 642, 1520, 642, 1520, 642, 1514, 642, 438, + 642, 438, 642, 1520, 636, 438, 642, 438, 642, 438, 642, 438, + 642, 438, 640, 1520, 638, 1520, 642, 438, 640, 1520, 642, 438, + 642, 434, 642, 438, 642, 438, 642, 438, 668, 414, 636, 1520, + 642, 1520, 642, 1514, 642, 1520, 642, 1520, 640, 1518, 638, 1520, + 666, 1494, 642, 438, 642, 434, 642, 438, 640, 438, 642, 438, + 642, 440, 640, 434, 642, 438, 642, 438, 642, 1520, 642, 438, + 642, 1514, 642, 1520, 640, 1520, 636, 438, 642, 438, 642, 438, + 666, 414, 642, 1520, 636, 1520, 642, 438, 642, 438, 640, 438, + 642, 434, 642, 1518, 642, 1520, 642, 438, 642, 434, 640, 438, + 642, 438, 642, 438, 642, 440, 642, 438, 668, 408, 642, 1520, + 642, 438, 642, 1520, 638, 1518, 642, 438, 642, 438, 640, 1520, + 640, 438, 642, 7362, 4474, 4262, 642, 1518, 638, 1520, 640, 1520, + 642, 1520, 638, 438, 642, 438, 642, 1518, 642, 438, 638, 438, + 642, 438, 642, 438, 642, 438, 642, 1514, 642, 1520, 642, 438, + 666, 1490, 642, 438, 642, 438, 642, 440, 640, 438, 642, 434, + 640, 438, 642, 1520, 642, 1520, 636, 1520, 642, 1520, 642, 1514, + 642, 1518, 642, 1518, 640, 1516, 642, 438, 642, 438, 642, 438, + 640, 438, 638, 442, 642, 434, 642, 440, 640, 438, 642, 438, + 642, 1518, 642, 438, 642, 1514, 642, 1520, 642, 1518, 642, 438, + 642, 432, 642, 438, 642, 438, 642, 1520, 642, 1514, 642, 438, + 642, 438, 642, 438, 642, 438, 642, 1514, 642, 1520, 642, 438, + 642, 438, 638, 438, 642, 438, 642, 438, 640, 440, 642, 438, + 640, 434, 642, 1520, 642, 438, 640, 1520, 668, 1490, 666, 414, + 640, 438, 642, 1520, 642, 438, 636}; + + irsend.reset(); + irsend.sendRaw(rawData3, 295, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + toshiba.setRaw(irsend.capture.state); + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(24, toshiba.getTemp()); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); + EXPECT_EQ(kToshibaAcHeat, toshiba.getMode()); + + uint16_t rawData4[295] = { + 4474, 4262, 636, 1520, 640, 1520, 640, 1520, 638, 1518, 642, 438, + 642, 438, 642, 1520, 636, 438, 642, 438, 642, 438, 642, 438, + 636, 444, 636, 1520, 640, 1520, 642, 438, 638, 1524, 638, 438, + 640, 438, 642, 438, 640, 438, 642, 438, 638, 438, 642, 1518, + 642, 1520, 666, 1494, 636, 1520, 640, 1520, 640, 1520, 636, 1524, + 638, 1520, 640, 440, 640, 438, 642, 438, 636, 444, 636, 438, + 642, 438, 640, 440, 640, 438, 642, 438, 642, 1518, 638, 438, + 642, 1518, 642, 438, 640, 1520, 636, 444, 636, 438, 640, 438, + 642, 438, 668, 1494, 640, 438, 642, 1518, 636, 444, 636, 438, + 640, 1520, 642, 1518, 642, 1520, 636, 444, 636, 438, 642, 438, + 642, 438, 640, 440, 640, 438, 640, 440, 640, 438, 640, 1518, + 642, 1520, 636, 1524, 636, 1518, 642, 438, 642, 1518, 642, 1518, + 640, 438, 642, 7364, 4472, 4262, 642, 1518, 642, 1518, 638, 1518, + 642, 1520, 642, 438, 642, 438, 640, 1520, 636, 440, 640, 438, + 642, 438, 640, 438, 642, 438, 642, 1518, 636, 1524, 636, 438, + 640, 1520, 642, 438, 642, 438, 640, 438, 636, 444, 636, 438, + 668, 412, 642, 1518, 642, 1520, 642, 1520, 636, 1518, 642, 1518, + 642, 1520, 636, 1520, 668, 1494, 642, 438, 636, 444, 664, 412, + 642, 438, 668, 412, 642, 438, 636, 442, 638, 442, 638, 438, + 642, 1518, 642, 438, 642, 1518, 638, 438, 642, 1518, 642, 440, + 640, 438, 636, 444, 636, 444, 636, 1520, 642, 438, 642, 1520, + 636, 444, 636, 438, 642, 1520, 640, 1520, 636, 1520, 668, 412, + 642, 438, 642, 438, 642, 438, 638, 442, 636, 438, 642, 438, + 668, 412, 640, 1520, 638, 1524, 636, 1520, 642, 1520, 636, 444, + 638, 1522, 638, 1518, 640, 438, 642}; + + irsend.reset(); + irsend.sendRaw(rawData4, 295, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + toshiba.setRaw(irsend.capture.state); + EXPECT_FALSE(toshiba.getPower()); + EXPECT_EQ(22, toshiba.getTemp()); + EXPECT_EQ(4, toshiba.getFan()); + + // Confirming the quirky behaviour that the 'Power OFF' signal + // sets the mode to heat. + // The previous state the remote was in was 'AUTO' just prior to + // sending the power off message. + EXPECT_EQ(kToshibaAcHeat, toshiba.getMode()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp new file mode 100644 index 000000000..c30cb21d3 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp @@ -0,0 +1,118 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendWhirlpoolAC(). + +// Test sending typical data only. +TEST(TestSendWhirlpoolAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + uint8_t data[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + + irsend.sendWhirlpoolAC(data); + EXPECT_EQ( + "m8950s4484" + "m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533m597s1649" + "m597s533m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s1649m597s533m597s533m597s533" + "m597s1649m597s533m597s533m597s533m597s1649m597s1649m597s1649m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s7920" + "m597s1649m597s533m597s533m597s533m597s1649m597s533m597s533m597s1649" + "m597s1649m597s1649m597s1649m597s1649m597s1649m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s1649m597s1649m597s1649m597s1649m597s533m597s1649m597s1649m597s1649" + "m597s7920" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s100000", + irsend.outputStr()); +} + +// Tests for decodeWhirlpoolAC(). +// Decode normal WhirlpoolAC messages. +TEST(TestDecodeWhirlpoolAC, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Synthesised Normal WhirlpoolAC message. + irsend.reset(); + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + irsend.sendWhirlpoolAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); + EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a recorded example +TEST(TestDecodeWhirlpoolAC, RealExampleDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real WhirlpoolAC message. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/509 + uint16_t rawData[343] = { + 8950, 4484, 598, 1642, 598, 1646, 594, 534, 594, 538, 602, 532, + 598, 540, 600, 542, 598, 1650, 600, 522, 598, 1644, 596, 1650, + 600, 532, 598, 538, 602, 536, 594, 548, 592, 538, 602, 518, + 600, 524, 596, 532, 598, 532, 598, 1654, 596, 544, 596, 544, + 596, 536, 594, 1644, 596, 528, 600, 528, 592, 538, 602, 1648, + 602, 1654, 596, 1664, 598, 534, 594, 526, 594, 530, 598, 528, + 602, 530, 600, 534, 596, 542, 598, 542, 598, 534, 596, 526, + 594, 530, 600, 528, 602, 530, 600, 534, 596, 542, 598, 544, + 596, 518, 602, 7916, 598, 1642, 598, 528, 600, 528, 602, 530, + 600, 1652, 598, 542, 598, 544, 596, 1654, 596, 1644, 596, 1648, + 602, 1644, 596, 1654, 596, 1656, 604, 536, 594, 548, 602, 528, + 600, 520, 600, 524, 596, 532, 598, 532, 596, 538, 602, 536, + 594, 546, 594, 538, 602, 518, 600, 524, 596, 532, 598, 532, + 598, 536, 594, 544, 596, 544, 596, 536, 594, 526, 592, 530, + 600, 528, 600, 530, 602, 532, 596, 542, 598, 542, 598, 534, + 596, 524, 596, 528, 600, 526, 592, 538, 592, 542, 598, 540, + 600, 540, 600, 530, 598, 522, 598, 526, 594, 534, 596, 534, + 594, 540, 602, 536, 592, 548, 592, 538, 600, 1636, 594, 1648, + 602, 1642, 598, 1652, 598, 538, 602, 1680, 570, 1662, 598, 1634, + 596, 7924, 600, 520, 598, 526, 592, 534, 596, 534, 596, 540, + 600, 536, 604, 538, 602, 530, 600, 520, 598, 1640, 600, 528, + 600, 530, 600, 534, 594, 544, 596, 544, 596, 534, 596, 526, + 594, 528, 600, 526, 594, 536, 592, 542, 598, 538, 602, 538, + 602, 528, 600, 520, 600, 524, 596, 530, 600, 532, 598, 534, + 596, 542, 598, 542, 598, 532, 598, 524, 596, 528, 602, 526, + 594, 536, 594, 540, 600, 536, 594, 548, 592, 538, 602, 518, + 602, 522, 596, 530, 600, 530, 600, 534, 596, 542, 598, 544, + 596, 534, 596, 524, 594, 1644, 596, 532, 596, 534, 596, 538, + 602, 536, 594, 546, 594, 520, 600}; + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + + irsend.reset(); + irsend.sendRaw(rawData, 343, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); + EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Whynter_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Whynter_test.cpp similarity index 82% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Whynter_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Whynter_test.cpp index 4978bb6f5..748a4c9bf 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Whynter_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Whynter_test.cpp @@ -19,7 +19,8 @@ TEST(TestSendWhynter, SendDataOnly) { "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" - "m750s108000", irsend.outputStr()); + "m750s52050", + irsend.outputStr()); irsend.reset(); irsend.sendWhynter(0xFFFFFFFF); @@ -29,7 +30,8 @@ TEST(TestSendWhynter, SendDataOnly) { "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" - "m750s108000", irsend.outputStr()); + "m750s12200", + irsend.outputStr()); irsend.reset(); irsend.sendWhynter(0x87654321); @@ -39,7 +41,8 @@ TEST(TestSendWhynter, SendDataOnly) { "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000", irsend.outputStr()); + "m750s33850", + irsend.outputStr()); } // Test sending with different repeats. @@ -48,50 +51,55 @@ TEST(TestSendWhynter, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendWhynter(0x87654321, WHYNTER_BITS, 0); // 0 repeats. + irsend.sendWhynter(0x87654321, kWhynterBits, 0); // 0 repeats. EXPECT_EQ( "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000", irsend.outputStr()); + "m750s33850", + irsend.outputStr()); irsend.reset(); - irsend.sendWhynter(0x87654321, WHYNTER_BITS, 1); // 1 repeat. + irsend.sendWhynter(0x87654321, kWhynterBits, 1); // 1 repeat. EXPECT_EQ( "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000" + "m750s33850" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000", irsend.outputStr()); - irsend.sendWhynter(0x87654321, WHYNTER_BITS, 2); // 2 repeats. + "m750s33850", + irsend.outputStr()); + + irsend.reset(); + irsend.sendWhynter(0x87654321, kWhynterBits, 2); // 2 repeats. EXPECT_EQ( "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000" + "m750s33850" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000" + "m750s33850" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000", irsend.outputStr()); + "m750s33850", + irsend.outputStr()); } // Test sending an atypical data size. @@ -104,7 +112,8 @@ TEST(TestSendWhynter, SendUnusualSize) { EXPECT_EQ( "m750s750m2850s2850" "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" - "m750s108000", irsend.outputStr()); + "m750s88050", + irsend.outputStr()); irsend.reset(); irsend.sendWhynter(0x1234567890ABCDEF, 64); @@ -118,7 +127,8 @@ TEST(TestSendWhynter, SendUnusualSize) { "m750s2150m750s750m750s2150m750s750m750s2150m750s750m750s2150m750s2150" "m750s2150m750s2150m750s750m750s750m750s2150m750s2150m750s750m750s2150" "m750s2150m750s2150m750s2150m750s750m750s2150m750s2150m750s2150m750s2150" - "m750s108000", irsend.outputStr()); + "m750s12200", + irsend.outputStr()); } // Tests for decodeWhynter(). @@ -133,9 +143,9 @@ TEST(TestDecodeWhynter, NormalDecodeWithStrict) { irsend.reset(); irsend.sendWhynter(0x87654321); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -150,24 +160,24 @@ TEST(TestDecodeWhynter, NormalDecodeWithRepeatAndStrict) { // Normal Whynter 32-bit message with 2 repeats. irsend.reset(); - irsend.sendWhynter(0x87654321, WHYNTER_BITS, 2); + irsend.sendWhynter(0x87654321, kWhynterBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); EXPECT_FALSE(irsend.capture.repeat); - irsend.makeDecodeResult(2 * WHYNTER_BITS + 6); - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + irsend.makeDecodeResult(2 * kWhynterBits + 6); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); - irsend.makeDecodeResult(2 * (2 * WHYNTER_BITS + 6)); - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + irsend.makeDecodeResult(2 * (2 * kWhynterBits + 6)); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); } @@ -181,7 +191,7 @@ TEST(TestDecodeWhynter, DecodeWithNonStrictSizes) { irsend.sendWhynter(0x12, 8); // Illegal sized Whynter 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, 8, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, 8, false)); @@ -195,7 +205,7 @@ TEST(TestDecodeWhynter, DecodeWithNonStrictSizes) { irsend.sendWhynter(0x1234567890, 40); // Illegal size Whynter 40-bit message. irsend.makeDecodeResult(); // Shouldn't pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -236,12 +246,13 @@ TEST(TestDecodeWhynter, FailToDecodeNonWhynterExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, false)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, false)); } diff --git a/lib/IRremoteESP8266-2.2.1.02/tools/Makefile b/lib/IRremoteESP8266-2.5.2.03/tools/Makefile similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/tools/Makefile rename to lib/IRremoteESP8266-2.5.2.03/tools/Makefile index 84bf6569b..c303e051d 100644 --- a/lib/IRremoteESP8266-2.2.1.02/tools/Makefile +++ b/lib/IRremoteESP8266-2.5.2.03/tools/Makefile @@ -22,10 +22,22 @@ CPPFLAGS += -DUNIT_TEST # Flags passed to the C++ compiler. CXXFLAGS += -g -Wall -Wextra -pthread -all : gc_decode +all : gc_decode mode2_decode + +run_tests : all + failed=""; \ + for py_unittest in *_test.py; do \ + echo "RUNNING: $${py_unittest}"; \ + python ./$${py_unittest} || failed="$${failed} $${py_unittest}"; \ + done; \ + if [ -n "$${failed}" ]; then \ + echo "FAIL: :-( :-( Unit test(s)$${failed} failed! :-( :-("; exit 1; \ + else \ + echo "PASS: \o/ \o/ All unit tests passed. \o/ \o/"; \ + fi clean : - rm -f *.o gc_decode + rm -f *.o *.pyc gc_decode mode2_decode # All the IR protocol object files. @@ -33,9 +45,13 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \ ir_LG.o ir_Mitsubishi.o ir_Fujitsu.o ir_Sharp.o ir_Sanyo.o \ ir_Denon.o ir_Dish.o ir_Panasonic.o ir_Whynter.o ir_Coolix.o \ ir_Aiwa.o ir_Sherwood.o ir_Kelvinator.o ir_Daikin.o ir_Gree.o \ - ir_Pronto.o ir_GlobalCache.o ir_Nikai.o + ir_Pronto.o ir_GlobalCache.o ir_Nikai.o ir_Toshiba.o ir_Midea.o \ + ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o ir_Hitachi.o \ + ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o ir_Pioneer.o \ + ir_MWM.o + # Common object files -COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS) +COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS) # Common dependencies COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \ @@ -49,8 +65,13 @@ gc_decode.o : gc_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) gc_decode : $(COMMON_OBJ) gc_decode.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ +mode2_decode.o : mode2_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -I$(TEST_DIR) -c mode2_decode.cpp -IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h +mode2_decode : $(COMMON_OBJ) mode2_decode.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h @@ -75,7 +96,7 @@ ir_Sherwood.o : $(USER_DIR)/ir_Sherwood.cpp $(COMMON_DEPS) ir_Sony.o : $(USER_DIR)/ir_Sony.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sony.cpp -ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(COMMON_DEPS) +ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp ir_Kelvinator.o : $(USER_DIR)/ir_Kelvinator.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_DEPS) @@ -134,3 +155,42 @@ ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS) ir_Nikai.o : $(USER_DIR)/ir_Nikai.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Nikai.cpp + +ir_Toshiba.o : $(USER_DIR)/ir_Toshiba.h $(USER_DIR)/ir_Toshiba.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Toshiba.cpp + +ir_Midea.o : $(USER_DIR)/ir_Midea.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Midea.cpp + +ir_Magiquest.o : $(USER_DIR)/ir_Magiquest.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Magiquest.cpp + +ir_Lasertag.o : $(USER_DIR)/ir_Lasertag.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lasertag.cpp + +ir_Carrier.o : $(USER_DIR)/ir_Carrier.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Carrier.cpp + +ir_Haier.o : $(USER_DIR)/ir_Haier.cpp $(USER_DIR)/ir_Haier.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Haier.cpp + +ir_Hitachi.o : $(USER_DIR)/ir_Hitachi.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Hitachi.cpp + +ir_GICable.o : $(USER_DIR)/ir_GICable.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GICable.cpp + +ir_Whirlpool.o : $(USER_DIR)/ir_Whirlpool.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whirlpool.cpp + +ir_Lutron.o : $(USER_DIR)/ir_Lutron.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lutron.cpp + +ir_Electra.o : $(USER_DIR)/ir_Electra.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Electra.cpp + +ir_Pioneer.o : $(USER_DIR)/ir_Pioneer.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pioneer.cpp + +ir_MWM.o : $(USER_DIR)/ir_MWM.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_MWM.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh b/lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh new file mode 100644 index 000000000..e0b0ebe35 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Convert IRremoteESP8266's rawData output into Global Cache format. + +function isDigits() +{ + [[ "$1" =~ ^[0-9]+$ ]] +} + +function usage() +{ +cat << EOF +Usage: $0 Frequency_in_Hz + Reads an IRremoteESP8266 rawData declaration from STDIN and converts it to + GlobalCache format. + e.g. + uint16_t rawbuf[37] = { + 7930, 3952, 494, 1482, 520, 1482, 494, 1508, + 494, 520, 494, 1482, 494, 520, 494, 1482, + 494, 1482, 494, 3978, 494, 520, 494, 520, + 494, 520, 494, 520, 520, 520, 494, 520, + 494, 520, 494, 520, 494}; +EOF + exit 1 +} + +# We need a frequency argument. +if [[ $# -ne 1 ]]; then + usage +fi +HZ="$1" +# HZ must be a positive number +if ! isDigits "${HZ}"; then + usage +fi +# HZ must not be zero. +if [[ ${HZ} == 0 ]]; then + usage +fi + + +PERIOD_OFFSET=0 +period=$((((1000000 + (${HZ} / 2)) / ${HZ}) + ${PERIOD_OFFSET})) +result="${HZ},1,1" +while read line; do + # Quick and Dirty Removal of any array declaration syntax, and any commas. + line="$(echo ${line} | sed 's/uint.*{//i' | sed 's/,//g' | sed 's/};.*//g')" + for msecs in ${line}; do + if isDigits "${msecs}"; then + result="${result},$((${msecs} / ${period}))" + fi + done +done +echo "GlobalCache code = \"${result}\"" diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py b/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py new file mode 100644 index 000000000..5fd399807 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py @@ -0,0 +1,432 @@ +#!/usr/bin/python +"""Attempt an automatic analysis of IRremoteESP8266's Raw data output. + Makes suggestions on key values and tried to break down the message + into likely chunks.""" +# +# Copyright 2018 David Conran +import argparse +import sys + + +class RawIRMessage(object): + """Basic analyse functions & structure for raw IR messages.""" + + # pylint: disable=too-many-instance-attributes + + def __init__(self, margin, timings, output=sys.stdout, verbose=True): + self.hdr_mark = None + self.hdr_space = None + self.bit_mark = None + self.zero_space = None + self.one_space = None + self.gaps = [] + self.margin = margin + self.marks = [] + self.mark_buckets = {} + self.spaces = [] + self.space_buckets = {} + self.output = output + self.verbose = verbose + if len(timings) <= 3: + raise ValueError("Too few message timings supplied.") + self.timings = timings + self._generate_timing_candidates() + self._calc_values() + + def _generate_timing_candidates(self): + """Determine the likely values from the given data.""" + count = 0 + for usecs in self.timings: + count = count + 1 + if count % 2: + self.marks.append(usecs) + else: + self.spaces.append(usecs) + self.marks, self.mark_buckets = self.reduce_list(self.marks) + self.spaces, self.space_buckets = self.reduce_list(self.spaces) + + def reduce_list(self, items): + """Reduce a list of numbers into buckets that are at least margin apart.""" + result = [] + last = -1 + buckets = {} + for item in sorted(items, reverse=True): + if last == -1 or item < last - self.margin: + result.append(item) + last = item + buckets[last] = [item] + else: + buckets[last].append(item) + return result, buckets + + def _usec_compare(self, seen, expected): + """Compare two usec values and see if they match within a + subtractive margin.""" + return seen <= expected and seen > expected - self.margin + + def _usec_compares(self, usecs, expecteds): + """Compare a usec value to a list of values and return True + if they are within a subtractive margin.""" + for expected in expecteds: + if self._usec_compare(usecs, expected): + return True + return False + + def display_binary(self, binary_str): + """Display common representations of the suppied binary string.""" + num = int(binary_str, 2) + bits = len(binary_str) + rev_binary_str = binary_str[::-1] + rev_num = int(rev_binary_str, 2) + self.output.write("\n Bits: %d\n" + " Hex: %s (MSB first)\n" + " %s (LSB first)\n" + " Dec: %s (MSB first)\n" + " %s (LSB first)\n" + " Bin: 0b%s (MSB first)\n" + " 0b%s (LSB first)\n" % + (bits, "0x{0:0{1}X}".format(num, bits / 4), + "0x{0:0{1}X}".format(rev_num, bits / 4), num, rev_num, + binary_str, rev_binary_str)) + + def add_data_code(self, bin_str, footer=True): + """Add the common "data" sequence of code to send the bulk of a message.""" + # pylint: disable=no-self-use + code = [] + code.append(" // Data") + code.append(" // e.g. data = 0x%X, nbits = %d" % (int(bin_str, 2), + len(bin_str))) + code.append(" sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, " + "nbits, true);") + if footer: + code.append(" // Footer") + code.append(" mark(kBitMark);") + return code + + def _calc_values(self): + """Calculate the values which describe the standard timings + for the protocol.""" + if self.verbose: + self.output.write("Potential Mark Candidates:\n" + "%s\n" + "Potential Space Candidates:\n" + "%s\n" % (str(self.marks), str(self.spaces))) + # Largest mark is likely the kHdrMark + self.hdr_mark = self.marks[0] + # The bit mark is likely to be the smallest mark. + self.bit_mark = self.marks[-1] + + if self.is_space_encoded() and len(self.spaces) >= 3: + if self.verbose and len(self.marks) > 2: + self.output.write("DANGER: Unexpected and unused mark timings!") + # We should have 3 space candidates at least. + # They should be: zero_space (smallest), one_space, & hdr_space (largest) + spaces = list(self.spaces) + self.zero_space = spaces.pop() + self.one_space = spaces.pop() + self.hdr_space = spaces.pop() + # Rest are probably message gaps + self.gaps = spaces + + def is_space_encoded(self): + """Make an educated guess if the message is space encoded.""" + return len(self.spaces) > len(self.marks) + + def is_hdr_mark(self, usec): + """Is usec the header mark?""" + return self._usec_compare(usec, self.hdr_mark) + + def is_hdr_space(self, usec): + """Is usec the header space?""" + return self._usec_compare(usec, self.hdr_space) + + def is_bit_mark(self, usec): + """Is usec the bit mark?""" + return self._usec_compare(usec, self.bit_mark) + + def is_one_space(self, usec): + """Is usec the one space?""" + return self._usec_compare(usec, self.one_space) + + def is_zero_space(self, usec): + """Is usec the zero_space?""" + return self._usec_compare(usec, self.zero_space) + + def is_gap(self, usec): + """Is usec the a space gap?""" + return self._usec_compares(usec, self.gaps) + + +def avg_list(items): + """Return the average of a list of numbers.""" + if items: + return sum(items) / len(items) + return 0 + + +def add_bit(so_far, bit, output=sys.stdout): + """Add a bit to the end of the bits collected so far.""" + if bit == "reset": + return "" + output.write(str(bit)) # This effectively displays in LSB first order. + return so_far + str(bit) # Storing it in MSB first order. + + +def convert_rawdata(data_str): + """Parse a C++ rawdata declaration into a list of values.""" + start = data_str.find('{') + end = data_str.find('}') + if end == -1: + end = len(data_str) + if start > end: + raise ValueError("Raw Data not parsible due to parentheses placement.") + data_str = data_str[start + 1:end] + results = [] + for timing in [x.strip() for x in data_str.split(',')]: + try: + results.append(int(timing)) + except ValueError: + raise ValueError( + "Raw Data contains a non-numeric value of '%s'." % timing) + return results + + +def dump_constants(message, defines, output=sys.stdout): + """Dump the key constants and generate the C++ #defines.""" + hdr_mark = avg_list(message.mark_buckets[message.hdr_mark]) + bit_mark = avg_list(message.mark_buckets[message.bit_mark]) + hdr_space = avg_list(message.space_buckets[message.hdr_space]) + one_space = avg_list(message.space_buckets[message.one_space]) + zero_space = avg_list(message.space_buckets[message.zero_space]) + + output.write("Guessing key value:\n" + "kHdrMark = %d\n" + "kHdrSpace = %d\n" + "kBitMark = %d\n" + "kOneSpace = %d\n" + "kZeroSpace = %d\n" % (hdr_mark, hdr_space, bit_mark, one_space, + zero_space)) + defines.append("const uint16_t kHdrMark = %d;" % hdr_mark) + defines.append("const uint16_t kBitMark = %d;" % bit_mark) + defines.append("const uint16_t kHdrSpace = %d;" % hdr_space) + defines.append("const uint16_t kOneSpace = %d;" % one_space) + defines.append("const uint16_t kZeroSpace = %d;" % zero_space) + + avg_gaps = [avg_list(message.space_buckets[x]) for x in message.gaps] + if len(message.gaps) == 1: + output.write("kSpaceGap = %d\n" % avg_gaps[0]) + defines.append("const uint16_t kSpaceGap = %d;" % avg_gaps[0]) + else: + count = 0 + for gap in avg_gaps: + # We probably (still) have a gap in the protocol. + count = count + 1 + output.write("kSpaceGap%d = %d\n" % (count, gap)) + defines.append("const uint16_t kSpaceGap%d = %d;" % (count, gap)) + + +def parse_and_report(rawdata_str, margin, gen_code=False, output=sys.stdout): + """Analyse the rawdata c++ definition of a IR message.""" + defines = [] + function_code = [] + + # Parse the input. + rawdata = convert_rawdata(rawdata_str) + + output.write("Found %d timing entries.\n" % len(rawdata)) + + message = RawIRMessage(margin, rawdata, output) + output.write("\nGuessing encoding type:\n") + if message.is_space_encoded(): + output.write("Looks like it uses space encoding. Yay!\n\n") + dump_constants(message, defines, output) + else: + output.write("Sorry, it looks like it is Mark encoded. " + "I can't do that yet. Exiting.\n") + sys.exit(1) + total_bits = decode_data(message, defines, function_code, output) + if gen_code: + generate_irsend_code(defines, function_code, total_bits, output) + + +def decode_data(message, defines, function_code, output=sys.stdout): + """Decode the data sequence with the given values in mind.""" + # pylint: disable=too-many-branches,too-many-statements + + # Now we have likely candidates for the key values, go through the original + # sequence and break it up and indicate accordingly. + + output.write("\nDecoding protocol based on analysis so far:\n\n") + state = "" + count = 1 + total_bits = "" + binary_value = add_bit("", "reset") + + function_code.extend([ + "// Function should be safe up to 64 bits.", + "void IRsend::sendXyz(const uint64_t data, const uint16_t" + " nbits, const uint16_t repeat) {", + " enableIROut(38); // A guess. Most common frequency.", + " for (uint16_t r = 0; r <= repeat; r++) {" + ]) + + for usec in message.timings: + if (message.is_hdr_mark(usec) and count % 2 and + not message.is_bit_mark(usec)): + state = "HM" + if binary_value: + message.display_binary(binary_value) + function_code.extend(message.add_data_code(binary_value, False)) + total_bits = total_bits + binary_value + binary_value = add_bit(binary_value, "reset") + output.write("kHdrMark+") + function_code.extend([" // Header", " mark(kHdrMark);"]) + elif message.is_hdr_space(usec) and not message.is_one_space(usec): + if state != "HM": + if binary_value: + message.display_binary(binary_value) + total_bits = total_bits + binary_value + function_code.extend(message.add_data_code(binary_value)) + binary_value = add_bit(binary_value, "reset") + output.write("UNEXPECTED->") + state = "HS" + output.write("kHdrSpace+") + function_code.append(" space(kHdrSpace);") + elif message.is_bit_mark(usec) and count % 2: + if state != "HS" and state != "BS": + output.write("kBitMark(UNEXPECTED)") + state = "BM" + elif message.is_zero_space(usec): + if state != "BM": + output.write("kZeroSpace(UNEXPECTED)") + state = "BS" + binary_value = add_bit(binary_value, 0, output) + elif message.is_one_space(usec): + if state != "BM": + output.write("kOneSpace(UNEXPECTED)") + state = "BS" + binary_value = add_bit(binary_value, 1, output) + elif message.is_gap(usec): + if state != "BM": + output.write("UNEXPECTED->") + state = "GS" + output.write("GAP(%d)" % usec) + if binary_value: + message.display_binary(binary_value) + function_code.extend(message.add_data_code(binary_value)) + else: + function_code.extend([" // Gap", " mark(kBitMark);"]) + function_code.append(" space(kSpaceGap);") + total_bits = total_bits + binary_value + binary_value = add_bit(binary_value, "reset") + else: + output.write("UNKNOWN(%d)" % usec) + state = "UNK" + count = count + 1 + if binary_value: + message.display_binary(binary_value) + function_code.extend(message.add_data_code(binary_value)) + function_code.extend([ + " space(100000); // A 100% made up guess of the gap" + " between messages.", " }", "}" + ]) + + total_bits = total_bits + binary_value + output.write("\nTotal Nr. of suspected bits: %d\n" % len(total_bits)) + defines.append("const uint16_t kXyzBits = %d;" % len(total_bits)) + if len(total_bits) > 64: + defines.append("const uint16_t kXyzStateLength = %d;" % + (len(total_bits) / 8)) + return total_bits + + +def generate_irsend_code(defines, normal, bits_str, output=sys.stdout): + """Output the estimated C++ code to reproduce the IR message.""" + output.write("\nGenerating a VERY rough code outline:\n\n" + "// WARNING: This probably isn't directly usable." + " It's a guide only.\n") + for line in defines: + output.write("%s\n" % line) + + if len(bits_str) > 64: # Will it fit in a uint64_t? + output.write("// DANGER: More than 64 bits detected. A uint64_t for " + "'data' won't work!\n") + # Display the "normal" version's code incase there are some + # oddities in it. + for line in normal: + output.write("%s\n" % line) + + if len(bits_str) > 64: # Will it fit in a uint64_t? + output.write("\n\n// Alternative >64 bit Function\n" + "void IRsend::sendXyz(uint8_t data[], uint16_t nbytes," + " uint16_t repeat) {\n" + " // nbytes should typically be kXyzStateLength\n" + " // data should typically be:\n" + " // uint8_t data[kXyzStateLength] = {0x%s};\n" + " // data[] is assumed to be in MSB order for this code.\n" + " for (uint16_t r = 0; r <= repeat; r++) {\n" + " sendGeneric(kHdrMark, kHdrSpace,\n" + " kBitMark, kOneSpace,\n" + " kBitMark, kZeroSpace,\n" + " kBitMark,\n" + " 100000, // 100%% made-up guess at the" + " message gap.\n" + " data, nbytes,\n" + " 38000, // Complete guess of the modulation" + " frequency.\n" + " true, 0, 50);\n" + " }\n" + "}\n" % ", 0x".join("%02X" % int(bits_str[i:i + 8], 2) + for i in range(0, len(bits_str), 8))) + + +def main(): + """Parse the commandline arguments and call the method.""" + arg_parser = argparse.ArgumentParser( + description="Read an IRremoteESP8266 rawData declaration and tries to " + "analyse it.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + arg_parser.add_argument( + "-g", + "--code", + action="store_true", + default=False, + dest="gen_code", + help="Generate a C++ code outline to aid making an IRsend function.") + arg_group = arg_parser.add_mutually_exclusive_group(required=True) + arg_group.add_argument( + "rawdata", + help="A rawData line from IRrecvDumpV2. e.g. 'uint16_t rawbuf[37] = {" + "7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, " + "520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, " + "494, 520, 520, 520, 494, 520, 494, 520, 494, 520, 494};'", + nargs="?") + arg_group.add_argument( + "-f", "--file", help="Read in a rawData line from the file.") + arg_parser.add_argument( + "-r", + "--range", + type=int, + help="Max number of micro-seconds difference between values to consider" + " it the same value.", + dest="margin", + default=200) + arg_group.add_argument( + "--stdin", + help="Read in a rawData line from STDIN.", + action="store_true", + default=False) + arg_options = arg_parser.parse_args() + + if arg_options.stdin: + data = sys.stdin.read() + elif arg_options.file: + with open(arg_options.file) as input_file: + data = input_file.read() + else: + data = arg_options.rawdata + parse_and_report(data, arg_options.margin, arg_options.gen_code) + + +if __name__ == '__main__': + main() diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py b/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py new file mode 100644 index 000000000..681ff5520 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py @@ -0,0 +1,492 @@ +#!/usr/bin/python +"""Unit tests for auto_analyse_raw_data.py""" +import StringIO +import unittest +import auto_analyse_raw_data as analyse + + +class TestRawIRMessage(unittest.TestCase): + """Unit tests for the RawIRMessage class.""" + + # pylint: disable=too-many-public-methods + + def test_display_binary(self): + """Test the display_binary() method.""" + output = StringIO.StringIO() + message = analyse.RawIRMessage(100, [8000, 4000, 500, 500, 500], output, + False) + self.assertEqual(output.getvalue(), '') + message.display_binary("10101010") + message.display_binary("0000000000000000") + message.display_binary("00010010001101000101011001111000") + self.assertEqual(output.getvalue(), '\n' + ' Bits: 8\n' + ' Hex: 0xAA (MSB first)\n' + ' 0x55 (LSB first)\n' + ' Dec: 170 (MSB first)\n' + ' 85 (LSB first)\n' + ' Bin: 0b10101010 (MSB first)\n' + ' 0b01010101 (LSB first)\n' + '\n' + ' Bits: 16\n' + ' Hex: 0x0000 (MSB first)\n' + ' 0x0000 (LSB first)\n' + ' Dec: 0 (MSB first)\n' + ' 0 (LSB first)\n' + ' Bin: 0b0000000000000000 (MSB first)\n' + ' 0b0000000000000000 (LSB first)\n' + '\n' + ' Bits: 32\n' + ' Hex: 0x12345678 (MSB first)\n' + ' 0x1E6A2C48 (LSB first)\n' + ' Dec: 305419896 (MSB first)\n' + ' 510274632 (LSB first)\n' + ' Bin: 0b00010010001101000101011001111000 (MSB first)\n' + ' 0b00011110011010100010110001001000 (LSB first)\n') + + +class TestAutoAnalyseRawData(unittest.TestCase): + """Unit tests for the functions in AutoAnalyseRawData.""" + + # pylint: disable=too-many-public-methods + + def test_dump_constants_simple(self): + """Simple tests for the dump_constants() function.""" + ignore = StringIO.StringIO() + output = StringIO.StringIO() + defs = [] + message = analyse.RawIRMessage(200, [ + 7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, + 520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494, + 520, 520, 520, 494, 520, 494, 520, 494, 1482, 494 + ], ignore) + analyse.dump_constants(message, defs, output) + self.assertEqual(defs, [ + 'const uint16_t kHdrMark = 7930;', 'const uint16_t kBitMark = 496;', + 'const uint16_t kHdrSpace = 3965;', 'const uint16_t kOneSpace = 1485;', + 'const uint16_t kZeroSpace = 520;' + ]) + self.assertEqual(output.getvalue(), 'Guessing key value:\n' + 'kHdrMark = 7930\n' + 'kHdrSpace = 3965\n' + 'kBitMark = 496\n' + 'kOneSpace = 1485\n' + 'kZeroSpace = 520\n') + + def test_dump_constants_aircon(self): + """More complex tests for the dump_constants() function.""" + ignore = StringIO.StringIO() + output = StringIO.StringIO() + defs = [] + message = analyse.RawIRMessage(200, [ + 9008, 4496, 644, 1660, 676, 530, 648, 558, 672, 1636, 646, 1660, 644, + 556, 650, 584, 626, 560, 644, 580, 628, 1680, 624, 560, 648, 1662, 644, + 582, 648, 536, 674, 530, 646, 580, 628, 560, 670, 532, 646, 562, 644, + 556, 672, 536, 648, 1662, 646, 1660, 652, 554, 644, 558, 672, 538, 644, + 560, 668, 560, 648, 1638, 668, 536, 644, 1660, 668, 532, 648, 560, 648, + 1660, 674, 554, 622, 19990, 646, 580, 624, 1660, 648, 556, 648, 558, + 674, 556, 622, 560, 644, 564, 668, 536, 646, 1662, 646, 1658, 672, 534, + 648, 558, 644, 562, 648, 1662, 644, 584, 622, 558, 648, 562, 668, 534, + 670, 536, 670, 532, 672, 536, 646, 560, 646, 558, 648, 558, 670, 534, + 650, 558, 646, 560, 646, 560, 668, 1638, 646, 1662, 646, 1660, 646, + 1660, 648 + ], ignore) + analyse.dump_constants(message, defs, output) + self.assertEqual(defs, [ + 'const uint16_t kHdrMark = 9008;', 'const uint16_t kBitMark = 650;', + 'const uint16_t kHdrSpace = 4496;', 'const uint16_t kOneSpace = 1657;', + 'const uint16_t kZeroSpace = 554;', 'const uint16_t kSpaceGap = 19990;' + ]) + self.assertEqual(output.getvalue(), 'Guessing key value:\n' + 'kHdrMark = 9008\n' + 'kHdrSpace = 4496\n' + 'kBitMark = 650\n' + 'kOneSpace = 1657\n' + 'kZeroSpace = 554\n' + 'kSpaceGap = 19990\n') + + def test_convert_rawdata(self): + """Tests for the convert_rawdata() function.""" + # trivial cases + self.assertEqual(analyse.convert_rawdata("0"), [0]) + with self.assertRaises(ValueError) as context: + analyse.convert_rawdata("") + self.assertEqual(context.exception.message, + "Raw Data contains a non-numeric value of ''.") + + # Single parenthesis + self.assertEqual(analyse.convert_rawdata("foo {10"), [10]) + self.assertEqual(analyse.convert_rawdata("20} bar"), [20]) + + # No parentheses + self.assertEqual(analyse.convert_rawdata("10,20 , 30"), [10, 20, 30]) + + # Dual parentheses + self.assertEqual(analyse.convert_rawdata("{10,20 , 30}"), [10, 20, 30]) + self.assertEqual(analyse.convert_rawdata("foo{10,20}bar"), [10, 20]) + + # Many parentheses + self.assertEqual(analyse.convert_rawdata("foo{10,20}{bar}"), [10, 20]) + self.assertEqual(analyse.convert_rawdata("foo{10,20}{bar}}{"), [10, 20]) + + # Bad parentheses + with self.assertRaises(ValueError) as context: + analyse.convert_rawdata("}10{") + self.assertEqual(context.exception.message, + "Raw Data not parsible due to parentheses placement.") + + # Non base-10 values + with self.assertRaises(ValueError) as context: + analyse.convert_rawdata("10, 20, foo, bar, 30") + self.assertEqual(context.exception.message, + "Raw Data contains a non-numeric value of 'foo'.") + + # A messy usual "good" case. + input_str = """uint16_t rawbuf[6] = { + 9008, 4496, 644, + 1660, 676, + + 530} + ;""" + self.assertEqual( + analyse.convert_rawdata(input_str), [9008, 4496, 644, 1660, 676, 530]) + + def test_parse_and_report(self): + """Tests for the parse_and_report() function.""" + + # Without code generation. + output = StringIO.StringIO() + input_str = """ + uint16_t rawbuf[139] = {9008, 4496, 644, 1660, 676, 530, 648, 558, 672, + 1636, 646, 1660, 644, 556, 650, 584, 626, 560, 644, 580, 628, 1680, + 624, 560, 648, 1662, 644, 582, 648, 536, 674, 530, 646, 580, 628, + 560, 670, 532, 646, 562, 644, 556, 672, 536, 648, 1662, 646, 1660, + 652, 554, 644, 558, 672, 538, 644, 560, 668, 560, 648, 1638, 668, + 536, 644, 1660, 668, 532, 648, 560, 648, 1660, 674, 554, 622, 19990, + 646, 580, 624, 1660, 648, 556, 648, 558, 674, 556, 622, 560, 644, + 564, 668, 536, 646, 1662, 646, 1658, 672, 534, 648, 558, 644, 562, + 648, 1662, 644, 584, 622, 558, 648, 562, 668, 534, 670, 536, 670, + 532, 672, 536, 646, 560, 646, 558, 648, 558, 670, 534, 650, 558, + 646, 560, 646, 560, 668, 1638, 646, 1662, 646, 1660, 646, 1660, + 648};""" + analyse.parse_and_report(input_str, 200, False, output) + self.assertEqual( + output.getvalue(), 'Found 139 timing entries.\n' + 'Potential Mark Candidates:\n' + '[9008, 676]\n' + 'Potential Space Candidates:\n' + '[19990, 4496, 1680, 584]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kHdrMark = 9008\n' + 'kHdrSpace = 4496\n' + 'kBitMark = 650\n' + 'kOneSpace = 1657\n' + 'kZeroSpace = 554\n' + 'kSpaceGap = 19990\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kHdrMark+kHdrSpace+10011000010100000000011000001010010GAP(19990)\n' + ' Bits: 35\n' + ' Hex: 0x4C2803052 (MSB first)\n' + ' 0x250600A19 (LSB first)\n' + ' Dec: 20443050066 (MSB first)\n' + ' 9938405913 (LSB first)\n' + ' Bin: 0b10011000010100000000011000001010010 (MSB first)\n' + ' 0b01001010000011000000000101000011001 (LSB first)\n' + 'kBitMark(UNEXPECTED)01000000110001000000000000001111\n' + ' Bits: 32\n' + ' Hex: 0x40C4000F (MSB first)\n' + ' 0xF0002302 (LSB first)\n' + ' Dec: 1086586895 (MSB first)\n' + ' 4026540802 (LSB first)\n' + ' Bin: 0b01000000110001000000000000001111 (MSB first)\n' + ' 0b11110000000000000010001100000010 (LSB first)\n' + '\n' + 'Total Nr. of suspected bits: 67\n') + + # With code generation. + output = StringIO.StringIO() + input_str = """ + uint16_t rawbuf[37] = {7930, 3952, 494, 1482, 520, 1482, 494, + 1508, 494, 520, 494, 1482, 494, 520, 494, 1482, 494, 1482, 494, + 3978, 494, 520, 494, 520, 494, 520, 494, 520, 520, 520, 494, 520, + 494, 520, 494, 1482, 494};""" + analyse.parse_and_report(input_str, 200, True, output) + self.assertEqual( + output.getvalue(), 'Found 37 timing entries.\n' + 'Potential Mark Candidates:\n' + '[7930, 520]\n' + 'Potential Space Candidates:\n' + '[3978, 1508, 520]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kHdrMark = 7930\n' + 'kHdrSpace = 3965\n' + 'kBitMark = 496\n' + 'kOneSpace = 1485\n' + 'kZeroSpace = 520\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kHdrMark+kHdrSpace+11101011\n' + ' Bits: 8\n' + ' Hex: 0xEB (MSB first)\n' + ' 0xD7 (LSB first)\n' + ' Dec: 235 (MSB first)\n' + ' 215 (LSB first)\n' + ' Bin: 0b11101011 (MSB first)\n' + ' 0b11010111 (LSB first)\n' + 'UNEXPECTED->kHdrSpace+00000001\n' + ' Bits: 8\n' + ' Hex: 0x01 (MSB first)\n' + ' 0x80 (LSB first)\n' + ' Dec: 1 (MSB first)\n' + ' 128 (LSB first)\n' + ' Bin: 0b00000001 (MSB first)\n' + ' 0b10000000 (LSB first)\n' + '\n' + 'Total Nr. of suspected bits: 16\n' + '\n' + 'Generating a VERY rough code outline:\n' + '\n' + "// WARNING: This probably isn't directly usable. It's a guide only.\n" + 'const uint16_t kHdrMark = 7930;\n' + 'const uint16_t kBitMark = 496;\n' + 'const uint16_t kHdrSpace = 3965;\n' + 'const uint16_t kOneSpace = 1485;\n' + 'const uint16_t kZeroSpace = 520;\n' + 'const uint16_t kXyzBits = 16;\n' + '// Function should be safe up to 64 bits.\n' + 'void IRsend::sendXyz(const uint64_t data, const uint16_t nbits,' + ' const uint16_t repeat) {\n' + ' enableIROut(38); // A guess. Most common frequency.\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0xEB, nbits = 8\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Footer\n' + ' mark(kBitMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x1, nbits = 8\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Footer\n' + ' mark(kBitMark);\n' + ' space(100000); // A 100% made up guess of the gap between' + ' messages.\n' + ' }\n' + '}\n') + + def test_unusual_gaps(self): + """Tests for unusual Space Gaps in parse_and_report() function.""" + + # Tests for unusual Gaps. (Issue #482) + output = StringIO.StringIO() + input_str = """ + uint16_t rawbuf[272] = {3485, 3512, 864, 864, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, + 864, 2620, 864, 864, 864, 2620, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, 864, 864, 864, 864, 864, 2620, 864, 864, + 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, + 3485, 3512, 864, 864, 864, 2620, 864, 864, 864, 2620, 864, 2620, + 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, 2620, 864, 864, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, + 3485, 3512, 864, 13996, + 3485, 3512, 864, 864, 864, 864, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 864, 864, 2620, + 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 864, + 864, 864, 864, 864, 864, 2620, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 864, 864, 864, + 3485, 3512, 864, 864, 864, 864, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 864, 864, 2620, + 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 864, + 864, 864, 864, 864, 864, 2620, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 864, 864, 864, 3485, 3512, 864, 13996};""" + analyse.parse_and_report(input_str, 200, True, output) + self.assertEqual( + output.getvalue(), 'Found 272 timing entries.\n' + 'Potential Mark Candidates:\n' + '[3485, 864]\n' + 'Potential Space Candidates:\n' + '[13996, 3512, 2620, 864]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kHdrMark = 3485\n' + 'kHdrSpace = 3512\n' + 'kBitMark = 864\n' + 'kOneSpace = 2620\n' + 'kZeroSpace = 864\n' + 'kSpaceGap = 13996\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kHdrMark+kHdrSpace+01011111010111110100000001000000\n' + ' Bits: 32\n' + ' Hex: 0x5F5F4040 (MSB first)\n' + ' 0x0202FAFA (LSB first)\n' + ' Dec: 1600077888 (MSB first)\n' + ' 33749754 (LSB first)\n' + ' Bin: 0b01011111010111110100000001000000 (MSB first)\n' + ' 0b00000010000000101111101011111010 (LSB first)\n' + 'kHdrMark+kHdrSpace+01011111010111110100000001000000\n' + ' Bits: 32\n' + ' Hex: 0x5F5F4040 (MSB first)\n' + ' 0x0202FAFA (LSB first)\n' + ' Dec: 1600077888 (MSB first)\n' + ' 33749754 (LSB first)\n' + ' Bin: 0b01011111010111110100000001000000 (MSB first)\n' + ' 0b00000010000000101111101011111010 (LSB first)\n' + 'kHdrMark+kHdrSpace+GAP(13996)' + 'kHdrMark+kHdrSpace+00101111001011110110110001101100\n' + ' Bits: 32\n' + ' Hex: 0x2F2F6C6C (MSB first)\n' + ' 0x3636F4F4 (LSB first)\n' + ' Dec: 791637100 (MSB first)\n' + ' 909571316 (LSB first)\n' + ' Bin: 0b00101111001011110110110001101100 (MSB first)\n' + ' 0b00110110001101101111010011110100 (LSB first)\n' + 'kHdrMark+kHdrSpace+00101111001011110110110001101100\n' + ' Bits: 32\n' + ' Hex: 0x2F2F6C6C (MSB first)\n' + ' 0x3636F4F4 (LSB first)\n' + ' Dec: 791637100 (MSB first)\n' + ' 909571316 (LSB first)\n' + ' Bin: 0b00101111001011110110110001101100 (MSB first)\n' + ' 0b00110110001101101111010011110100 (LSB first)\n' + 'kHdrMark+kHdrSpace+GAP(13996)\n' + 'Total Nr. of suspected bits: 128\n' + '\n' + 'Generating a VERY rough code outline:\n' + '\n' + "// WARNING: This probably isn't directly usable. It's a guide only.\n" + 'const uint16_t kHdrMark = 3485;\n' + 'const uint16_t kBitMark = 864;\n' + 'const uint16_t kHdrSpace = 3512;\n' + 'const uint16_t kOneSpace = 2620;\n' + 'const uint16_t kZeroSpace = 864;\n' + 'const uint16_t kSpaceGap = 13996;\n' + 'const uint16_t kXyzBits = 128;\n' + 'const uint16_t kXyzStateLength = 16;\n' + "// DANGER: More than 64 bits detected. A uint64_t for 'data' won't" + ' work!\n' + '// Function should be safe up to 64 bits.\n' + 'void IRsend::sendXyz(const uint64_t data, const uint16_t nbits,' + ' const uint16_t repeat) {\n' + ' enableIROut(38); // A guess. Most common frequency.\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x5F5F4040, nbits = 32\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x5F5F4040, nbits = 32\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Gap\n' + ' mark(kBitMark);\n' + ' space(kSpaceGap);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x2F2F6C6C, nbits = 32\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x2F2F6C6C, nbits = 32\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Gap\n' + ' mark(kBitMark);\n' + ' space(kSpaceGap);\n' + ' space(100000); // A 100% made up guess of the gap between' + ' messages.\n' + ' }\n' + '}\n' + '\n' + '\n' + '// Alternative >64 bit Function\n' + 'void IRsend::sendXyz(uint8_t data[], uint16_t nbytes, uint16_t repeat)' + ' {\n' + ' // nbytes should typically be kXyzStateLength\n' + ' // data should typically be:\n' + ' // uint8_t data[kXyzStateLength] = {0x5F, 0x5F, 0x40, 0x40, 0x5F,' + ' 0x5F, 0x40, 0x40, 0x2F, 0x2F, 0x6C, 0x6C, 0x2F, 0x2F, 0x6C, 0x6C};\n' + ' // data[] is assumed to be in MSB order for this code.\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' sendGeneric(kHdrMark, kHdrSpace,\n' + ' kBitMark, kOneSpace,\n' + ' kBitMark, kZeroSpace,\n' + ' kBitMark,\n' + ' 100000, // 100% made-up guess at the message gap.\n' + ' data, nbytes,\n' + ' 38000, // Complete guess of the modulation' + ' frequency.\n' + ' true, 0, 50);\n' + ' }\n' + '}\n') + + def test_reduce_list(self): + """Tests for the reduce_list method.""" + + ignore = StringIO.StringIO() + message = analyse.RawIRMessage(200, [ + 7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, + 520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494, + 520, 520, 520, 494, 520, 494, 520, 494, 1482, 494 + ], ignore) + test_space_data = [4496, 1660, 530, 558, 1636, 1660, 556] + result_list, result_dict = message.reduce_list(test_space_data) + self.assertEqual([4496, 1660, 558], result_list) + self.assertEqual({ + 558: [558, 556, 530], + 1660: [1660, 1660, 1636], + 4496: [4496] + }, result_dict) + + def test_avg_list(self): + """Tests for the avg_list method.""" + + self.assertEqual(0, analyse.avg_list([])) + self.assertEqual(23, analyse.avg_list([10, 20, 40])) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp new file mode 100644 index 000000000..52ffd17b7 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp @@ -0,0 +1,109 @@ +// Quick and dirty tool to decode GlobalCache (GC) codes +// and ProntoHex codes +// Copyright 2017 Jorge Cisneros + +#include +#include +#include +#include +#include +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" + +const uint16_t kMaxGcCodeLength = 10000; + +void str_to_uint16(char *str, uint16_t *res, uint8_t base) { + char *end; + errno = 0; + intmax_t val = strtoimax(str, &end, base); + if (errno == ERANGE || val < 0 || val > UINT16_MAX || end == str || + *end != '\0') + return; + *res = (uint16_t)val; +} + +void usage_error(char *name) { + std::cerr << "Usage: " << name << " [-raw] " << std::endl + << "Usage: " << name << " -prontohex [-raw] " + << std::endl; +} + +int main(int argc, char *argv[]) { + int argv_offset = 1; + bool dumpraw = false; + bool prontohex = false; + + // Check the invocation/calling usage. + if (argc < 2 || argc > 4) { + usage_error(argv[0]); + return 1; + } + if (strncmp("-prontohex", argv[argv_offset], 10) == 0) { + prontohex = true; + argv_offset++; + } + + if (strncmp("-raw", argv[argv_offset], 4) == 0) { + dumpraw = true; + argv_offset++; + } + if (argc - argv_offset != 1) { + usage_error(argv[0]); + return 1; + } + + uint16_t gc_test[kMaxGcCodeLength]; + int index = 0; + char *pch; + char *saveptr1; + char *sep = const_cast(","); + int codebase = 10; + + if (prontohex) { + sep = const_cast(" "); + codebase = 16; + } + + pch = strtok_r(argv[argv_offset], sep, &saveptr1); + while (pch != NULL && index < kMaxGcCodeLength) { + str_to_uint16(pch, &gc_test[index], codebase); + pch = strtok_r(NULL, sep, &saveptr1); + index++; + } + + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + if (prontohex) { + irsend.sendPronto(gc_test, index); + } else { + irsend.sendGC(gc_test, index); + } + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + + std::cout << "Code length " << index << std::endl + << "Code type " << irsend.capture.decode_type << " (" + << typeToString(irsend.capture.decode_type) << ")" << std::endl + << "Code bits " << irsend.capture.bits << std::endl; + if (hasACState(irsend.capture.decode_type)) { + std::cout << "State value 0x"; + for (uint16_t i = 0; i < irsend.capture.bits / 8; i++) + printf("%02X", irsend.capture.state[i]); + std::cout << std::endl; + } else { + std::cout << "Code value 0x" << std::hex << irsend.capture.value + << std::endl + << "Code address 0x" << std::hex << irsend.capture.address + << std::endl + << "Code command 0x" << std::hex << irsend.capture.command + << std::endl; + } + + if (dumpraw || irsend.capture.decode_type == UNKNOWN) irsend.dumpRawResult(); + + return 0; +} diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords b/lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords new file mode 100644 index 000000000..a2cdccd9b --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords @@ -0,0 +1,82 @@ +#!/bin/bash +# Generate a keywords.txt for the library that is suitable for the Arduino IDE. +# Expects to run from the top directory of the library. + +# Set the locale for sorting +export LC_ALL=C + +cat << EndOfTextEndOfTextEndOfText +######################################### +# Syntax Coloring Map For IRremoteESP8266 +######################################### + +################################################ +# WARNING: Do NOT edit this file directly. +# It is generated by 'tools/mkkeywords' +# e.g. tools/mkkeywords > keywords.txt +################################################ + +####################################################### +# The Arduino IDE requires the use of a tab separator +# between the name and identifier. Without this tab the +# keyword is not highlighted. +# +# Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords +####################################################### + +####################################### +# Datatypes & Classes (KEYWORD1) +####################################### + +EndOfTextEndOfTextEndOfText + +CLASSES=$(grep "^class " src/*.h | cut -d' ' -f2 | sort -u) +# Manually add typedefs as they are hard to parse out. +CLASSES="${CLASSES} ir_params_t match_result_t" +for i in ${CLASSES}; do + echo -e "${i}\tKEYWORD1" +done | sort -du + +cat << EndOfTextEndOfTextEndOfText + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +EndOfTextEndOfTextEndOfText + +METHODS=$(egrep "^(u?int|void|bool|String|static|match_result_t).*\(" src/*.cpp| + cut -d' ' -f2- | sed 's/^.*:://' | cut -d'(' -f1 | sort -u | + grep -v ICACHE_RAM_ATTR) +for i in ${METHODS}; do + echo -e "${i}\tKEYWORD2" +done | sort -u + +cat << EndOfTextEndOfTextEndOfText + +####################################### +# Constants (LITERAL1) +####################################### + +EndOfTextEndOfTextEndOfText +LITERALS=$(grep "^#define [A-Z]" src/*.cpp src/*.h | + while read ignore define ignore; do + echo ${define}; + done | sort -u | + grep -v [\(\)] | grep -v ^_ | grep -v _\$ | grep -v VIRTUAL) +CONSTS=$(grep "^const " src/*.cpp src/*.h | + sed 's/\[.*\] =.*//;s/ =.*//;s/^.* k/k/') +ENUMS=$(cat src/*.h | while read a b; do + if [[ ${a} == "};" ]]; then + ENUM=0; + fi; + if [[ ${ENUM} -eq 1 ]]; then + echo $a | sed 's/,//g'; + fi; + if [[ ${a} == "enum" ]]; then + ENUM=1; + fi; + done) +for i in ${LITERALS} ${CONSTS} ${ENUMS}; do + echo -e "${i}\tLITERAL1" +done | sort -u diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp b/lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp new file mode 100644 index 000000000..63dfa6221 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp @@ -0,0 +1,122 @@ +// Quick and dirty tool to decode mode2 data from LIRC +// Copyright 2018 Brett T. Warden +// based on c2_decode.cpp, Copyright 2017 Jorge Cisneros + +// Usage example: +// mode2 -H udp -d 5000 | ./mode2_decode + +/* Sample input (alternating space and pulse durations in microseconds): +space 500000 +pulse 915 +space 793 +pulse 488 +space 366 +pulse 915 +space 793 +pulse 427 +space 500000 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" + +const uint16_t kMaxGcCodeLength = 10000; + +void str_to_uint16(char *str, uint16_t *res, uint8_t base) { + char *end; + errno = 0; + intmax_t val = strtoimax(str, &end, base); + if (errno == ERANGE || val < 0 || val > UINT16_MAX || end == str || + *end != '\0') + return; + *res = (uint16_t)val; +} + +void usage_error(char *name) { + std::cerr << "Usage: " << name << " [-raw]" << std::endl; +} + +int main(int argc, char *argv[]) { + bool dumpraw = false; + + // Check the invocation/calling usage. + if (argc > 2) { + usage_error(argv[0]); + return 1; + } + + if (argc == 2 && strncmp("-raw", argv[1], 4) == 0) { + dumpraw = true; + } + + int index = 0; + std::string line, type; + std::string pulse = "pulse"; + std::string space = "space"; + int duration; + + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + while (getline(std::cin, line)) { + std::istringstream iss1(line); + iss1 >> type; + iss1 >> duration; + + // Clamp duration to int16_t + if (duration > 0xFFFF) { + duration = 0xFFFF; + } + if (pulse.compare(type) == 0) { + irsend.mark(duration); + } else if (space.compare(type) == 0) { + irsend.space(duration); + } + index++; + + if (duration > 20000 || index >= kMaxGcCodeLength) { + // Skip long spaces at beginning + if (index > 1) { + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + + std::cout << "Code length " << index << std::endl + << "Code type " << irsend.capture.decode_type << " (" + << typeToString(irsend.capture.decode_type) << ")" + << std::endl + << "Code bits " << irsend.capture.bits << std::endl; + if (hasACState(irsend.capture.decode_type)) { + std::cout << "State value 0x"; + for (uint16_t i = 0; i < irsend.capture.bits / 8; i++) + printf("%02X", irsend.capture.state[i]); + std::cout << std::endl; + } else { + std::cout << "Code value 0x" << std::hex << irsend.capture.value + << std::endl + << "Code address 0x" << std::hex << irsend.capture.address + << std::endl + << "Code command 0x" << std::hex << irsend.capture.command + << std::endl; + } + + if (dumpraw || irsend.capture.decode_type == UNKNOWN) + irsend.dumpRawResult(); + } + + irsend.reset(); + index = 0; + } + } + + return 0; +} diff --git a/lib/NewPing-1.9.1/README.md b/lib/NewPing-1.9.1/README.md new file mode 100644 index 000000000..8760c35ff --- /dev/null +++ b/lib/NewPing-1.9.1/README.md @@ -0,0 +1,3 @@ +# NewPing Arduino Library for Arduino + +## See the [NewPing Wiki](https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home) for documentation \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde b/lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde new file mode 100644 index 000000000..a42c792b8 --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde @@ -0,0 +1,78 @@ +// --------------------------------------------------------------------------- +// Before attempting to use this sketch, please read the "Help with 15 Sensors Example Sketch": +// https://bitbucket.org/teckel12/arduino-new-ping/wiki/Help%20with%2015%20Sensors%20Example%20Sketch +// +// This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust +// the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the +// "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor +// is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results +// are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project +// would normally process the sensor results in this function (for example, decide if a robot needs to +// turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs +// to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other +// processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind. +// --------------------------------------------------------------------------- +#include + +#define SONAR_NUM 15 // Number of sensors. +#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. +#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). + +unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor. +unsigned int cm[SONAR_NUM]; // Where the ping distances are stored. +uint8_t currentSensor = 0; // Keeps track of which sensor is active. + +NewPing sonar[SONAR_NUM] = { // Sensor object array. + NewPing(41, 42, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. + NewPing(43, 44, MAX_DISTANCE), + NewPing(45, 20, MAX_DISTANCE), + NewPing(21, 22, MAX_DISTANCE), + NewPing(23, 24, MAX_DISTANCE), + NewPing(25, 26, MAX_DISTANCE), + NewPing(27, 28, MAX_DISTANCE), + NewPing(29, 30, MAX_DISTANCE), + NewPing(31, 32, MAX_DISTANCE), + NewPing(34, 33, MAX_DISTANCE), + NewPing(35, 36, MAX_DISTANCE), + NewPing(37, 38, MAX_DISTANCE), + NewPing(39, 40, MAX_DISTANCE), + NewPing(50, 51, MAX_DISTANCE), + NewPing(52, 53, MAX_DISTANCE) +}; + +void setup() { + Serial.begin(115200); + pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting. + for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor. + pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL; +} + +void loop() { + for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors. + if (millis() >= pingTimer[i]) { // Is it this sensor's time to ping? + pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Set next time this sensor will be pinged. + if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results. + sonar[currentSensor].timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance). + currentSensor = i; // Sensor being accessed. + cm[currentSensor] = 0; // Make distance zero in case there's no ping echo for this sensor. + sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo). + } + } + // Other code that *DOESN'T* analyze ping results can go here. +} + +void echoCheck() { // If ping received, set the sensor distance to array. + if (sonar[currentSensor].check_timer()) + cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM; +} + +void oneSensorCycle() { // Sensor ping cycle complete, do something with the results. + // The following code would be replaced with your code that does something with the ping results. + for (uint8_t i = 0; i < SONAR_NUM; i++) { + Serial.print(i); + Serial.print("="); + Serial.print(cm[i]); + Serial.print("cm "); + } + Serial.println(); +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde b/lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde new file mode 100644 index 000000000..061d7f3ee --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde @@ -0,0 +1,29 @@ +// --------------------------------------------------------------------------- +// Example NewPing library sketch that pings 3 sensors 20 times a second. +// --------------------------------------------------------------------------- + +#include + +#define SONAR_NUM 3 // Number of sensors. +#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. + +NewPing sonar[SONAR_NUM] = { // Sensor object array. + NewPing(4, 5, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. + NewPing(6, 7, MAX_DISTANCE), + NewPing(8, 9, MAX_DISTANCE) +}; + +void setup() { + Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. +} + +void loop() { + for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through each sensor and display results. + delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings. + Serial.print(i); + Serial.print("="); + Serial.print(sonar[i].ping_cm()); + Serial.print("cm "); + } + Serial.println(); +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde b/lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde new file mode 100644 index 000000000..d9d26673e --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde @@ -0,0 +1,46 @@ +// --------------------------------------------------------------------------- +// This example shows how to use NewPing's ping_timer method which uses the Timer2 interrupt to get the +// ping time. The advantage of using this method over the standard ping method is that it permits a more +// event-driven sketch which allows you to appear to do two things at once. An example would be to ping +// an ultrasonic sensor for a possible collision while at the same time navigating. This allows a +// properly developed sketch to multitask. Be aware that because the ping_timer method uses Timer2, +// other features or libraries that also use Timer2 would be effected. For example, the PWM function on +// pins 3 & 11 on Arduino Uno (pins 9 and 11 on Arduino Mega) and the Tone library. Note, only the PWM +// functionality of the pins is lost (as they use Timer2 to do PWM), the pins are still available to use. +// NOTE: For Teensy/Leonardo (ATmega32U4) the library uses Timer4 instead of Timer2. +// --------------------------------------------------------------------------- +#include + +#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on ping sensor. +#define ECHO_PIN 11 // Arduino pin tied to echo pin on ping sensor. +#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. + +unsigned int pingSpeed = 50; // How frequently are we going to send out a ping (in milliseconds). 50ms would be 20 times a second. +unsigned long pingTimer; // Holds the next ping time. + +void setup() { + Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. + pingTimer = millis(); // Start now. +} + +void loop() { + // Notice how there's no delays in this sketch to allow you to do other processing in-line while doing distance pings. + if (millis() >= pingTimer) { // pingSpeed milliseconds since last ping, do another ping. + pingTimer += pingSpeed; // Set the next ping time. + sonar.ping_timer(echoCheck); // Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status. + } + // Do other stuff here, really. Think of it as multi-tasking. +} + +void echoCheck() { // Timer2 interrupt calls this function every 24uS where you can check the ping status. + // Don't do anything here! + if (sonar.check_timer()) { // This is how you check to see if the ping was received. + // Here's where you can add code. + Serial.print("Ping: "); + Serial.print(sonar.ping_result / US_ROUNDTRIP_CM); // Ping returned, uS result in ping_result, convert to cm with US_ROUNDTRIP_CM. + Serial.println("cm"); + } + // Don't do anything here! +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde b/lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde new file mode 100644 index 000000000..12f6fdaaf --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde @@ -0,0 +1,22 @@ +// --------------------------------------------------------------------------- +// Example NewPing library sketch that does a ping about 20 times per second. +// --------------------------------------------------------------------------- + +#include + +#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor. +#define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor. +#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. + +void setup() { + Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. +} + +void loop() { + delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings. + Serial.print("Ping: "); + Serial.print(sonar.ping_cm()); // Send ping, get distance in cm and print result (0 = outside set distance range) + Serial.println("cm"); +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde b/lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde new file mode 100644 index 000000000..5908f5858 --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde @@ -0,0 +1,60 @@ +// --------------------------------------------------------------------------- +// Calculate a ping median using the ping_timer() method. +// --------------------------------------------------------------------------- + +#include + +#define ITERATIONS 5 // Number of iterations. +#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on ping sensor. +#define ECHO_PIN 11 // Arduino pin tied to echo pin on ping sensor. +#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. +#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). + +unsigned long pingTimer[ITERATIONS]; // Holds the times when the next ping should happen for each iteration. +unsigned int cm[ITERATIONS]; // Where the ping distances are stored. +uint8_t currentIteration = 0; // Keeps track of iteration step. + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. + +void setup() { + Serial.begin(115200); + pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting. + for (uint8_t i = 1; i < ITERATIONS; i++) // Set the starting time for each iteration. + pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL; +} + +void loop() { + for (uint8_t i = 0; i < ITERATIONS; i++) { // Loop through all the iterations. + if (millis() >= pingTimer[i]) { // Is it this iteration's time to ping? + pingTimer[i] += PING_INTERVAL * ITERATIONS; // Set next time this sensor will be pinged. + if (i == 0 && currentIteration == ITERATIONS - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results. + sonar.timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance). + currentIteration = i; // Sensor being accessed. + cm[currentIteration] = 0; // Make distance zero in case there's no ping echo for this iteration. + sonar.ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo). + } + } + // Other code that *DOESN'T* analyze ping results can go here. +} + +void echoCheck() { // If ping received, set the sensor distance to array. + if (sonar.check_timer()) + cm[currentIteration] = sonar.ping_result / US_ROUNDTRIP_CM; +} + +void oneSensorCycle() { // All iterations complete, calculate the median. + unsigned int uS[ITERATIONS]; + uint8_t j, it = ITERATIONS; + uS[0] = NO_ECHO; + for (uint8_t i = 0; i < it; i++) { // Loop through iteration results. + if (cm[i] != NO_ECHO) { // Ping in range, include as part of median. + if (i > 0) { // Don't start sort till second ping. + for (j = i; j > 0 && uS[j - 1] < cm[i]; j--) // Insertion sort loop. + uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion. + } else j = 0; // First ping is sort starting point. + uS[j] = cm[i]; // Add last ping to array in sorted position. + } else it--; // Ping out of range, skip and don't include as part of median. + } + Serial.print(uS[it >> 1]); + Serial.println("cm"); +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde b/lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde new file mode 100644 index 000000000..35e1db227 --- /dev/null +++ b/lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde @@ -0,0 +1,25 @@ +// --------------------------------------------------------------------------- +// While the NewPing library's primary goal is to interface with ultrasonic sensors, interfacing with +// the Timer2 interrupt was a result of creating an interrupt-based ping method. Since these Timer2 +// interrupt methods were built, the library may as well provide the functionality to use these methods +// in your sketches. This shows how simple it is (no ultrasonic sensor required). Keep in mind that +// these methods use Timer2, as does NewPing's ping_timer method for using ultrasonic sensors. You +// can't use ping_timer at the same time you're using timer_ms or timer_us as all use the same timer. +// --------------------------------------------------------------------------- + +#include + +#define LED_PIN 13 // Pin with LED attached. + +void setup() { + pinMode(LED_PIN, OUTPUT); + NewPing::timer_ms(500, toggleLED); // Create a Timer2 interrupt that calls toggleLED in your sketch once every 500 milliseconds. +} + +void loop() { + // Do anything here, the Timer2 interrupt will take care of the flashing LED without your intervention. +} + +void toggleLED() { + digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle the LED. +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/keywords.txt b/lib/NewPing-1.9.1/keywords.txt new file mode 100644 index 000000000..0487ff26d --- /dev/null +++ b/lib/NewPing-1.9.1/keywords.txt @@ -0,0 +1,31 @@ +################################### +# Syntax Coloring Map For NewPing +################################### + +################################### +# Datatypes (KEYWORD1) +################################### + +NewPing KEYWORD1 + +################################### +# Methods and Functions (KEYWORD2) +################################### + +ping KEYWORD2 +ping_in KEYWORD2 +ping_cm KEYWORD2 +ping_median KEYWORD2 +ping_timer KEYWORD2 +check_timer KEYWORD2 +ping_result KEYWORD2 +timer_us KEYWORD2 +timer_ms KEYWORD2 +timer_stop KEYWORD2 +convert_in KEYWORD2 +convert_cm KEYWORD2 + +################################### +# Constants (LITERAL1) +################################### + diff --git a/lib/NewPing-1.9.1/library.properties b/lib/NewPing-1.9.1/library.properties new file mode 100644 index 000000000..c825146d9 --- /dev/null +++ b/lib/NewPing-1.9.1/library.properties @@ -0,0 +1,10 @@ +name=NewPing +version=1.9.1 +author=Tim Eckel +maintainer=Tim Eckel +sentence=A library that makes working with ultrasonic sensors easy. +paragraph=When I first received an ultrasonic sensor I was not happy with how poorly it performed. I soon realized the problem was not the sensor, it was the available ping and ultrasonic libraries causing the problem. The NewPing library totally fixes these problems, adds many new features, and breathes new life into these very affordable distance sensors. +category=Sensors +url=https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home +architectures=avr,arm,esp8266 +includes=NewPing.h diff --git a/lib/NewPing-1.9.1/src/NewPing.cpp b/lib/NewPing-1.9.1/src/NewPing.cpp new file mode 100644 index 000000000..05c8af4c6 --- /dev/null +++ b/lib/NewPing-1.9.1/src/NewPing.cpp @@ -0,0 +1,365 @@ +// --------------------------------------------------------------------------- +// Created by Tim Eckel - teckel@leethost.com +// +// See NewPing.h for license, purpose, syntax, version history, links, etc. +// --------------------------------------------------------------------------- + +#include "NewPing.h" + + +// --------------------------------------------------------------------------- +// NewPing constructor +// --------------------------------------------------------------------------- + +NewPing::NewPing(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance) { +#if DO_BITWISE == true + _triggerBit = digitalPinToBitMask(trigger_pin); // Get the port register bitmask for the trigger pin. + _echoBit = digitalPinToBitMask(echo_pin); // Get the port register bitmask for the echo pin. + + _triggerOutput = portOutputRegister(digitalPinToPort(trigger_pin)); // Get the output port register for the trigger pin. + _echoInput = portInputRegister(digitalPinToPort(echo_pin)); // Get the input port register for the echo pin. + + _triggerMode = (uint8_t *) portModeRegister(digitalPinToPort(trigger_pin)); // Get the port mode register for the trigger pin. +#else + _triggerPin = trigger_pin; + _echoPin = echo_pin; +#endif + + set_max_distance(max_cm_distance); // Call function to set the max sensor distance. + +#if (defined (__arm__) && (defined (TEENSYDUINO) || defined(PARTICLE))) || DO_BITWISE != true + pinMode(echo_pin, INPUT); // Set echo pin to input (on Teensy 3.x (ARM), pins default to disabled, at least one pinMode() is needed for GPIO mode). + pinMode(trigger_pin, OUTPUT); // Set trigger pin to output (on Teensy 3.x (ARM), pins default to disabled, at least one pinMode() is needed for GPIO mode). +#endif + +#if defined (ARDUINO_AVR_YUN) + pinMode(echo_pin, INPUT); // Set echo pin to input for the Arduino Yun, not sure why it doesn't default this way. +#endif + +#if ONE_PIN_ENABLED != true && DO_BITWISE == true + *_triggerMode |= _triggerBit; // Set trigger pin to output. +#endif +} + + +// --------------------------------------------------------------------------- +// Standard ping methods +// --------------------------------------------------------------------------- + +unsigned int NewPing::ping(unsigned int max_cm_distance) { + if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance. + + if (!ping_trigger()) return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function. + +#if URM37_ENABLED == true + #if DO_BITWISE == true + while (!(*_echoInput & _echoBit)) // Wait for the ping echo. + #else + while (!digitalRead(_echoPin)) // Wait for the ping echo. + #endif + if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. +#else + #if DO_BITWISE == true + while (*_echoInput & _echoBit) // Wait for the ping echo. + #else + while (digitalRead(_echoPin)) // Wait for the ping echo. + #endif + if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. +#endif + + return (micros() - (_max_time - _maxEchoTime) - PING_OVERHEAD); // Calculate ping time, include overhead. +} + + +unsigned long NewPing::ping_cm(unsigned int max_cm_distance) { + unsigned long echoTime = NewPing::ping(max_cm_distance); // Calls the ping method and returns with the ping echo distance in uS. +#if ROUNDING_ENABLED == false + return (echoTime / US_ROUNDTRIP_CM); // Call the ping method and returns the distance in centimeters (no rounding). +#else + return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters. +#endif +} + + +unsigned long NewPing::ping_in(unsigned int max_cm_distance) { + unsigned long echoTime = NewPing::ping(max_cm_distance); // Calls the ping method and returns with the ping echo distance in uS. +#if ROUNDING_ENABLED == false + return (echoTime / US_ROUNDTRIP_IN); // Call the ping method and returns the distance in inches (no rounding). +#else + return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches. +#endif +} + + +unsigned long NewPing::ping_median(uint8_t it, unsigned int max_cm_distance) { + unsigned int uS[it], last; + uint8_t j, i = 0; + unsigned long t; + uS[0] = NO_ECHO; + + while (i < it) { + t = micros(); // Start ping timestamp. + last = ping(max_cm_distance); // Send ping. + + if (last != NO_ECHO) { // Ping in range, include as part of median. + if (i > 0) { // Don't start sort till second ping. + for (j = i; j > 0 && uS[j - 1] < last; j--) // Insertion sort loop. + uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion. + } else j = 0; // First ping is sort starting point. + uS[j] = last; // Add last ping to array in sorted position. + i++; // Move to next ping. + } else it--; // Ping out of range, skip and don't include as part of median. + + if (i < it && micros() - t < PING_MEDIAN_DELAY) + delay((PING_MEDIAN_DELAY + t - micros()) / 1000); // Millisecond delay between pings. + + } + return (uS[it >> 1]); // Return the ping distance median. +} + + +// --------------------------------------------------------------------------- +// Standard and timer interrupt ping method support functions (not called directly) +// --------------------------------------------------------------------------- + +boolean NewPing::ping_trigger() { +#if DO_BITWISE == true + #if ONE_PIN_ENABLED == true + *_triggerMode |= _triggerBit; // Set trigger pin to output. + #endif + + *_triggerOutput &= ~_triggerBit; // Set the trigger pin low, should already be low, but this will make sure it is. + delayMicroseconds(4); // Wait for pin to go low. + *_triggerOutput |= _triggerBit; // Set trigger pin high, this tells the sensor to send out a ping. + delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS. + *_triggerOutput &= ~_triggerBit; // Set trigger pin back to low. + + #if ONE_PIN_ENABLED == true + *_triggerMode &= ~_triggerBit; // Set trigger pin to input (when using one Arduino pin, this is technically setting the echo pin to input as both are tied to the same Arduino pin). + #endif + + #if URM37_ENABLED == true + if (!(*_echoInput & _echoBit)) return false; // Previous ping hasn't finished, abort. + _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) + while (*_echoInput & _echoBit) // Wait for ping to start. + if (micros() > _max_time) return false; // Took too long to start, abort. + #else + if (*_echoInput & _echoBit) return false; // Previous ping hasn't finished, abort. + _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) + while (!(*_echoInput & _echoBit)) // Wait for ping to start. + if (micros() > _max_time) return false; // Took too long to start, abort. + #endif +#else + #if ONE_PIN_ENABLED == true + pinMode(_triggerPin, OUTPUT); // Set trigger pin to output. + #endif + + digitalWrite(_triggerPin, LOW); // Set the trigger pin low, should already be low, but this will make sure it is. + delayMicroseconds(4); // Wait for pin to go low. + digitalWrite(_triggerPin, HIGH); // Set trigger pin high, this tells the sensor to send out a ping. + delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS. + digitalWrite(_triggerPin, LOW); // Set trigger pin back to low. + + #if ONE_PIN_ENABLED == true + pinMode(_triggerPin, INPUT); // Set trigger pin to input (when using one Arduino pin, this is technically setting the echo pin to input as both are tied to the same Arduino pin). + #endif + + #if URM37_ENABLED == true + if (!digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort. + _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) + while (digitalRead(_echoPin)) // Wait for ping to start. + if (micros() > _max_time) return false; // Took too long to start, abort. + #else + if (digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort. + _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) + while (!digitalRead(_echoPin)) // Wait for ping to start. + if (micros() > _max_time) return false; // Took too long to start, abort. + #endif +#endif + + _max_time = micros() + _maxEchoTime; // Ping started, set the time-out. + return true; // Ping started successfully. +} + + +void NewPing::set_max_distance(unsigned int max_cm_distance) { +#if ROUNDING_ENABLED == false + _maxEchoTime = min(max_cm_distance + 1, (unsigned int) MAX_SENSOR_DISTANCE + 1) * US_ROUNDTRIP_CM; // Calculate the maximum distance in uS (no rounding). +#else + _maxEchoTime = min(max_cm_distance, (unsigned int) MAX_SENSOR_DISTANCE) * US_ROUNDTRIP_CM + (US_ROUNDTRIP_CM / 2); // Calculate the maximum distance in uS. +#endif +} + + +#if TIMER_ENABLED == true && DO_BITWISE == true + + // --------------------------------------------------------------------------- + // Timer interrupt ping methods (won't work with ATmega128, ATtiny and most non-AVR microcontrollers) + // --------------------------------------------------------------------------- + + void NewPing::ping_timer(void (*userFunc)(void), unsigned int max_cm_distance) { + if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance. + + if (!ping_trigger()) return; // Trigger a ping, if it returns false, return without starting the echo timer. + timer_us(ECHO_TIMER_FREQ, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS. + } + + + boolean NewPing::check_timer() { + if (micros() > _max_time) { // Outside the time-out limit. + timer_stop(); // Disable timer interrupt + return false; // Cancel ping timer. + } + + #if URM37_ENABLED == false + if (!(*_echoInput & _echoBit)) { // Ping echo received. + #else + if (*_echoInput & _echoBit) { // Ping echo received. + #endif + timer_stop(); // Disable timer interrupt + ping_result = (micros() - (_max_time - _maxEchoTime) - PING_TIMER_OVERHEAD); // Calculate ping time including overhead. + return true; // Return ping echo true. + } + + return false; // Return false because there's no ping echo yet. + } + + + // --------------------------------------------------------------------------- + // Timer2/Timer4 interrupt methods (can be used for non-ultrasonic needs) + // --------------------------------------------------------------------------- + + // Variables used for timer functions + void (*intFunc)(); + void (*intFunc2)(); + unsigned long _ms_cnt_reset; + volatile unsigned long _ms_cnt; + #if defined(__arm__) && (defined (TEENSYDUINO) || defined(PARTICLE)) + IntervalTimer itimer; + #endif + + + void NewPing::timer_us(unsigned int frequency, void (*userFunc)(void)) { + intFunc = userFunc; // User's function to call when there's a timer event. + timer_setup(); // Configure the timer interrupt. + + #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo). + OCR4C = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. + TIMSK4 = (1<>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. + TIMSK2 |= (1<= 100 + #include + #else + #include + #if defined (PARTICLE) + #include + #else + #include + #endif + #endif + + #if defined (__AVR__) + #include + #include + #endif + + // Shouldn't need to change these values unless you have a specific need to do so. + #define MAX_SENSOR_DISTANCE 500 // Maximum sensor distance can be as high as 500cm, no reason to wait for ping longer than sound takes to travel this distance and back. Default=500 + #define US_ROUNDTRIP_CM 57 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space. Default=57 + #define US_ROUNDTRIP_IN 146 // Microseconds (uS) it takes sound to travel round-trip 1 inch (2 inches total), uses integer to save compiled code space. Defalult=146 + #define ONE_PIN_ENABLED true // Set to "false" to disable one pin mode which saves around 14-26 bytes of binary size. Default=true + #define ROUNDING_ENABLED false // Set to "true" to enable distance rounding which also adds 64 bytes to binary size. Default=false + #define URM37_ENABLED false // Set to "true" to enable support for the URM37 sensor in PWM mode. Default=false + #define TIMER_ENABLED true // Set to "false" to disable the timer ISR (if getting "__vector_7" compile errors set this to false). Default=true + + // Probably shouldn't change these values unless you really know what you're doing. + #define NO_ECHO 0 // Value returned if there's no ping echo within the specified MAX_SENSOR_DISTANCE or max_cm_distance. Default=0 + #define MAX_SENSOR_DELAY 5800 // Maximum uS it takes for sensor to start the ping. Default=5800 + #define ECHO_TIMER_FREQ 24 // Frequency to check for a ping echo (every 24uS is about 0.4cm accuracy). Default=24 + #define PING_MEDIAN_DELAY 29000 // Microsecond delay between pings in the ping_median method. Default=29000 + #define PING_OVERHEAD 5 // Ping overhead in microseconds (uS). Default=5 + #define PING_TIMER_OVERHEAD 13 // Ping timer overhead in microseconds (uS). Default=13 + #if URM37_ENABLED == true + #undef US_ROUNDTRIP_CM + #undef US_ROUNDTRIP_IN + #define US_ROUNDTRIP_CM 50 // Every 50uS PWM signal is low indicates 1cm distance. Default=50 + #define US_ROUNDTRIP_IN 127 // If 50uS is 1cm, 1 inch would be 127uS (50 x 2.54 = 127). Default=127 + #endif + + // Conversion from uS to distance (round result to nearest cm or inch). + #define NewPingConvert(echoTime, conversionFactor) (max(((unsigned int)echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0))) + + // Detect non-AVR microcontrollers (Teensy 3.x, Arduino DUE, etc.) and don't use port registers or timer interrupts as required. + #if (defined (__arm__) && (defined (TEENSYDUINO) || defined (PARTICLE))) + #undef PING_OVERHEAD + #define PING_OVERHEAD 1 + #undef PING_TIMER_OVERHEAD + #define PING_TIMER_OVERHEAD 1 + #define DO_BITWISE true + #elif !defined (__AVR__) + #undef PING_OVERHEAD + #define PING_OVERHEAD 1 + #undef PING_TIMER_OVERHEAD + #define PING_TIMER_OVERHEAD 1 + #undef TIMER_ENABLED + #define TIMER_ENABLED false + #define DO_BITWISE false + #else + #define DO_BITWISE true + #endif + + // Disable the timer interrupts when using ATmega128 and all ATtiny microcontrollers. + #if defined (__AVR_ATmega128__) || defined (__AVR_ATtiny24__) || defined (__AVR_ATtiny44__) || defined (__AVR_ATtiny441__) || defined (__AVR_ATtiny84__) || defined (__AVR_ATtiny841__) || defined (__AVR_ATtiny25__) || defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) || defined (__AVR_ATtiny261__) || defined (__AVR_ATtiny461__) || defined (__AVR_ATtiny861__) || defined (__AVR_ATtiny43U__) + #undef TIMER_ENABLED + #define TIMER_ENABLED false + #endif + + // Define timers when using ATmega8, ATmega16, ATmega32 and ATmega8535 microcontrollers. + #if defined (__AVR_ATmega8__) || defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega8535__) + #define OCR2A OCR2 + #define TIMSK2 TIMSK + #define OCIE2A OCIE2 + #endif + + class NewPing { + public: + NewPing(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance = MAX_SENSOR_DISTANCE); + unsigned int ping(unsigned int max_cm_distance = 0); + unsigned long ping_cm(unsigned int max_cm_distance = 0); + unsigned long ping_in(unsigned int max_cm_distance = 0); + unsigned long ping_median(uint8_t it = 5, unsigned int max_cm_distance = 0); + static unsigned int convert_cm(unsigned int echoTime); + static unsigned int convert_in(unsigned int echoTime); + #if TIMER_ENABLED == true + void ping_timer(void (*userFunc)(void), unsigned int max_cm_distance = 0); + boolean check_timer(); + unsigned long ping_result; + static void timer_us(unsigned int frequency, void (*userFunc)(void)); + static void timer_ms(unsigned long frequency, void (*userFunc)(void)); + static void timer_stop(); + #endif + private: + boolean ping_trigger(); + void set_max_distance(unsigned int max_cm_distance); + #if TIMER_ENABLED == true + boolean ping_trigger_timer(unsigned int trigger_delay); + boolean ping_wait_timer(); + static void timer_setup(); + static void timer_ms_cntdwn(); + #endif + #if DO_BITWISE == true + uint8_t _triggerBit; + uint8_t _echoBit; + #if defined(PARTICLE) + #if !defined(portModeRegister) + #if defined (STM32F10X_MD) + #define portModeRegister(port) ( &(port->CRL) ) + #elif defined (STM32F2XX) + #define portModeRegister(port) ( &(port->MODER) ) + #endif + #endif + volatile uint32_t *_triggerOutput; + volatile uint32_t *_echoInput; + volatile uint32_t *_triggerMode; + #else + volatile uint8_t *_triggerOutput; + volatile uint8_t *_echoInput; + volatile uint8_t *_triggerMode; + #endif + #else + uint8_t _triggerPin; + uint8_t _echoPin; + #endif + unsigned int _maxEchoTime; + unsigned long _max_time; + }; + + +#endif diff --git a/lib/TasmotaSerial-2.1.0/README.md b/lib/TasmotaSerial-2.2.0/README.md similarity index 100% rename from lib/TasmotaSerial-2.1.0/README.md rename to lib/TasmotaSerial-2.2.0/README.md diff --git a/lib/TasmotaSerial-2.1.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-2.2.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-2.1.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-2.2.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-2.1.0/keywords.txt b/lib/TasmotaSerial-2.2.0/keywords.txt similarity index 100% rename from lib/TasmotaSerial-2.1.0/keywords.txt rename to lib/TasmotaSerial-2.2.0/keywords.txt diff --git a/lib/TasmotaSerial-2.1.0/library.json b/lib/TasmotaSerial-2.2.0/library.json similarity index 94% rename from lib/TasmotaSerial-2.1.0/library.json rename to lib/TasmotaSerial-2.2.0/library.json index 59d06ad5f..23a2ddab9 100644 --- a/lib/TasmotaSerial-2.1.0/library.json +++ b/lib/TasmotaSerial-2.2.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaSerial", - "version": "2.1.0", + "version": "2.2.0", "keywords": [ "serial", "io", "TasmotaSerial" ], diff --git a/lib/TasmotaSerial-2.1.0/library.properties b/lib/TasmotaSerial-2.2.0/library.properties similarity index 94% rename from lib/TasmotaSerial-2.1.0/library.properties rename to lib/TasmotaSerial-2.2.0/library.properties index 93f4a1d39..54c79e218 100644 --- a/lib/TasmotaSerial-2.1.0/library.properties +++ b/lib/TasmotaSerial-2.2.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaSerial -version=2.1.0 +version=2.2.0 author=Theo Arends maintainer=Theo Arends sentence=Implementation of software serial with hardware serial fallback for ESP8266. diff --git a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp similarity index 95% rename from lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp index d9fc29e6f..3df42f834 100644 --- a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp @@ -76,10 +76,11 @@ static void (*ISRList[16])() = { tms_isr_15 }; -TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fallback) +TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback) { m_valid = false; m_hardserial = 0; + m_hardswap = 0; m_stop_bits = 1; if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) { return; @@ -87,9 +88,14 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa m_rx_pin = receive_pin; m_tx_pin = transmit_pin; m_in_pos = m_out_pos = 0; - if (hardware_fallback && (((1 == m_rx_pin) && (3 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { + if (hardware_fallback && (((3 == m_rx_pin) && (1 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { m_hardserial = 1; - } else { + } + else if ((2 == hardware_fallback) && (((13 == m_rx_pin) && (15 == m_tx_pin)) || ((13 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (15 == m_tx_pin)))) { + m_hardserial = 1; + m_hardswap = 1; + } + else { if (m_rx_pin > -1) { m_buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE); if (m_buffer == NULL) return; @@ -134,6 +140,9 @@ bool TasmotaSerial::begin(long speed, int stop_bits) { } else { Serial.begin(speed, SERIAL_8N1); } + if (m_hardswap) { + Serial.swap(); + } } else { // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed; diff --git a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h similarity index 95% rename from lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h index e40c34ee8..de991526a 100644 --- a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h +++ b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h @@ -38,7 +38,7 @@ class TasmotaSerial : public Stream { public: - TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fallback = false); + TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback = 0); virtual ~TasmotaSerial(); bool begin(long speed, int stop_bits = 1); @@ -62,6 +62,7 @@ class TasmotaSerial : public Stream { // Member variables bool m_valid; bool m_hardserial; + bool m_hardswap; bool m_high_speed; int m_rx_pin; int m_tx_pin; diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/.gitignore b/lib/esp-epaper-29-ws-20171230-gemu-1.0/.gitignore new file mode 100644 index 000000000..fa4850d8f --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/.gitignore @@ -0,0 +1,12 @@ +sdkconfig* +.cproject +.project +.settings/* +build/* +doxygen_sqlite3.db +docs/_build +docs/man +docs/xml +docs/doxygen-warning-log.txt +docs/sphinx-warning-log.txt +*.pyc diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/.travis.yml b/lib/esp-epaper-29-ws-20171230-gemu-1.0/.travis.yml new file mode 100644 index 000000000..08c8c109e --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/.travis.yml @@ -0,0 +1,43 @@ +sudo: false +language: bash +os: + - linux + +addons: + apt: + packages: + - gperf + - python + - python-serial + +before_install: + # Save path to the git respository + - PROJECT_PATH=$(pwd) + +install: + # Install ESP32 toochain following steps as desribed + # in http://esp-idf.readthedocs.io/en/latest/linux-setup.html + # + # Get required packages - already done above, see addons: apt: packages: + # - sudo apt-get install git wget make libncurses-dev flex bison gperf python python-serial + # Prepare directory for the toolchain + - mkdir -p ~/esp + - cd ~/esp + - XTENSA_DIST=xtensa-esp32-elf-linux64-1.22.0-75-gbaf03c2-5.2.0.tar.gz + # Download binary toolchain for the ESP32 + - wget https://dl.espressif.com/dl/$XTENSA_DIST + - tar -xzf $XTENSA_DIST + # Make xtensa-esp32-elf available for all terminal sessions + - export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin + # Get ESP-IDF from github + - git clone --recursive https://github.com/espressif/esp-idf.git + # Set the path to ESP-IDF directory + - export IDF_PATH=~/esp/esp-idf + +script: + # Go back to the git repository + - cd $PROJECT_PATH + # Update configuration so that kconfig doesn't start interactive mode + - make defconfig + # Build project from the git repository + - make diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/Arduino/epd2in9-demo/epd2in9-demo.ino b/lib/esp-epaper-29-ws-20171230-gemu-1.0/Arduino/epd2in9-demo/epd2in9-demo.ino new file mode 100644 index 000000000..a407cb818 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/Arduino/epd2in9-demo/epd2in9-demo.ino @@ -0,0 +1,82 @@ +/** + * @filename : epd2in9-demo.ino + * @brief : 2.9inch e-paper display demo + * @author : Yehui from Waveshare + * + * Copyright (C) Waveshare September 9 2017 + * + * @author : Updated by krzychb@gazeta,pl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documnetation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include "imagedata.h" + +#define COLORED 0 +#define UNCOLORED 1 + +unsigned char image[4736]; +Paint paint(image, 0, 0); // width should be the multiple of 8 +Epd epd; + +void setup() { + Serial.begin(115200); + Serial.println("Starting..."); + if (epd.Init(lut_full_update) != 0) { + Serial.println("e-Paper init failed"); + return; + } + Serial.println("Init done"); +} + +void loop() { + + // Clear image memory + epd.ClearFrameMemory(0xFF); // bit set = white, bit reset = black + epd.DisplayFrame(); + Serial.println("Cleared frame memory"); + + // Welcome text + paint.SetRotate(ROTATE_270); + paint.SetWidth(128); + paint.SetHeight(296); + paint.Clear(UNCOLORED); + paint.DrawStringAt(50, 50, "Hello world!", &Font24, COLORED); + epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight()); + epd.DisplayFrame(); + Serial.println("Displayed welcome text"); + delay(3000); + + epd.SetFrameMemory(IMAGE_DATA); + epd.DisplayFrame(); + Serial.println("Displayed image data"); + delay(3000); + + // Black screen + epd.ClearFrameMemory(0); + epd.DisplayFrame(); + Serial.println("Displayed black screen"); + delay(3000); + + epd.Reset(); +} + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/Arduino/libraries/readme.txt b/lib/esp-epaper-29-ws-20171230-gemu-1.0/Arduino/libraries/readme.txt new file mode 100644 index 000000000..96ce674fe --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/Arduino/libraries/readme.txt @@ -0,0 +1 @@ +For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/LICENSE b/lib/esp-epaper-29-ws-20171230-gemu-1.0/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/Makefile b/lib/esp-epaper-29-ws-20171230-gemu-1.0/Makefile new file mode 100644 index 000000000..ad8f69434 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := esp-epaper-29-ws + +include $(IDF_PATH)/make/project.mk + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/README.md b/lib/esp-epaper-29-ws-20171230-gemu-1.0/README.md new file mode 100644 index 000000000..4afa05aa6 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/README.md @@ -0,0 +1,124 @@ +# 2.9" Waveshare ePaper Driver Example + +Communicate with [2.9" Waveshare ePaper Module](https://www.waveshare.com/wiki/2.9inch_e-Paper_Module) using SPI interface of [ESP32](http://espressif.com/en/products/hardware/esp32/overview) and [ESP-IDF](https://github.com/espressif/esp-idf) or [Arduino](https://www.arduino.cc/). + +* [2.9" Waveshare ePaper Module Datasheet](pictures/2.9inch_e-Paper_Datasheet.pdf) + + +## About + +ePaper displays are great for low power applications. They do not need much energy when operated. They retain the last image at zero energy consumed. You can buy them cheaply as they are produced in high volumes to be used in stores as electronic shelf labels. If your do not need fast update of displayed information, go ahead and use ePaper display for your project! This is what I decided to do. Unfortunately I could not find a driver that would easy integrate into my code. Also documentation how to drive them is still somewhat obscure (December 2017). Fortunately with help of great resources mentioned in [Credits](#credits) I was able to develop the driver I was looking for. + +![alt text](pictures/e-paper-and-esp-sample-image.jpg "ePaper display showing a sample graphics image") +![alt text](pictures/e-paper-and-esp-sample-text.jpg "ePaper display showing a sample text and lines drawn from the application using graphics functions") + + +### How to run this example + +#### Arduino + +The quickest way check this software in action is in [Arduino](https://www.arduino.cc/) environment. It should work with all Arduino boards that have SPI interface. Some concern may be the size of memory to store the image. To display the full memory buffer you need 4736 bytes of RAM. If you do not have enough memory, then you can update display where it changed, using smaller chunks of memory. As this project is oriented to use [ESP32](http://espressif.com/en/products/hardware/esp32/overview) chip, there is no concern, it has more than enough RAM. To load the [application](Arduino/epd2in9-demo) use instructions in [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) repository. + +#### ESP-IDF + +To use the [example code](main) with [ESP-IDF](https://github.com/espressif/esp-idf) framework, please follow [ESP32 Get Started](https://esp-idf.readthedocs.io/en/latest/get-started/index.html). + + +### Wiring of ePaper Module used in example code + +| Signal Name | ePaper Module | ESP32 | +| :--- | :---: | :---: | +| Module Busy | BUSY | GPIO22 | +| Reset | RST | GPIO23 | +| Data / Command | DC | GPIO21 | +| Slave Select | CS | GPIO19 | +| Serial Clock | CLK | GPIO18 | +| Master Out Slave In | DIN | GPIO5 | +| Ground | GND | GND | +| Power Supply | 3.3V | 3V3 | + + +### Example log output + +### Arduino + +``` +Starting... +Init done. +Cleared frame memory. +Displayed welcome text +Displayed image data +Displayed black screen +``` + +### ESP-IDF + +``` +I (0) cpu_start: Starting scheduler on APP CPU. +I (259) ePaper Example: Starting example +I (259) ePaper Example: Before ePaper driver init, heap: 297852 +I (279) ePaper Driver: SPI data sent 30 +I (279) ePaper Example: e-Paper Display Espressif logo +I (279) ePaper Driver: SPI data sent 4736 +I (6969) ePaper Example: e-Paper Display sample graphics +I (7039) ePaper Driver: SPI data sent 4736 +I (8669) ePaper Example: EPD Display update count: 0 +I (8669) ePaper Example: After ePaper driver delete, heap: 302292 + +``` + + +## Build Status for ESP-IDF + +[![Build Status](https://travis-ci.org/krzychb/esp-epaper-29-ws.svg?branch=master)](https://travis-ci.org/krzychb/esp-epaper-29-ws) + + +## Documentation for ESP-IDF + +[![Documentation Status](https://readthedocs.org/projects/esp-epaper-29-ws/badge/?version=latest)](http://esp-epaper-29-ws.readthedocs.io/en/latest/?badge=latest) + + +## ESP-IDF Usage Notes + +### Changes to the original driver + +I have discovered that there are plenty of similar e-paper displays on the market that look exactly the same, but require some modifications in the driver code. In my case I have modified the following: + +* Display initialization sequence in function `iot_epaper_spi_init()` +* LUT tables, they differ in size and quantity and dictate how the image is "developed" on the screen +* Commands to to configure image data transfer to the display, two extra functions have been added - `iot_set_ram_area()` and `iot_set_ram_address_counter()`. +* Commands to show up the image +* Other minor things like configuration of checking the BUSY signal, command to put the ePaper into sleep mode, display resolution, etc. + + +### Optimizing the SPI communication + +I have decided to make some updates to the SPI code in original [epaper](https://github.com/espressif/esp-iot-solution/tree/master/components/spi_devices/epaper/test) component. In particular I have configured DMA transfer instead of sending image data byte by byte. Also I have removed pre and post transfer delays. + + +### Converting pictures + +To convert an exiting image to the C header file, use an application recommended by Waveshare in their [Wiki](https://www.waveshare.com/wiki/2.9inch_e-Paper_Module#How_to_display_an_image). See a picture below what parameters to set. I have discovered that you need to mirror the image and this was not documented in the Wiki. + +![alt text](pictures/image-conversion-setup.png "Example how to set up the application to convert an image to the C header file") + + +## Contribute + +Feel free to contribute to the project in any way you like! + +If you find any issues with code or description please report them using *Issues* tab above. + + +## Credits + +This repository has been prepared thanks to great work of the following teams and individuals: + +* Espressif team that develops and maintains [esp-idf](https://github.com/espressif/esp-idf) repository +* esp-iot-solution team that developed cleanly coded [epaper](https://github.com/espressif/esp-iot-solution/tree/master/components/spi_devices/epaper/test) component for another type of display +* Waveshare that provides [great documentation](https://www.waveshare.com/wiki/2.9inch_e-Paper_Module) and [demo code](https://www.waveshare.com/wiki/File:2.9inch_e-Paper_Module_code.7z) for various displays they supply + + +## License + +[Apache License Version 2.0, January 2004](LICENSE) \ No newline at end of file diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/component.mk b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/component.mk new file mode 100644 index 000000000..2581b048f --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/component.mk @@ -0,0 +1,2 @@ +COMPONENT_ADD_INCLUDEDIRS := . + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper-29-ws.c b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper-29-ws.c new file mode 100644 index 000000000..c4090a83c --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper-29-ws.c @@ -0,0 +1,695 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include +#include +#include +#include "driver/gpio.h" +#include "driver/spi_master.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/xtensa_api.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/ringbuf.h" +#include "esp_log.h" + +#include "epaper-29-ws.h" + +static const char* TAG = "ePaper Driver"; + +#define EPAPER_QUE_SIZE_DEFAULT 10 + +const unsigned char lut_full_update[] = +{ + 0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, + 0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51, + 0x35, 0x51, 0x51, 0x19, 0x01, 0x00 +}; + +// This LUT is not yet used in the code below +const unsigned char lut_partial_update[] = +{ + 0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static portMUX_TYPE epaper_spinlock = portMUX_INITIALIZER_UNLOCKED; +#define EPAPER_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) +#define EPAPER_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) + +// LCD data/command +typedef struct { + uint8_t dc_io; + uint8_t dc_level; +} epaper_dc_t; + +typedef struct { + spi_device_handle_t bus; + epaper_conf_t pin; /* EPD properties */ + epaper_paint_t paint; /* Paint properties */ + epaper_dc_t dc; + xSemaphoreHandle spi_mux; +} epaper_dev_t; + +/* This function is called (in irq context!) just before a transmission starts. + * It will set the D/C line to the value indicated in the user field + */ +static void iot_epaper_pre_transfer_callback(spi_transaction_t *t) +{ + epaper_dc_t *dc = (epaper_dc_t *) t->user; + gpio_set_level((int)dc->dc_io, (int)dc->dc_level); +} + +static esp_err_t _iot_epaper_spi_send(spi_device_handle_t spi, spi_transaction_t* t) +{ + return spi_device_transmit(spi, t); +} + +void iot_epaper_send(spi_device_handle_t spi, const uint8_t *data, int len, epaper_dc_t *dc) +{ + esp_err_t ret; + if (len == 0) { + return; // no need to send anything + } + spi_transaction_t t = { + .length = len * 8, // Len is in bytes, transaction length is in bits. + .tx_buffer = data, + .user = (void *) dc, + }; + ret = _iot_epaper_spi_send(spi, &t); + assert(ret == ESP_OK); +} + +static void iot_epaper_send_command(epaper_handle_t dev, unsigned char command) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + device->dc.dc_io = device->pin.dc_pin; + device->dc.dc_level = device->pin.dc_lev_cmd; + iot_epaper_send(device->bus, &command, 1, &device->dc); +} + +static void iot_epaper_send_byte(epaper_handle_t dev, const uint8_t data) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + device->dc.dc_io = device->pin.dc_pin; + device->dc.dc_level = device->pin.dc_lev_data; + iot_epaper_send(device->bus, &data, 1, &device->dc); +} + +static void iot_epaper_send_data(epaper_handle_t dev, const uint8_t *data, int length) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + device->dc.dc_io = device->pin.dc_pin; + device->dc.dc_level = device->pin.dc_lev_data; + // To Do: original driver was sending byte by byte + // Pay attention to possible performance issues + iot_epaper_send(device->bus, data, length, &device->dc); + ESP_LOGI(TAG, "SPI data sent %d", length); +} + +static void iot_epaper_paint_init(epaper_handle_t dev, unsigned char* image, int width, int height) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + device->paint.rotate = E_PAPER_ROTATE_0; + device->paint.image = image; + /* 1 byte = 8 pixels, so the width should be the multiple of 8 */ + device->paint.width = width % 8 ? width + 8 - (width % 8) : width; + device->paint.height = height; +} + +static void iot_epaper_gpio_init(epaper_conf_t * pin) +{ + gpio_pad_select_gpio(pin->reset_pin); + gpio_set_direction(pin->reset_pin, GPIO_MODE_OUTPUT); + gpio_set_level(pin->reset_pin, pin->rst_active_level); + gpio_pad_select_gpio(pin->dc_pin); + gpio_set_direction(pin->dc_pin, GPIO_MODE_OUTPUT); + gpio_set_level(pin->dc_pin, 1); + ets_delay_us(10000); + gpio_set_level(pin->dc_pin, 0); + gpio_pad_select_gpio(pin->busy_pin); + gpio_set_direction(pin->busy_pin, GPIO_MODE_INPUT); + gpio_set_pull_mode(pin->busy_pin, GPIO_PULLUP_ONLY); +} + +static esp_err_t iot_epaper_spi_init(epaper_handle_t dev, spi_device_handle_t *e_spi, epaper_conf_t *pin) +{ + esp_err_t ret; + spi_bus_config_t buscfg = { + .miso_io_num = -1, // MISO not used, we are transferring to the slave only + .mosi_io_num = pin->mosi_pin, + .sclk_io_num = pin->sck_pin, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + // The maximum size sent below covers the case + // when the whole frame buffer is transferred to the slave + .max_transfer_sz = EPD_WIDTH * EPD_HEIGHT / 8, + }; + spi_device_interface_config_t devcfg = { + .clock_speed_hz = pin->clk_freq_hz, + .mode = 0, // SPI mode 0 + .spics_io_num = pin->cs_pin, + // To Do: clarify what does it mean + .queue_size = EPAPER_QUE_SIZE_DEFAULT, + // We are sending only in one direction (to the ePaper slave) + .flags = (SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE), + //Specify pre-transfer callback to handle D/C line + .pre_cb = iot_epaper_pre_transfer_callback, + }; + ret = spi_bus_initialize(pin->spi_host, &buscfg, 1); + assert(ret == ESP_OK); + ret = spi_bus_add_device(pin->spi_host, &devcfg, e_spi); + assert(ret == ESP_OK); + return ret; +} + +static void iot_epaper_set_lut(epaper_handle_t dev) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + iot_epaper_send_command(dev, E_PAPER_WRITE_LUT_REGISTER); + iot_epaper_send_data(dev, lut_full_update, sizeof(lut_full_update)); + xSemaphoreGiveRecursive(device->spi_mux); +} + +static void iot_epaper_epd_init(epaper_handle_t dev) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + + iot_epaper_reset(dev); + + /* This part of code is ePaper module specific + * It has been copied from the instructions as it is + */ + iot_epaper_send_command(dev, E_PAPER_DRIVER_OUTPUT_CONTROL); + iot_epaper_send_byte(dev, (EPD_HEIGHT - 1) & 0xff); + iot_epaper_send_byte(dev, ((EPD_HEIGHT - 1) >> 8) & 0xff); + iot_epaper_send_byte(dev, 0x00); // GD = 0; SM = 0; TB = 0 + + iot_epaper_send_command(dev, E_PAPER_BOOSTER_SOFT_START_CONTROL); + iot_epaper_send_byte(dev, 0xD7); + iot_epaper_send_byte(dev, 0xD6); + iot_epaper_send_byte(dev, 0x9D); + + iot_epaper_send_command(dev, E_PAPER_WRITE_VCOM_REGISTER); + iot_epaper_send_byte(dev, 0xA8); // VCOM 7C + + iot_epaper_send_command(dev, E_PAPER_SET_DUMMY_LINE_PERIOD); + iot_epaper_send_byte(dev, 0x1A); // 4 dummy lines per gate + + iot_epaper_send_command(dev, E_PAPER_SET_GATE_TIME); + iot_epaper_send_byte(dev, 0x08); // 2us per line + + iot_epaper_send_command(dev, E_PAPER_DATA_ENTRY_MODE_SETTING); + iot_epaper_send_byte(dev, 0x03); // X increment; Y increment + + iot_epaper_set_lut(dev); + xSemaphoreGiveRecursive(device->spi_mux); +} + +epaper_handle_t iot_epaper_create(spi_device_handle_t bus, epaper_conf_t *epconf) +{ + epaper_dev_t* dev = (epaper_dev_t*) calloc(1, sizeof(epaper_dev_t)); + dev->spi_mux = xSemaphoreCreateRecursiveMutex(); + uint8_t* frame_buf = (unsigned char*) heap_caps_malloc( + (epconf->width * epconf->height / 8), MALLOC_CAP_8BIT); + if (frame_buf == NULL) { + ESP_LOGE(TAG, "frame_buffer malloc fail"); + return NULL; + } + iot_epaper_gpio_init(epconf); + ESP_LOGD(TAG, "gpio init ok"); + if (bus) { + dev->bus = bus; + } else { + iot_epaper_spi_init(dev, &dev->bus, epconf); + ESP_LOGD(TAG, "spi init ok"); + } + dev->pin = *epconf; + iot_epaper_epd_init(dev); + iot_epaper_paint_init(dev, frame_buf, epconf->width, epconf->height); + return (epaper_handle_t) dev; +} + +esp_err_t iot_epaper_delete(epaper_handle_t dev, bool del_bus) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + + iot_epaper_sleep(dev); + + spi_bus_remove_device(device->bus); + if (del_bus) { + spi_bus_free(device->pin.spi_host); + } + vSemaphoreDelete(device->spi_mux); + if (device->paint.image) { + free(device->paint.image); + device->paint.image = NULL; + } + free(device); + return ESP_OK; +} + +int iot_epaper_get_width(epaper_handle_t dev) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + return device->paint.width; +} + +void iot_epaper_set_width(epaper_handle_t dev, int width) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + device->paint.width = width % 8 ? width + 8 - (width % 8) : width; + xSemaphoreGiveRecursive(device->spi_mux); + +} + +int iot_epaper_get_height(epaper_handle_t dev) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + return device->paint.height; +} + +void iot_epaper_set_height(epaper_handle_t dev, int height) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + device->paint.height = height; + xSemaphoreGiveRecursive(device->spi_mux); +} + +int iot_epaper_get_rotate(epaper_handle_t dev) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + return device->paint.rotate; +} + +void iot_epaper_set_rotate(epaper_handle_t dev, int rotate) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + device->paint.rotate = rotate; + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: Getters and Setters + */ +unsigned char* iot_epaper_get_image(epaper_handle_t dev) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + return device->paint.image; +} + +/** + * @brief: this draws a pixel by absolute coordinates. + * this function won't be affected by the rotate parameter. + */ +static void iot_epaper_draw_absolute_pixel(epaper_handle_t dev, int x, int y, int colored) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + if (x < 0 || x >= device->paint.width || y < 0 || y >= device->paint.height) { + return; + } + EPAPER_ENTER_CRITICAL(&epaper_spinlock); + if (device->pin.color_inv) { + if (colored) { + device->paint.image[(x + y * device->paint.width) / 8] |= 0x80 >> (x % 8); + } else { + device->paint.image[(x + y * device->paint.width) / 8] &= ~(0x80 >> (x % 8)); + } + } else { + if (colored) { + device->paint.image[(x + y * device->paint.width) / 8] &= ~(0x80 >> (x % 8)); + } else { + device->paint.image[(x + y * device->paint.width) / 8] |= 0x80 >> (x % 8); + } + } + EPAPER_EXIT_CRITICAL(&epaper_spinlock); +} + +void iot_epaper_clean_paint(epaper_handle_t dev, int colored) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + for (int x = 0; x < device->paint.width; x++) { + for (int y = 0; y < device->paint.height; y++) { + iot_epaper_draw_absolute_pixel(dev, x, y, colored); + } + } + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: this displays a string on the frame buffer but not refresh + */ +void iot_epaper_draw_string(epaper_handle_t dev, int x, int y, const char* text, epaper_font_t* font, int colored) +{ + const char* p_text = text; + unsigned int counter = 0; + int refcolumn = x; + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + /* Send the string character by character on EPD */ + while (*p_text != 0) { + /* Display one character on EPD */ + iot_epaper_draw_char(dev, refcolumn, y, *p_text, font, colored); + /* Decrement the column position by 16 */ + refcolumn += font->width; + /* Point on the next character */ + p_text++; + counter++; + } + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: this draws a pixel by the coordinates + */ +void iot_epaper_draw_pixel(epaper_handle_t dev, int x, int y, int colored) +{ + int point_temp; + epaper_dev_t* device = (epaper_dev_t*) dev; + if (device->paint.rotate == E_PAPER_ROTATE_0) { + if (x < 0 || x >= device->paint.width || y < 0 || y >= device->paint.height) { + return; + } + iot_epaper_draw_absolute_pixel(dev, x, y, colored); + } else if (device->paint.rotate == E_PAPER_ROTATE_90) { + if (x < 0 || x >= device->paint.height || y < 0 || y >= device->paint.width) { + return; + } + point_temp = x; + x = device->paint.width - y; + y = point_temp; + iot_epaper_draw_absolute_pixel(dev, x, y, colored); + } else if (device->paint.rotate == E_PAPER_ROTATE_180) { + if (x < 0 || x >= device->paint.width || y < 0 || y >= device->paint.height) { + return; + } + x = device->paint.width - x; + y = device->paint.height - y; + iot_epaper_draw_absolute_pixel(dev, x, y, colored); + } else if (device->paint.rotate == E_PAPER_ROTATE_270) { + if (x < 0 || x >= device->paint.height || y < 0 || y >= device->paint.width) { + return; + } + point_temp = x; + x = y; + y = device->paint.height - point_temp; + iot_epaper_draw_absolute_pixel(dev, x, y, colored); + } +} + +/** + * @brief: this draws a character on the frame buffer but not refresh + */ +void iot_epaper_draw_char(epaper_handle_t dev, int x, int y, char ascii_char, epaper_font_t* font, int colored) +{ + int i, j; + unsigned int char_offset = (ascii_char - ' ') * font->height * (font->width / 8 + (font->width % 8 ? 1 : 0)); + const unsigned char* ptr = &font->font_table[char_offset]; + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + for (j = 0; j < font->height; j++) { + for (i = 0; i < font->width; i++) { + if (*ptr & (0x80 >> (i % 8))) { + iot_epaper_draw_pixel(dev, x + i, y + j, colored); + } + if (i % 8 == 7) { + ptr++; + } + } + if (font->width % 8 != 0) { + ptr++; + } + } + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: this draws a line on the frame buffer + */ +void iot_epaper_draw_line(epaper_handle_t dev, int x0, int y0, int x1, int y1, + int colored) +{ + /* Bresenham algorithm */ + int dx = x1 - x0 >= 0 ? x1 - x0 : x0 - x1; + int sx = x0 < x1 ? 1 : -1; + int dy = y1 - y0 <= 0 ? y1 - y0 : y0 - y1; + int sy = y0 < y1 ? 1 : -1; + int err = dx + dy; + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + while ((x0 != x1) && (y0 != y1)) { + iot_epaper_draw_pixel(dev, x0, y0, colored); + if (2 * err >= dy) { + err += dy; + x0 += sx; + } + if (2 * err <= dx) { + err += dx; + y0 += sy; + } + } + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: this draws a horizontal line on the frame buffer + */ +void iot_epaper_draw_horizontal_line(epaper_handle_t dev, int x, int y, int width, int colored) +{ + int i; + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + for (i = x; i < x + width; i++) { + iot_epaper_draw_pixel(dev, i, y, colored); + } + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: this draws a vertical line on the frame buffer + */ +void iot_epaper_draw_vertical_line(epaper_handle_t dev, int x, int y, int height, int colored) +{ + int i; + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + for (i = y; i < y + height; i++) { + iot_epaper_draw_pixel(dev, x, i, colored); + } + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: this draws a rectangle + */ +void iot_epaper_draw_rectangle(epaper_handle_t dev, int x0, int y0, int x1, int y1, int colored) +{ + int min_x, min_y, max_x, max_y; + min_x = x1 > x0 ? x0 : x1; + max_x = x1 > x0 ? x1 : x0; + min_y = y1 > y0 ? y0 : y1; + max_y = y1 > y0 ? y1 : y0; + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + iot_epaper_draw_horizontal_line(dev, min_x, min_y, max_x - min_x + 1, colored); + iot_epaper_draw_horizontal_line(dev, min_x, max_y, max_x - min_x + 1, colored); + iot_epaper_draw_vertical_line(dev, min_x, min_y, max_y - min_y + 1, colored); + iot_epaper_draw_vertical_line(dev, max_x, min_y, max_y - min_y + 1, colored); + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: this draws a filled rectangle + */ +void ior_epaper_draw_filled_rectangle(epaper_handle_t dev, int x0, int y0, int x1, int y1, int colored) +{ + int min_x, min_y, max_x, max_y; + int i; + min_x = x1 > x0 ? x0 : x1; + max_x = x1 > x0 ? x1 : x0; + min_y = y1 > y0 ? y0 : y1; + max_y = y1 > y0 ? y1 : y0; + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + for (i = min_x; i <= max_x; i++) { + iot_epaper_draw_vertical_line(dev, i, min_y, max_y - min_y + 1, colored); + } + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: this draws a circle + */ +void iot_epaper_draw_circle(epaper_handle_t dev, int x, int y, int radius, + int colored) +{ + /* Bresenham algorithm */ + int x_pos = -radius; + int y_pos = 0; + int err = 2 - 2 * radius; + int e2; + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + do { + iot_epaper_draw_pixel(dev, x - x_pos, y + y_pos, colored); + iot_epaper_draw_pixel(dev, x + x_pos, y + y_pos, colored); + iot_epaper_draw_pixel(dev, x + x_pos, y - y_pos, colored); + iot_epaper_draw_pixel(dev, x - x_pos, y - y_pos, colored); + e2 = err; + if (e2 <= y_pos) { + err += ++y_pos * 2 + 1; + if (-x_pos == y_pos && e2 <= x_pos) { + e2 = 0; + } + } + if (e2 > x_pos) { + err += ++x_pos * 2 + 1; + } + } while (x_pos <= 0); + xSemaphoreGiveRecursive(device->spi_mux); +} + +/** + * @brief: this draws a filled circle + */ +void iot_epaper_draw_filled_circle(epaper_handle_t dev, int x, int y, int radius, int colored) +{ + /* Bresenham algorithm */ + int x_pos = -radius; + int y_pos = 0; + int err = 2 - 2 * radius; + int e2; + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + do { + iot_epaper_draw_pixel(dev, x - x_pos, y + y_pos, colored); + iot_epaper_draw_pixel(dev, x + x_pos, y + y_pos, colored); + iot_epaper_draw_pixel(dev, x + x_pos, y - y_pos, colored); + iot_epaper_draw_pixel(dev, x - x_pos, y - y_pos, colored); + iot_epaper_draw_horizontal_line(dev, x + x_pos, y + y_pos, 2 * (-x_pos) + 1, colored); + iot_epaper_draw_horizontal_line(dev, x + x_pos, y - y_pos, 2 * (-x_pos) + 1, colored); + e2 = err; + if (e2 <= y_pos) { + err += ++y_pos * 2 + 1; + if (-x_pos == y_pos && e2 <= x_pos) { + e2 = 0; + } + } + if (e2 > x_pos) { + err += ++x_pos * 2 + 1; + } + } while (x_pos <= 0); + xSemaphoreGiveRecursive(device->spi_mux); +} + +void iot_epaper_wait_idle(epaper_handle_t dev) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + while (gpio_get_level((gpio_num_t) device->pin.busy_pin) == device->pin.busy_active_level) { + vTaskDelay(10 / portTICK_RATE_MS); + } +} + +void iot_epaper_reset(epaper_handle_t dev) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + gpio_set_level((gpio_num_t) device->pin.reset_pin, (~(device->pin.rst_active_level)) & 0x1); + ets_delay_us(200); + gpio_set_level((gpio_num_t) device->pin.reset_pin, (device->pin.rst_active_level) & 0x1); //module reset + ets_delay_us(200); + gpio_set_level((gpio_num_t) device->pin.reset_pin, (~(device->pin.rst_active_level)) & 0x1); + iot_epaper_wait_idle(dev); + xSemaphoreGiveRecursive(device->spi_mux); +} + +/* This function has been exposed to implement partial updates of the image + * To Do: implement partial updates of the image + */ +void iot_set_ram_area(epaper_handle_t dev, int x_start, int y_start, int x_end, int y_end) +{ + iot_epaper_send_command(dev, E_PAPER_SET_RAM_X_ADDRESS_START_END_POSITION); + iot_epaper_send_byte(dev, x_start >> 3); // 8 pixels per byte + iot_epaper_send_byte(dev, x_end >> 3); // 8 pixels per byte + iot_epaper_send_command(dev, E_PAPER_SET_RAM_Y_ADDRESS_START_END_POSITION); + iot_epaper_send_byte(dev, y_start & 0xff); + iot_epaper_send_byte(dev, y_start >> 8); + iot_epaper_send_byte(dev, y_end & 0xff); + iot_epaper_send_byte(dev, y_end >> 8); +} + +/* This function has been exposed to implement partial updates of the image + * To Do: implement partial updates of the image + */ +void iot_set_ram_address_counter(epaper_handle_t dev, int x, int y) +{ + iot_epaper_send_command(dev, E_PAPER_SET_RAM_X_ADDRESS_COUNTER); + iot_epaper_send_byte(dev, x >> 3); // 8 pixels per byte + iot_epaper_send_command(dev, E_PAPER_SET_RAM_Y_ADDRESS_COUNTER); + iot_epaper_send_byte(dev, y & 0xff); + iot_epaper_send_byte(dev, y >> 8); +} + +/* This transfer to the display the whole image frame + * To Do: implement partial updates of the image + */ +void iot_epaper_display_frame(epaper_handle_t dev, const unsigned char* frame_buffer) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + if (frame_buffer == NULL) { + frame_buffer = device->paint.image; + } + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + if (frame_buffer != NULL) { + + // configure ePaper's memory to send data + iot_set_ram_area(dev, 0, 0, EPD_WIDTH-1, EPD_HEIGHT-1); + iot_set_ram_address_counter(dev, 0, 0); + + // send image data + iot_epaper_send_command(dev, E_PAPER_WRITE_RAM); + iot_epaper_send_data(dev, frame_buffer, device->paint.width / 8 * device->paint.height); + + // update display + iot_epaper_send_command(dev, E_PAPER_DISPLAY_UPDATE_CONTROL_2); + iot_epaper_send_byte(dev, 0xC4); + iot_epaper_send_command(dev, E_PAPER_MASTER_ACTIVATION); + iot_epaper_send_command(dev, E_PAPER_TERMINATE_FRAME_READ_WRITE); + iot_epaper_wait_idle(dev); + } + xSemaphoreGiveRecursive(device->spi_mux); +} + +void iot_epaper_sleep(epaper_handle_t dev) +{ + epaper_dev_t* device = (epaper_dev_t*) dev; + xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY); + iot_epaper_send_command(dev, E_PAPER_DEEP_SLEEP_MODE); + iot_epaper_wait_idle(dev); + xSemaphoreGiveRecursive(device->spi_mux); +} + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper-29-ws.h b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper-29-ws.h new file mode 100644 index 000000000..929395395 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper-29-ws.h @@ -0,0 +1,351 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _IOT_E_PAPER_29_H_ +#define _IOT_E_PAPER_29_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif +#include "driver/spi_master.h" + +// Display orientation +typedef enum { + E_PAPER_ROTATE_0, + E_PAPER_ROTATE_90, + E_PAPER_ROTATE_180, + E_PAPER_ROTATE_270, +} epaper_rotate_t; + +typedef struct +{ + uint16_t width; + uint16_t height; + const uint8_t *font_table; +} epaper_font_t; + +#define COLORED 0 +#define UNCOLORED 1 + +// Display resolution +#define EPD_WIDTH 128 +#define EPD_HEIGHT 296 + +// Display CONTROLLER COMMANDS +#define E_PAPER_DRIVER_OUTPUT_CONTROL 0x01 +#define E_PAPER_BOOSTER_SOFT_START_CONTROL 0x0C +#define E_PAPER_GATE_SCAN_START_POSITION 0x0F +#define E_PAPER_DEEP_SLEEP_MODE 0x10 +#define E_PAPER_DATA_ENTRY_MODE_SETTING 0x11 +#define E_PAPER_SW_RESET 0x12 +#define E_PAPER_TEMPERATURE_SENSOR_CONTROL 0x1A +#define E_PAPER_MASTER_ACTIVATION 0x20 +#define E_PAPER_DISPLAY_UPDATE_CONTROL_1 0x21 +#define E_PAPER_DISPLAY_UPDATE_CONTROL_2 0x22 +#define E_PAPER_WRITE_RAM 0x24 +#define E_PAPER_WRITE_VCOM_REGISTER 0x2C +#define E_PAPER_WRITE_LUT_REGISTER 0x32 +#define E_PAPER_SET_DUMMY_LINE_PERIOD 0x3A +#define E_PAPER_SET_GATE_TIME 0x3B +#define E_PAPER_BORDER_WAVEFORM_CONTROL 0x3C +#define E_PAPER_SET_RAM_X_ADDRESS_START_END_POSITION 0x44 +#define E_PAPER_SET_RAM_Y_ADDRESS_START_END_POSITION 0x45 +#define E_PAPER_SET_RAM_X_ADDRESS_COUNTER 0x4E +#define E_PAPER_SET_RAM_Y_ADDRESS_COUNTER 0x4F +#define E_PAPER_TERMINATE_FRAME_READ_WRITE 0xFF + +/* Paint properties */ +typedef struct { + unsigned char* image; + epaper_rotate_t rotate; + int width; + int height; +} epaper_paint_t; + +/* EPD properties */ +typedef struct { + int reset_pin; + int dc_pin; + int cs_pin; + int busy_pin; + int mosi_pin; + int miso_pin; + int sck_pin; + + uint8_t rst_active_level; + uint8_t busy_active_level; + uint8_t dc_lev_data; + uint8_t dc_lev_cmd; + + int clk_freq_hz; + spi_host_device_t spi_host; + + int width; + int height; + bool color_inv; +} epaper_conf_t; + +typedef void* epaper_handle_t; /*handle of epaper*/ + +/** + * @brief Create and init epaper and return a epaper handle + * + * @param bus handle of spi device + * @param epconf configure struct for epaper device + * + * @return + * - handle of epaper + */ +epaper_handle_t iot_epaper_create(spi_device_handle_t bus, epaper_conf_t * epconf); + +/** + * @brief delete epaper handle_t + * + * @param dev object handle of epaper + * @param del_bus whether to delete spi bus + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t iot_epaper_delete(epaper_handle_t dev, bool del_bus); + +/** + * @brief clear display frame buffer + * + * @param dev object handle of epaper + * @param colored to set display color + */ +void iot_epaper_clean_paint(epaper_handle_t dev, int colored); + +/** + * @brief get paint width + * + * @param dev object handle of epaper + * + * @return + * - paint width + */ +int iot_epaper_get_width(epaper_handle_t dev); + +/** + * @brief set paint width + * @param dev object handle of epaper + * @param width paint width + */ +void iot_epaper_set_width(epaper_handle_t dev, int width); + +/** + * @brief get paint height + * @param dev object handle of epaper + * @return + * - paint height + */ +int iot_epaper_get_height(epaper_handle_t dev); + +/** + * @brief set paint height + * @param dev object handle of epaper + * @param paint height + */ +void iot_epaper_set_height(epaper_handle_t dev, int height); + +/** + * @brief get paint rotate + * @param dev object handle of epaper + * @return + * - current rotation + */ +int iot_epaper_get_rotate(epaper_handle_t dev); + +/** + * @brief set paint rotate + * @param dev object handle of epaper + * @param rotation + */ +void iot_epaper_set_rotate(epaper_handle_t dev, int rotate); + +/** + * @brief get display data + * @param dev object handle of epaper + * @return + * - Pointer to display data + */ +unsigned char* iot_epaper_get_image(epaper_handle_t dev); + +/** + * @brief draw string start on point(x,y) and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * @param dev object handle of epaper + * @param x poing (x) + * @param y poing (y) + * @param text display string + * @param font Font style + * @param colored display color + */ +void iot_epaper_draw_string(epaper_handle_t dev, int x, int y, const char* text, + epaper_font_t* font, int colored); + +/** + * @brief draw pixel and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * @param dev object handle of epaper + * @param x point (x) + * @param y point (y) + * @param colored display color + */ +void iot_epaper_draw_pixel(epaper_handle_t dev, int x, int y, int colored); + +/** + * @brief draw char and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * @param dev object handle of epaper + * @param x poing (x) + * @param y poing (y) + * @param ascii_char display char + * @param font font style + * @param colored display color + */ +void iot_epaper_draw_char(epaper_handle_t dev, int x, int y, char ascii_char, + epaper_font_t* font, int colored); + +/** + * @brief draw line start on point(x0,y0) end on point(x1,y1) and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * + * @param dev object handle of epaper + * @param x0 poing (x0) + * @param y0 poing (y0) + * @param x1 poing (x1) + * @param y1 poing (y1) + * @param colored display color + */ +void iot_epaper_draw_line(epaper_handle_t dev, int x0, int y0, int x1, int y1, + int colored); + +/** + * @brief draw horizontal line start on point(x,y) and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * @param dev object handle of epaper + * @param x poing (x) + * @param y poing (y) + * @param width line width + * @param colored display color + */ +void iot_epaper_draw_horizontal_line(epaper_handle_t dev, int x, int y, + int width, int colored); + +/** + * @brief draw vertical line start on point(x,y) and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * + * @param dev object handle of epaper + * @param x poing (x) + * @param y poing (y) + * @param line height + * @param display color + */ +void iot_epaper_draw_vertical_line(epaper_handle_t dev, int x, int y, + int height, int colored); + +/** + * @brief draw rectangle point(x0,y0) (x1,y1) and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * + * @param dev object handle of epaper + * @param x0 point(x0,y0) + * @param y0 point(x0,y0) + * @param x1 point(x1,y1) + * @param y1 point(x1,y1) + * @param colored display color + */ +void iot_epaper_draw_rectangle(epaper_handle_t dev, int x0, int y0, int x1, + int y1, int colored); + +/** + * @brief draw fill rectangle point(x0,y0) (x1,y1) and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * + * @param dev object handle of epaper + * @param x0 point(x0,y0) + * @param y0 point(x0,y0) + * @param x1 point(x1,y1) + * @param y1 point(x1,y1) + * @param colored display color + */ +void ior_epaper_draw_filled_rectangle(epaper_handle_t dev, int x0, int y0, + int x1, int y1, int colored); + +/** + * @brief draw a circle at point(x,y) and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * + * @param dev object handle of epaper + * @param x point(x,y) + * @param y point(x,y) + * @param colored display color + */ +void iot_epaper_draw_circle(epaper_handle_t dev, int x, int y, int radius, + int colored); + +/** + * @brief draw a fill circle at point(x,y) and save on display data array, + * screen will display when call iot_epaper_display_frame function. + * + * @param dev object handle of epaper + * @param x point(x,y) + * @param y point(x,y) + * @param radius radius of the circle + * @param colored display color + */ +void iot_epaper_draw_filled_circle(epaper_handle_t dev, int x, int y, + int radius, int colored); + +/** + * @brief wait until idle + * @param dev object handle of epaper + */ +void iot_epaper_wait_idle(epaper_handle_t dev); + +/** + * @brief reset device + * + * @param dev object handle of epaper + */ +void iot_epaper_reset(epaper_handle_t dev); + +/** + * @brief dispaly frame, refresh screen + * + * @param dev object handle of epaper + */ +void iot_epaper_display_frame(epaper_handle_t dev, const unsigned char* frame_buffer); + +/** + * @brief After this command is transmitted, the chip would enter the deep-sleep mode to save power. + * The deep sleep mode would return to standby by hardware reset. The only one parameter is a + * check code, the command would be executed if check code = 0xA5. + * You can use iot_epaper_reset() to awaken and EPD_Init() to initialize + * + * @param dev object handle of epaper + */ +void iot_epaper_sleep(epaper_handle_t dev); + +#ifdef __cplusplus +} +#endif + +#endif //_IOT_E_PAPER_29_H_ + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper_font.c b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper_font.c new file mode 100644 index 000000000..3c745541e --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper_font.c @@ -0,0 +1,8615 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include "epaper_fonts.h" + +const uint8_t Font8_Table[] = { +// @0 ' ' (5 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @8 '!' (5 pixels wide) + 0x20,// # + 0x20, // # + 0x20, // # + 0x20, // # + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + + // @16 '"' (5 pixels wide) + 0x50,// # # + 0x50, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @24 '#' (5 pixels wide) + 0x28,// # # + 0x50, // # # + 0xF8, // ##### + 0x50, // # # + 0xF8, // ##### + 0x50, // # # + 0xA0, // # # + 0x00, // + + // @32 '$' (5 pixels wide) + 0x20,// # + 0x30, // ## + 0x60, // ## + 0x30, // ## + 0x10, // # + 0x60, // ## + 0x20, // # + 0x00, // + + // @40 '%' (5 pixels wide) + 0x20,// # + 0x20, // # + 0x18, // ## + 0x60, // ## + 0x10, // # + 0x10, // # + 0x00, // + 0x00, // + + // @48 '&' (5 pixels wide) + 0x00,// + 0x38, // ### + 0x20, // # + 0x60, // ## + 0x50, // # # + 0x78, // #### + 0x00, // + 0x00, // + + // @56 ''' (5 pixels wide) + 0x20,// # + 0x20, // # + 0x20, // # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @64 '(' (5 pixels wide) + 0x10,// # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x10, // # + 0x00, // + + // @72 ')' (5 pixels wide) + 0x40,// # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x40, // # + 0x00, // + + // @80 '*' (5 pixels wide) + 0x20,// # + 0x70, // ### + 0x20, // # + 0x50, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @88 '+' (5 pixels wide) + 0x00,// + 0x20, // # + 0x20, // # + 0xF8, // ##### + 0x20, // # + 0x20, // # + 0x00, // + 0x00, // + + // @96 ',' (5 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x10, // # + 0x20, // # + 0x20, // # + 0x00, // + + // @104 '-' (5 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x70, // ### + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @112 '.' (5 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + + // @120 '/' (5 pixels wide) + 0x10,// # + 0x20, // # + 0x20, // # + 0x20, // # + 0x40, // # + 0x40, // # + 0x80, // # + 0x00, // + + // @128 '0' (5 pixels wide) + 0x20,// # + 0x50, // # # + 0x50, // # # + 0x50, // # # + 0x50, // # # + 0x20, // # + 0x00, // + 0x00, // + + // @136 '1' (5 pixels wide) + 0x60,// ## + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0xF8, // ##### + 0x00, // + 0x00, // + + // @144 '2' (5 pixels wide) + 0x20,// # + 0x50, // # # + 0x20, // # + 0x20, // # + 0x40, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @152 '3' (5 pixels wide) + 0x20,// # + 0x50, // # # + 0x10, // # + 0x20, // # + 0x10, // # + 0x60, // ## + 0x00, // + 0x00, // + + // @160 '4' (5 pixels wide) + 0x10,// # + 0x30, // ## + 0x50, // # # + 0x78, // #### + 0x10, // # + 0x38, // ### + 0x00, // + 0x00, // + + // @168 '5' (5 pixels wide) + 0x70,// ### + 0x40, // # + 0x60, // ## + 0x10, // # + 0x50, // # # + 0x20, // # + 0x00, // + 0x00, // + + // @176 '6' (5 pixels wide) + 0x30,// ## + 0x40, // # + 0x60, // ## + 0x50, // # # + 0x50, // # # + 0x60, // ## + 0x00, // + 0x00, // + + // @184 '7' (5 pixels wide) + 0x70,// ### + 0x50, // # # + 0x10, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x00, // + 0x00, // + + // @192 '8' (5 pixels wide) + 0x20,// # + 0x50, // # # + 0x20, // # + 0x50, // # # + 0x50, // # # + 0x20, // # + 0x00, // + 0x00, // + + // @200 '9' (5 pixels wide) + 0x30,// ## + 0x50, // # # + 0x50, // # # + 0x30, // ## + 0x10, // # + 0x60, // ## + 0x00, // + 0x00, // + + // @208 ':' (5 pixels wide) + 0x00,// + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + + // @216 ';' (5 pixels wide) + 0x00,// + 0x00, // + 0x10, // # + 0x00, // + 0x10, // # + 0x20, // # + 0x00, // + 0x00, // + + // @224 '<' (5 pixels wide) + 0x00,// + 0x10, // # + 0x20, // # + 0xC0, // ## + 0x20, // # + 0x10, // # + 0x00, // + 0x00, // + + // @232 '=' (5 pixels wide) + 0x00,// + 0x70, // ### + 0x00, // + 0x70, // ### + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @240 '>' (5 pixels wide) + 0x00,// + 0x40, // # + 0x20, // # + 0x18, // ## + 0x20, // # + 0x40, // # + 0x00, // + 0x00, // + + // @248 '?' (5 pixels wide) + 0x20,// # + 0x50, // # # + 0x10, // # + 0x20, // # + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + + // @256 '@' (5 pixels wide) + 0x30,// ## + 0x48, // # # + 0x48, // # # + 0x58, // # ## + 0x48, // # # + 0x40, // # + 0x38, // ### + 0x00, // + + // @264 'A' (5 pixels wide) + 0x60,// ## + 0x20, // # + 0x50, // # # + 0x70, // ### + 0x88, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @272 'B' (5 pixels wide) + 0xF0,// #### + 0x48, // # # + 0x70, // ### + 0x48, // # # + 0x48, // # # + 0xF0, // #### + 0x00, // + 0x00, // + + // @280 'C' (5 pixels wide) + 0x70,// ### + 0x50, // # # + 0x40, // # + 0x40, // # + 0x40, // # + 0x30, // ## + 0x00, // + 0x00, // + + // @288 'D' (5 pixels wide) + 0xF0,// #### + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0xF0, // #### + 0x00, // + 0x00, // + + // @296 'E' (5 pixels wide) + 0xF8,// ##### + 0x48, // # # + 0x60, // ## + 0x40, // # + 0x48, // # # + 0xF8, // ##### + 0x00, // + 0x00, // + + // @304 'F' (5 pixels wide) + 0xF8,// ##### + 0x48, // # # + 0x60, // ## + 0x40, // # + 0x40, // # + 0xE0, // ### + 0x00, // + 0x00, // + + // @312 'G' (5 pixels wide) + 0x70,// ### + 0x40, // # + 0x40, // # + 0x58, // # ## + 0x50, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @320 'H' (5 pixels wide) + 0xE8,// ### # + 0x48, // # # + 0x78, // #### + 0x48, // # # + 0x48, // # # + 0xE8, // ### # + 0x00, // + 0x00, // + + // @328 'I' (5 pixels wide) + 0x70,// ### + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @336 'J' (5 pixels wide) + 0x38,// ### + 0x10, // # + 0x10, // # + 0x50, // # # + 0x50, // # # + 0x20, // # + 0x00, // + 0x00, // + + // @344 'K' (5 pixels wide) + 0xD8,// ## ## + 0x50, // # # + 0x60, // ## + 0x70, // ### + 0x50, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @352 'L' (5 pixels wide) + 0xE0,// ### + 0x40, // # + 0x40, // # + 0x40, // # + 0x48, // # # + 0xF8, // ##### + 0x00, // + 0x00, // + + // @360 'M' (5 pixels wide) + 0xD8,// ## ## + 0xD8, // ## ## + 0xD8, // ## ## + 0xA8, // # # # + 0x88, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @368 'N' (5 pixels wide) + 0xD8,// ## ## + 0x68, // ## # + 0x68, // ## # + 0x58, // # ## + 0x58, // # ## + 0xE8, // ### # + 0x00, // + 0x00, // + + // @376 'O' (5 pixels wide) + 0x30,// ## + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @384 'P' (5 pixels wide) + 0xF0,// #### + 0x48, // # # + 0x48, // # # + 0x70, // ### + 0x40, // # + 0xE0, // ### + 0x00, // + 0x00, // + + // @392 'Q' (5 pixels wide) + 0x30,// ## + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x30, // ## + 0x18, // ## + 0x00, // + + // @400 'R' (5 pixels wide) + 0xF0,// #### + 0x48, // # # + 0x48, // # # + 0x70, // ### + 0x48, // # # + 0xE8, // ### # + 0x00, // + 0x00, // + + // @408 'S' (5 pixels wide) + 0x70,// ### + 0x50, // # # + 0x20, // # + 0x10, // # + 0x50, // # # + 0x70, // ### + 0x00, // + 0x00, // + + // @416 'T' (5 pixels wide) + 0xF8,// ##### + 0xA8, // # # # + 0x20, // # + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @424 'U' (5 pixels wide) + 0xD8,// ## ## + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @432 'V' (5 pixels wide) + 0xD8,// ## ## + 0x88, // # # + 0x48, // # # + 0x50, // # # + 0x50, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @440 'W' (5 pixels wide) + 0xD8,// ## ## + 0x88, // # # + 0xA8, // # # # + 0xA8, // # # # + 0xA8, // # # # + 0x50, // # # + 0x00, // + 0x00, // + + // @448 'X' (5 pixels wide) + 0xD8,// ## ## + 0x50, // # # + 0x20, // # + 0x20, // # + 0x50, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @456 'Y' (5 pixels wide) + 0xD8,// ## ## + 0x88, // # # + 0x50, // # # + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @464 'Z' (5 pixels wide) + 0x78,// #### + 0x48, // # # + 0x10, // # + 0x20, // # + 0x48, // # # + 0x78, // #### + 0x00, // + 0x00, // + + // @472 '[' (5 pixels wide) + 0x30,// ## + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x30, // ## + 0x00, // + + // @480 '\' (5 pixels wide) + 0x80,// # + 0x40, // # + 0x40, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x10, // # + 0x00, // + + // @488 ']' (5 pixels wide) + 0x60,// ## + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x60, // ## + 0x00, // + + // @496 '^' (5 pixels wide) + 0x20,// # + 0x20, // # + 0x50, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @504 '_' (5 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0xF8, // ##### + + // @512 '`' (5 pixels wide) + 0x20,// # + 0x10, // # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @520 'a' (5 pixels wide) + 0x00,// + 0x00, // + 0x30, // ## + 0x10, // # + 0x70, // ### + 0x78, // #### + 0x00, // + 0x00, // + + // @528 'b' (5 pixels wide) + 0xC0,// ## + 0x40, // # + 0x70, // ### + 0x48, // # # + 0x48, // # # + 0xF0, // #### + 0x00, // + 0x00, // + + // @536 'c' (5 pixels wide) + 0x00,// + 0x00, // + 0x70, // ### + 0x40, // # + 0x40, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @544 'd' (5 pixels wide) + 0x18,// ## + 0x08, // # + 0x38, // ### + 0x48, // # # + 0x48, // # # + 0x38, // ### + 0x00, // + 0x00, // + + // @552 'e' (5 pixels wide) + 0x00,// + 0x00, // + 0x70, // ### + 0x70, // ### + 0x40, // # + 0x30, // ## + 0x00, // + 0x00, // + + // @560 'f' (5 pixels wide) + 0x10,// # + 0x20, // # + 0x70, // ### + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @568 'g' (5 pixels wide) + 0x00,// + 0x00, // + 0x38, // ### + 0x48, // # # + 0x48, // # # + 0x38, // ### + 0x08, // # + 0x30, // ## + + // @576 'h' (5 pixels wide) + 0xC0,// ## + 0x40, // # + 0x70, // ### + 0x48, // # # + 0x48, // # # + 0xE8, // ### # + 0x00, // + 0x00, // + + // @584 'i' (5 pixels wide) + 0x20,// # + 0x00, // + 0x60, // ## + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @592 'j' (5 pixels wide) + 0x20,// # + 0x00, // + 0x70, // ### + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x70, // ### + + // @600 'k' (5 pixels wide) + 0xC0,// ## + 0x40, // # + 0x58, // # ## + 0x70, // ### + 0x50, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @608 'l' (5 pixels wide) + 0x60,// ## + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @616 'm' (5 pixels wide) + 0x00,// + 0x00, // + 0xD0, // ## # + 0xA8, // # # # + 0xA8, // # # # + 0xA8, // # # # + 0x00, // + 0x00, // + + // @624 'n' (5 pixels wide) + 0x00,// + 0x00, // + 0xF0, // #### + 0x48, // # # + 0x48, // # # + 0xC8, // ## # + 0x00, // + 0x00, // + + // @632 'o' (5 pixels wide) + 0x00,// + 0x00, // + 0x30, // ## + 0x48, // # # + 0x48, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @640 'p' (5 pixels wide) + 0x00,// + 0x00, // + 0xF0, // #### + 0x48, // # # + 0x48, // # # + 0x70, // ### + 0x40, // # + 0xE0, // ### + + // @648 'q' (5 pixels wide) + 0x00,// + 0x00, // + 0x38, // ### + 0x48, // # # + 0x48, // # # + 0x38, // ### + 0x08, // # + 0x18, // ## + + // @656 'r' (5 pixels wide) + 0x00,// + 0x00, // + 0x78, // #### + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @664 's' (5 pixels wide) + 0x00,// + 0x00, // + 0x30, // ## + 0x20, // # + 0x10, // # + 0x60, // ## + 0x00, // + 0x00, // + + // @672 't' (5 pixels wide) + 0x00,// + 0x40, // # + 0xF0, // #### + 0x40, // # + 0x48, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @680 'u' (5 pixels wide) + 0x00,// + 0x00, // + 0xD8, // ## ## + 0x48, // # # + 0x48, // # # + 0x38, // ### + 0x00, // + 0x00, // + + // @688 'v' (5 pixels wide) + 0x00,// + 0x00, // + 0xC8, // ## # + 0x48, // # # + 0x30, // ## + 0x30, // ## + 0x00, // + 0x00, // + + // @696 'w' (5 pixels wide) + 0x00,// + 0x00, // + 0xD8, // ## ## + 0xA8, // # # # + 0xA8, // # # # + 0x50, // # # + 0x00, // + 0x00, // + + // @704 'x' (5 pixels wide) + 0x00,// + 0x00, // + 0x48, // # # + 0x30, // ## + 0x30, // ## + 0x48, // # # + 0x00, // + 0x00, // + + // @712 'y' (5 pixels wide) + 0x00,// + 0x00, // + 0xD8, // ## ## + 0x50, // # # + 0x50, // # # + 0x20, // # + 0x20, // # + 0x60, // ## + + // @720 'z' (5 pixels wide) + 0x00,// + 0x00, // + 0x78, // #### + 0x50, // # # + 0x28, // # # + 0x78, // #### + 0x00, // + 0x00, // + + // @728 '{' (5 pixels wide) + 0x10,// # + 0x20, // # + 0x20, // # + 0x60, // ## + 0x20, // # + 0x20, // # + 0x10, // # + 0x00, // + + // @736 '|' (5 pixels wide) + 0x20,// # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x00, // + + // @744 '}' (5 pixels wide) + 0x40,// # + 0x20, // # + 0x20, // # + 0x30, // ## + 0x20, // # + 0x20, // # + 0x40, // # + 0x00, // + + // @752 '~' (5 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x28, // # # + 0x50, // # # + 0x00, // + 0x00, // + 0x00, // + }; + +// Font data for Courier New 12pt + +const uint8_t Font12_Table[] = { +// @0 ' ' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @12 '!' (7 pixels wide) + 0x00,// + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x00, // + 0x00, // + 0x10, // # + 0x00, // + 0x00, // + 0x00, // + + // @24 '"' (7 pixels wide) + 0x00,// + 0x6C, // ## ## + 0x48, // # # + 0x48, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @36 '#' (7 pixels wide) + 0x00,// + 0x14, // # # + 0x14, // # # + 0x28, // # # + 0x7C, // ##### + 0x28, // # # + 0x7C, // ##### + 0x28, // # # + 0x50, // # # + 0x50, // # # + 0x00, // + 0x00, // + + // @48 '$' (7 pixels wide) + 0x00,// + 0x10, // # + 0x38, // ### + 0x40, // # + 0x40, // # + 0x38, // ### + 0x48, // # # + 0x70, // ### + 0x10, // # + 0x10, // # + 0x00, // + 0x00, // + + // @60 '%' (7 pixels wide) + 0x00,// + 0x20, // # + 0x50, // # # + 0x20, // # + 0x0C, // ## + 0x70, // ### + 0x08, // # + 0x14, // # # + 0x08, // # + 0x00, // + 0x00, // + 0x00, // + + // @72 '&' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x18, // ## + 0x20, // # + 0x20, // # + 0x54, // # # # + 0x48, // # # + 0x34, // ## # + 0x00, // + 0x00, // + 0x00, // + + // @84 ''' (7 pixels wide) + 0x00,// + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @96 '(' (7 pixels wide) + 0x00,// + 0x08, // # + 0x08, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x08, // # + 0x08, // # + 0x00, // + + // @108 ')' (7 pixels wide) + 0x00,// + 0x20, // # + 0x20, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x20, // # + 0x20, // # + 0x00, // + + // @120 '*' (7 pixels wide) + 0x00,// + 0x10, // # + 0x7C, // ##### + 0x10, // # + 0x28, // # # + 0x28, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @132 '+' (7 pixels wide) + 0x00,// + 0x00, // + 0x10, // # + 0x10, // # + 0x10, // # + 0xFE, // ####### + 0x10, // # + 0x10, // # + 0x10, // # + 0x00, // + 0x00, // + 0x00, // + + // @144 ',' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x18, // ## + 0x10, // # + 0x30, // ## + 0x20, // # + 0x00, // + + // @156 '-' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @168 '.' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x30, // ## + 0x30, // ## + 0x00, // + 0x00, // + 0x00, // + + // @180 '/' (7 pixels wide) + 0x00,// + 0x04, // # + 0x04, // # + 0x08, // # + 0x08, // # + 0x10, // # + 0x10, // # + 0x20, // # + 0x20, // # + 0x40, // # + 0x00, // + 0x00, // + + // @192 '0' (7 pixels wide) + 0x00,// + 0x38, // ### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @204 '1' (7 pixels wide) + 0x00,// + 0x30, // ## + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @216 '2' (7 pixels wide) + 0x00,// + 0x38, // ### + 0x44, // # # + 0x04, // # + 0x08, // # + 0x10, // # + 0x20, // # + 0x44, // # # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @228 '3' (7 pixels wide) + 0x00,// + 0x38, // ### + 0x44, // # # + 0x04, // # + 0x18, // ## + 0x04, // # + 0x04, // # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @240 '4' (7 pixels wide) + 0x00,// + 0x0C, // ## + 0x14, // # # + 0x14, // # # + 0x24, // # # + 0x44, // # # + 0x7E, // ###### + 0x04, // # + 0x0E, // ### + 0x00, // + 0x00, // + 0x00, // + + // @252 '5' (7 pixels wide) + 0x00,// + 0x3C, // #### + 0x20, // # + 0x20, // # + 0x38, // ### + 0x04, // # + 0x04, // # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @264 '6' (7 pixels wide) + 0x00,// + 0x1C, // ### + 0x20, // # + 0x40, // # + 0x78, // #### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @276 '7' (7 pixels wide) + 0x00,// + 0x7C, // ##### + 0x44, // # # + 0x04, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x10, // # + 0x10, // # + 0x00, // + 0x00, // + 0x00, // + + // @288 '8' (7 pixels wide) + 0x00,// + 0x38, // ### + 0x44, // # # + 0x44, // # # + 0x38, // ### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @300 '9' (7 pixels wide) + 0x00,// + 0x38, // ### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x3C, // #### + 0x04, // # + 0x08, // # + 0x70, // ### + 0x00, // + 0x00, // + 0x00, // + + // @312 ':' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x30, // ## + 0x30, // ## + 0x00, // + 0x00, // + 0x30, // ## + 0x30, // ## + 0x00, // + 0x00, // + 0x00, // + + // @324 ';' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x18, // ## + 0x18, // ## + 0x00, // + 0x00, // + 0x18, // ## + 0x30, // ## + 0x20, // # + 0x00, // + 0x00, // + + // @336 '<' (7 pixels wide) + 0x00,// + 0x00, // + 0x0C, // ## + 0x10, // # + 0x60, // ## + 0x80, // # + 0x60, // ## + 0x10, // # + 0x0C, // ## + 0x00, // + 0x00, // + 0x00, // + + // @348 '=' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x7C, // ##### + 0x00, // + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @360 '>' (7 pixels wide) + 0x00,// + 0x00, // + 0xC0, // ## + 0x20, // # + 0x18, // ## + 0x04, // # + 0x18, // ## + 0x20, // # + 0xC0, // ## + 0x00, // + 0x00, // + 0x00, // + + // @372 '?' (7 pixels wide) + 0x00,// + 0x00, // + 0x18, // ## + 0x24, // # # + 0x04, // # + 0x08, // # + 0x10, // # + 0x00, // + 0x30, // ## + 0x00, // + 0x00, // + 0x00, // + + // @384 '@' (7 pixels wide) + 0x38,// ### + 0x44, // # # + 0x44, // # # + 0x4C, // # ## + 0x54, // # # # + 0x54, // # # # + 0x4C, // # ## + 0x40, // # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + + // @396 'A' (7 pixels wide) + 0x00,// + 0x30, // ## + 0x10, // # + 0x28, // # # + 0x28, // # # + 0x28, // # # + 0x7C, // ##### + 0x44, // # # + 0xEE, // ### ### + 0x00, // + 0x00, // + 0x00, // + + // @408 'B' (7 pixels wide) + 0x00,// + 0xF8, // ##### + 0x44, // # # + 0x44, // # # + 0x78, // #### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0xF8, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @420 'C' (7 pixels wide) + 0x00,// + 0x3C, // #### + 0x44, // # # + 0x40, // # + 0x40, // # + 0x40, // # + 0x40, // # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @432 'D' (7 pixels wide) + 0x00,// + 0xF0, // #### + 0x48, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x48, // # # + 0xF0, // #### + 0x00, // + 0x00, // + 0x00, // + + // @444 'E' (7 pixels wide) + 0x00,// + 0xFC, // ###### + 0x44, // # # + 0x50, // # # + 0x70, // ### + 0x50, // # # + 0x40, // # + 0x44, // # # + 0xFC, // ###### + 0x00, // + 0x00, // + 0x00, // + + // @456 'F' (7 pixels wide) + 0x00,// + 0x7E, // ###### + 0x22, // # # + 0x28, // # # + 0x38, // ### + 0x28, // # # + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + 0x00, // + + // @468 'G' (7 pixels wide) + 0x00,// + 0x3C, // #### + 0x44, // # # + 0x40, // # + 0x40, // # + 0x4E, // # ### + 0x44, // # # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @480 'H' (7 pixels wide) + 0x00,// + 0xEE, // ### ### + 0x44, // # # + 0x44, // # # + 0x7C, // ##### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0xEE, // ### ### + 0x00, // + 0x00, // + 0x00, // + + // @492 'I' (7 pixels wide) + 0x00,// + 0x7C, // ##### + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @504 'J' (7 pixels wide) + 0x00,// + 0x3C, // #### + 0x08, // # + 0x08, // # + 0x08, // # + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x30, // ## + 0x00, // + 0x00, // + 0x00, // + + // @516 'K' (7 pixels wide) + 0x00,// + 0xEE, // ### ### + 0x44, // # # + 0x48, // # # + 0x50, // # # + 0x70, // ### + 0x48, // # # + 0x44, // # # + 0xE6, // ### ## + 0x00, // + 0x00, // + 0x00, // + + // @528 'L' (7 pixels wide) + 0x00,// + 0x70, // ### + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x24, // # # + 0x24, // # # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @540 'M' (7 pixels wide) + 0x00,// + 0xEE, // ### ### + 0x6C, // ## ## + 0x6C, // ## ## + 0x54, // # # # + 0x54, // # # # + 0x44, // # # + 0x44, // # # + 0xEE, // ### ### + 0x00, // + 0x00, // + 0x00, // + + // @552 'N' (7 pixels wide) + 0x00,// + 0xEE, // ### ### + 0x64, // ## # + 0x64, // ## # + 0x54, // # # # + 0x54, // # # # + 0x54, // # # # + 0x4C, // # ## + 0xEC, // ### ## + 0x00, // + 0x00, // + 0x00, // + + // @564 'O' (7 pixels wide) + 0x00,// + 0x38, // ### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @576 'P' (7 pixels wide) + 0x00,// + 0x78, // #### + 0x24, // # # + 0x24, // # # + 0x24, // # # + 0x38, // ### + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + 0x00, // + + // @588 'Q' (7 pixels wide) + 0x00,// + 0x38, // ### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x38, // ### + 0x1C, // ### + 0x00, // + 0x00, // + + // @600 'R' (7 pixels wide) + 0x00,// + 0xF8, // ##### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x78, // #### + 0x48, // # # + 0x44, // # # + 0xE2, // ### # + 0x00, // + 0x00, // + 0x00, // + + // @612 'S' (7 pixels wide) + 0x00,// + 0x34, // ## # + 0x4C, // # ## + 0x40, // # + 0x38, // ### + 0x04, // # + 0x04, // # + 0x64, // ## # + 0x58, // # ## + 0x00, // + 0x00, // + 0x00, // + + // @624 'T' (7 pixels wide) + 0x00,// + 0xFE, // ####### + 0x92, // # # # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @636 'U' (7 pixels wide) + 0x00,// + 0xEE, // ### ### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @648 'V' (7 pixels wide) + 0x00,// + 0xEE, // ### ### + 0x44, // # # + 0x44, // # # + 0x28, // # # + 0x28, // # # + 0x28, // # # + 0x10, // # + 0x10, // # + 0x00, // + 0x00, // + 0x00, // + + // @660 'W' (7 pixels wide) + 0x00,// + 0xEE, // ### ### + 0x44, // # # + 0x44, // # # + 0x54, // # # # + 0x54, // # # # + 0x54, // # # # + 0x54, // # # # + 0x28, // # # + 0x00, // + 0x00, // + 0x00, // + + // @672 'X' (7 pixels wide) + 0x00,// + 0xC6, // ## ## + 0x44, // # # + 0x28, // # # + 0x10, // # + 0x10, // # + 0x28, // # # + 0x44, // # # + 0xC6, // ## ## + 0x00, // + 0x00, // + 0x00, // + + // @684 'Y' (7 pixels wide) + 0x00,// + 0xEE, // ### ### + 0x44, // # # + 0x28, // # # + 0x28, // # # + 0x10, // # + 0x10, // # + 0x10, // # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @696 'Z' (7 pixels wide) + 0x00,// + 0x7C, // ##### + 0x44, // # # + 0x08, // # + 0x10, // # + 0x10, // # + 0x20, // # + 0x44, // # # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @708 '[' (7 pixels wide) + 0x00,// + 0x38, // ### + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x38, // ### + 0x00, // + + // @720 '\' (7 pixels wide) + 0x00,// + 0x40, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x10, // # + 0x10, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x00, // + 0x00, // + + // @732 ']' (7 pixels wide) + 0x00,// + 0x38, // ### + 0x08, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x38, // ### + 0x00, // + + // @744 '^' (7 pixels wide) + 0x00,// + 0x10, // # + 0x10, // # + 0x28, // # # + 0x44, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @756 '_' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0xFE, // ####### + + // @768 '`' (7 pixels wide) + 0x00,// + 0x10, // # + 0x08, // # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @780 'a' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x38, // ### + 0x44, // # # + 0x3C, // #### + 0x44, // # # + 0x44, // # # + 0x3E, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @792 'b' (7 pixels wide) + 0x00,// + 0xC0, // ## + 0x40, // # + 0x58, // # ## + 0x64, // ## # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0xF8, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @804 'c' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x3C, // #### + 0x44, // # # + 0x40, // # + 0x40, // # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @816 'd' (7 pixels wide) + 0x00,// + 0x0C, // ## + 0x04, // # + 0x34, // ## # + 0x4C, // # ## + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x3E, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @828 'e' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x38, // ### + 0x44, // # # + 0x7C, // ##### + 0x40, // # + 0x40, // # + 0x3C, // #### + 0x00, // + 0x00, // + 0x00, // + + // @840 'f' (7 pixels wide) + 0x00,// + 0x1C, // ### + 0x20, // # + 0x7C, // ##### + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @852 'g' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x36, // ## ## + 0x4C, // # ## + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x3C, // #### + 0x04, // # + 0x38, // ### + 0x00, // + + // @864 'h' (7 pixels wide) + 0x00,// + 0xC0, // ## + 0x40, // # + 0x58, // # ## + 0x64, // ## # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0xEE, // ### ### + 0x00, // + 0x00, // + 0x00, // + + // @876 'i' (7 pixels wide) + 0x00,// + 0x10, // # + 0x00, // + 0x70, // ### + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @888 'j' (7 pixels wide) + 0x00,// + 0x10, // # + 0x00, // + 0x78, // #### + 0x08, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x08, // # + 0x70, // ### + 0x00, // + + // @900 'k' (7 pixels wide) + 0x00,// + 0xC0, // ## + 0x40, // # + 0x5C, // # ### + 0x48, // # # + 0x70, // ### + 0x50, // # # + 0x48, // # # + 0xDC, // ## ### + 0x00, // + 0x00, // + 0x00, // + + // @912 'l' (7 pixels wide) + 0x00,// + 0x30, // ## + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @924 'm' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0xE8, // ### # + 0x54, // # # # + 0x54, // # # # + 0x54, // # # # + 0x54, // # # # + 0xFE, // ####### + 0x00, // + 0x00, // + 0x00, // + + // @936 'n' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0xD8, // ## ## + 0x64, // ## # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0xEE, // ### ### + 0x00, // + 0x00, // + 0x00, // + + // @948 'o' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x38, // ### + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x38, // ### + 0x00, // + 0x00, // + 0x00, // + + // @960 'p' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0xD8, // ## ## + 0x64, // ## # + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x78, // #### + 0x40, // # + 0xE0, // ### + 0x00, // + + // @972 'q' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x36, // ## ## + 0x4C, // # ## + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x3C, // #### + 0x04, // # + 0x0E, // ### + 0x00, // + + // @984 'r' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x6C, // ## ## + 0x30, // ## + 0x20, // # + 0x20, // # + 0x20, // # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @996 's' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x3C, // #### + 0x44, // # # + 0x38, // ### + 0x04, // # + 0x44, // # # + 0x78, // #### + 0x00, // + 0x00, // + 0x00, // + + // @1008 't' (7 pixels wide) + 0x00,// + 0x00, // + 0x20, // # + 0x7C, // ##### + 0x20, // # + 0x20, // # + 0x20, // # + 0x22, // # # + 0x1C, // ### + 0x00, // + 0x00, // + 0x00, // + + // @1020 'u' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0xCC, // ## ## + 0x44, // # # + 0x44, // # # + 0x44, // # # + 0x4C, // # ## + 0x36, // ## ## + 0x00, // + 0x00, // + 0x00, // + + // @1032 'v' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0xEE, // ### ### + 0x44, // # # + 0x44, // # # + 0x28, // # # + 0x28, // # # + 0x10, // # + 0x00, // + 0x00, // + 0x00, // + + // @1044 'w' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0xEE, // ### ### + 0x44, // # # + 0x54, // # # # + 0x54, // # # # + 0x54, // # # # + 0x28, // # # + 0x00, // + 0x00, // + 0x00, // + + // @1056 'x' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0xCC, // ## ## + 0x48, // # # + 0x30, // ## + 0x30, // ## + 0x48, // # # + 0xCC, // ## ## + 0x00, // + 0x00, // + 0x00, // + + // @1068 'y' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0xEE, // ### ### + 0x44, // # # + 0x24, // # # + 0x28, // # # + 0x18, // ## + 0x10, // # + 0x10, // # + 0x78, // #### + 0x00, // + + // @1080 'z' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x7C, // ##### + 0x48, // # # + 0x10, // # + 0x20, // # + 0x44, // # # + 0x7C, // ##### + 0x00, // + 0x00, // + 0x00, // + + // @1092 '{' (7 pixels wide) + 0x00,// + 0x08, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x20, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x08, // # + 0x00, // + + // @1104 '|' (7 pixels wide) + 0x00,// + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x00, // + 0x00, // + + // @1116 '}' (7 pixels wide) + 0x00,// + 0x20, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x08, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x20, // # + 0x00, // + + // @1128 '~' (7 pixels wide) + 0x00,// + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x24, // # # + 0x58, // # ## + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + }; + +// Font data for Courier New 16pt + +const uint8_t Font16_Table[] = { +// @0 ' ' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @32 '!' (11 pixels wide) + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @64 '"' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1D, 0xC0, // ### ### + 0x1D, 0xC0, // ### ### + 0x08, 0x80, // # # + 0x08, 0x80, // # # + 0x08, 0x80, // # # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @96 '#' (11 pixels wide) + 0x00, 0x00, // + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x3F, 0xC0, // ######## + 0x1B, 0x00, // ## ## + 0x3F, 0xC0, // ######## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @128 '$' (11 pixels wide) + 0x04, 0x00, // # + 0x1F, 0x80, // ###### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x38, 0x00, // ### + 0x1E, 0x00, // #### + 0x0F, 0x00, // #### + 0x03, 0x80, // ### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @160 '%' (11 pixels wide) + 0x00, 0x00, // + 0x18, 0x00, // ## + 0x24, 0x00, // # # + 0x24, 0x00, // # # + 0x18, 0xC0, // ## ## + 0x07, 0x80, // #### + 0x1E, 0x00, // #### + 0x31, 0x80, // ## ## + 0x02, 0x40, // # # + 0x02, 0x40, // # # + 0x01, 0x80, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @192 '&' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x0F, 0x00, // #### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x1D, 0x80, // ### ## + 0x37, 0x00, // ## ### + 0x33, 0x00, // ## ## + 0x1D, 0x80, // ### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @224 ''' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x02, 0x00, // # + 0x02, 0x00, // # + 0x02, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @256 '(' (11 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0E, 0x00, // ### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0E, 0x00, // ### + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @288 ')' (11 pixels wide) + 0x00, 0x00, // + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x1C, 0x00, // ### + 0x18, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @320 '*' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x3F, 0xC0, // ######## + 0x0F, 0x00, // #### + 0x1F, 0x80, // ###### + 0x19, 0x80, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @352 '+' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x3F, 0x80, // ####### + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @384 ',' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x0C, 0x00, // ## + 0x08, 0x00, // # + 0x08, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + + // @416 '-' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @448 '.' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @480 '/' (11 pixels wide) + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @512 '0' (11 pixels wide) + 0x00, 0x00, // + 0x0E, 0x00, // ### + 0x1B, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x0E, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @544 '1' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x3E, 0x00, // ##### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @576 '2' (11 pixels wide) + 0x00, 0x00, // + 0x0F, 0x00, // #### + 0x19, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x30, 0x00, // ## + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @608 '3' (11 pixels wide) + 0x00, 0x00, // + 0x3F, 0x00, // ###### + 0x61, 0x80, // ## ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x1F, 0x00, // ##### + 0x03, 0x80, // ### + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x61, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @640 '4' (11 pixels wide) + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x0F, 0x00, // #### + 0x0B, 0x00, // # ## + 0x1B, 0x00, // ## ## + 0x13, 0x00, // # ## + 0x33, 0x00, // ## ## + 0x3F, 0x80, // ####### + 0x03, 0x00, // ## + 0x0F, 0x80, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @672 '5' (11 pixels wide) + 0x00, 0x00, // + 0x1F, 0x80, // ###### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x1F, 0x00, // ##### + 0x11, 0x80, // # ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x21, 0x80, // # ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @704 '6' (11 pixels wide) + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x1C, 0x00, // ### + 0x18, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x00, // ## ### + 0x39, 0x80, // ### ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x19, 0x80, // ## ## + 0x0F, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @736 '7' (11 pixels wide) + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x43, 0x00, // # ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @768 '8' (11 pixels wide) + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @800 '9' (11 pixels wide) + 0x00, 0x00, // + 0x1E, 0x00, // #### + 0x33, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0x80, // ### ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x07, 0x00, // ### + 0x3C, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @832 ':' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @864 ';' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x08, 0x00, // # + 0x08, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @896 '<' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0xC0, // ## + 0x03, 0x00, // ## + 0x04, 0x00, // # + 0x18, 0x00, // ## + 0x60, 0x00, // ## + 0x18, 0x00, // ## + 0x04, 0x00, // # + 0x03, 0x00, // ## + 0x00, 0xC0, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @928 '=' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0xC0, // ######### + 0x00, 0x00, // + 0x7F, 0xC0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @960 '>' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x60, 0x00, // ## + 0x18, 0x00, // ## + 0x04, 0x00, // # + 0x03, 0x00, // ## + 0x00, 0xC0, // ## + 0x03, 0x00, // ## + 0x04, 0x00, // # + 0x18, 0x00, // ## + 0x60, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @992 '?' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x01, 0x80, // ## + 0x07, 0x00, // ### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1024 '@' (11 pixels wide) + 0x00, 0x00, // + 0x0E, 0x00, // ### + 0x11, 0x00, // # # + 0x21, 0x00, // # # + 0x21, 0x00, // # # + 0x27, 0x00, // # ### + 0x29, 0x00, // # # # + 0x29, 0x00, // # # # + 0x27, 0x00, // # ### + 0x20, 0x00, // # + 0x11, 0x00, // # # + 0x0E, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1056 'A' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x00, // ###### + 0x0F, 0x00, // #### + 0x09, 0x00, // # # + 0x19, 0x80, // ## ## + 0x19, 0x80, // ## ## + 0x1F, 0x80, // ###### + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x79, 0xE0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1088 'B' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7F, 0x00, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1120 'C' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x40, // ##### # + 0x30, 0xC0, // ## ## + 0x60, 0x40, // ## # + 0x60, 0x00, // ## + 0x60, 0x00, // ## + 0x60, 0x00, // ## + 0x60, 0x40, // ## # + 0x30, 0x80, // ## # + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1152 'D' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x31, 0x80, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x31, 0x80, // ## ## + 0x7F, 0x00, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1184 'E' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x80, // ######## + 0x30, 0x80, // ## # + 0x30, 0x80, // ## # + 0x32, 0x00, // ## # + 0x3E, 0x00, // ##### + 0x32, 0x00, // ## # + 0x30, 0x80, // ## # + 0x30, 0x80, // ## # + 0x7F, 0x80, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1216 'F' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0xC0, // ######### + 0x30, 0x40, // ## # + 0x30, 0x40, // ## # + 0x32, 0x00, // ## # + 0x3E, 0x00, // ##### + 0x32, 0x00, // ## # + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x7C, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1248 'G' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1E, 0x80, // #### # + 0x31, 0x80, // ## ## + 0x60, 0x80, // ## # + 0x60, 0x00, // ## + 0x60, 0x00, // ## + 0x67, 0xC0, // ## ##### + 0x61, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1280 'H' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x80, // ####### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1312 'I' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xC0, // ######## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1344 'J' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xC0, // ####### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x63, 0x00, // ## ## + 0x63, 0x00, // ## ## + 0x63, 0x00, // ## ## + 0x3E, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1376 'K' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x33, 0x00, // ## ## + 0x36, 0x00, // ## ## + 0x3C, 0x00, // #### + 0x3E, 0x00, // ##### + 0x33, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x79, 0xC0, // #### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1408 'L' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7E, 0x00, // ###### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x40, // ## # + 0x18, 0x40, // ## # + 0x18, 0x40, // ## # + 0x7F, 0xC0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1440 'M' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0xE0, 0xE0, // ### ### + 0x60, 0xC0, // ## ## + 0x71, 0xC0, // ### ### + 0x7B, 0xC0, // #### #### + 0x6A, 0xC0, // ## # # ## + 0x6E, 0xC0, // ## ### ## + 0x64, 0xC0, // ## # ## + 0x60, 0xC0, // ## ## + 0xFB, 0xE0, // ##### ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1472 'N' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x73, 0xC0, // ### #### + 0x31, 0x80, // ## ## + 0x39, 0x80, // ### ## + 0x3D, 0x80, // #### ## + 0x35, 0x80, // ## # ## + 0x37, 0x80, // ## #### + 0x33, 0x80, // ## ### + 0x31, 0x80, // ## ## + 0x79, 0x80, // #### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1504 'O' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1536 'P' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x7E, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1568 'Q' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x0C, 0xC0, // ## ## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1600 'R' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3E, 0x00, // ##### + 0x33, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7C, 0xE0, // ##### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1632 'S' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x80, // ###### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x38, 0x00, // ### + 0x1F, 0x00, // ##### + 0x03, 0x80, // ### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1664 'T' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x80, // ######## + 0x4C, 0x80, // # ## # + 0x4C, 0x80, // # ## # + 0x4C, 0x80, // # ## # + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1696 'U' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1728 'V' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x0A, 0x00, // # # + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1760 'W' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0xFB, 0xE0, // ##### ##### + 0x60, 0xC0, // ## ## + 0x64, 0xC0, // ## # ## + 0x6E, 0xC0, // ## ### ## + 0x6E, 0xC0, // ## ### ## + 0x2A, 0x80, // # # # # + 0x3B, 0x80, // ### ### + 0x3B, 0x80, // ### ### + 0x31, 0x80, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1792 'X' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x1B, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1824 'Y' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x79, 0xE0, // #### #### + 0x30, 0xC0, // ## ## + 0x19, 0x80, // ## ## + 0x0F, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1856 'Z' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x80, // ####### + 0x21, 0x80, // # ## + 0x23, 0x00, // # ## + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x0C, 0x00, // ## + 0x18, 0x80, // ## # + 0x30, 0x80, // ## # + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1888 '[' (11 pixels wide) + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1920 '\' (11 pixels wide) + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1952 ']' (11 pixels wide) + 0x00, 0x00, // + 0x1E, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1E, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1984 '^' (11 pixels wide) + 0x04, 0x00, // # + 0x0A, 0x00, // # # + 0x0A, 0x00, // # # + 0x11, 0x00, // # # + 0x20, 0x80, // # # + 0x20, 0x80, // # # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2016 '_' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0xFF, 0xE0, // ########### + + // @2048 '`' (11 pixels wide) + 0x08, 0x00, // # + 0x04, 0x00, // # + 0x02, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2080 'a' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x1F, 0x80, // ###### + 0x31, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0xC0, // ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2112 'b' (11 pixels wide) + 0x00, 0x00, // + 0x70, 0x00, // ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x00, // ## ### + 0x39, 0x80, // ### ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x39, 0x80, // ### ## + 0x77, 0x00, // ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2144 'c' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1E, 0x80, // #### # + 0x31, 0x80, // ## ## + 0x60, 0x80, // ## # + 0x60, 0x00, // ## + 0x60, 0x80, // ## # + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2176 'd' (11 pixels wide) + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x1D, 0x80, // ### ## + 0x33, 0x80, // ## ### + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0xC0, // ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2208 'e' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x60, 0xC0, // ## ## + 0x7F, 0xC0, // ######### + 0x60, 0x00, // ## + 0x30, 0xC0, // ## ## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2240 'f' (11 pixels wide) + 0x00, 0x00, // + 0x07, 0xE0, // ###### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0x80, // ####### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2272 'g' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1D, 0xC0, // ### ### + 0x33, 0x80, // ## ### + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0x80, // ### ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2304 'h' (11 pixels wide) + 0x00, 0x00, // + 0x70, 0x00, // ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x00, // ## ### + 0x39, 0x80, // ### ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2336 'i' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x00, 0x00, // + 0x1E, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2368 'j' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x00, 0x00, // + 0x3F, 0x00, // ###### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x3E, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2400 'k' (11 pixels wide) + 0x00, 0x00, // + 0x70, 0x00, // ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x80, // ## #### + 0x36, 0x00, // ## ## + 0x3C, 0x00, // #### + 0x3C, 0x00, // #### + 0x36, 0x00, // ## ## + 0x33, 0x00, // ## ## + 0x77, 0xC0, // ### ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2432 'l' (11 pixels wide) + 0x00, 0x00, // + 0x1E, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2464 'm' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x80, // ######## + 0x36, 0xC0, // ## ## ## + 0x36, 0xC0, // ## ## ## + 0x36, 0xC0, // ## ## ## + 0x36, 0xC0, // ## ## ## + 0x36, 0xC0, // ## ## ## + 0x76, 0xE0, // ### ## ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2496 'n' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x77, 0x00, // ### ### + 0x39, 0x80, // ### ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2528 'o' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2560 'p' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x77, 0x00, // ### ### + 0x39, 0x80, // ### ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x39, 0x80, // ### ## + 0x37, 0x00, // ## ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x7C, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2592 'q' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1D, 0xC0, // ### ### + 0x33, 0x80, // ## ### + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0x80, // ### ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2624 'r' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0x80, // #### ### + 0x1C, 0xC0, // ### ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x7F, 0x00, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2656 's' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x80, // ###### + 0x31, 0x80, // ## ## + 0x3C, 0x00, // #### + 0x1F, 0x00, // ##### + 0x03, 0x80, // ### + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2688 't' (11 pixels wide) + 0x00, 0x00, // + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x7F, 0x00, // ####### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x80, // ## # + 0x0F, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2720 'u' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x73, 0x80, // ### ### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0xC0, // ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2752 'v' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2784 'w' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0xF1, 0xE0, // #### #### + 0x60, 0xC0, // ## ## + 0x64, 0xC0, // ## # ## + 0x6E, 0xC0, // ## ### ## + 0x3B, 0x80, // ### ### + 0x3B, 0x80, // ### ### + 0x31, 0x80, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2816 'x' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x1B, 0x00, // ## ## + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x1B, 0x00, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2848 'y' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x79, 0xE0, // #### #### + 0x30, 0xC0, // ## ## + 0x19, 0x80, // ## ## + 0x19, 0x80, // ## ## + 0x0B, 0x00, // # ## + 0x0F, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x3E, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2880 'z' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x80, // ####### + 0x21, 0x80, // # ## + 0x03, 0x00, // ## + 0x0E, 0x00, // ### + 0x18, 0x00, // ## + 0x30, 0x80, // ## # + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2912 '{' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2944 '|' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2976 '}' (11 pixels wide) + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3008 '~' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x18, 0x00, // ## + 0x24, 0x80, // # # # + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + }; + +// Font data for Courier New 20pt + +const uint8_t Font20_Table[] = { +// @0 ' ' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @40 '!' (14 pixels wide) + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x02, 0x00, // # + 0x02, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @80 '"' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1C, 0xE0, // ### ### + 0x1C, 0xE0, // ### ### + 0x1C, 0xE0, // ### ### + 0x08, 0x40, // # # + 0x08, 0x40, // # # + 0x08, 0x40, // # # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @120 '#' (14 pixels wide) + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @160 '$' (14 pixels wide) + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x07, 0xE0, // ###### + 0x0F, 0xE0, // ####### + 0x18, 0x60, // ## ## + 0x18, 0x00, // ## + 0x1F, 0x00, // ##### + 0x0F, 0xC0, // ###### + 0x00, 0xE0, // ### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x1F, 0xC0, // ####### + 0x1F, 0x80, // ###### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @200 '%' (14 pixels wide) + 0x00, 0x00, // + 0x1C, 0x00, // ### + 0x22, 0x00, // # # + 0x22, 0x00, // # # + 0x22, 0x00, // # # + 0x1C, 0x60, // ### ## + 0x01, 0xE0, // #### + 0x0F, 0x80, // ##### + 0x3C, 0x00, // #### + 0x31, 0xC0, // ## ### + 0x02, 0x20, // # # + 0x02, 0x20, // # # + 0x02, 0x20, // # # + 0x01, 0xC0, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @240 '&' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0xE0, // ##### + 0x0F, 0xE0, // ####### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x0F, 0x30, // #### ## + 0x1F, 0xF0, // ######### + 0x19, 0xE0, // ## #### + 0x18, 0xC0, // ## ## + 0x1F, 0xF0, // ######### + 0x07, 0xB0, // #### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @280 ''' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x01, 0x00, // # + 0x01, 0x00, // # + 0x01, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @320 '(' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @360 ')' (14 pixels wide) + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @400 '*' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1B, 0x60, // ## ## ## + 0x1F, 0xE0, // ######## + 0x07, 0x80, // #### + 0x07, 0x80, // #### + 0x0F, 0xC0, // ###### + 0x0C, 0xC0, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @440 '+' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @480 ',' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @520 '-' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @560 '.' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @600 '/' (14 pixels wide) + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @640 '0' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x1F, 0xC0, // ####### + 0x18, 0xC0, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x1F, 0xC0, // ####### + 0x0F, 0x80, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @680 '1' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x1F, 0x00, // ##### + 0x1F, 0x00, // ##### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @720 '2' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x1F, 0xC0, // ####### + 0x38, 0xE0, // ### ### + 0x30, 0x60, // ## ## + 0x00, 0x60, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @760 '3' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x3F, 0xC0, // ######## + 0x30, 0xE0, // ## ### + 0x00, 0x60, // ## + 0x00, 0xE0, // ### + 0x07, 0xC0, // ##### + 0x07, 0xC0, // ##### + 0x00, 0xE0, // ### + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x60, 0xE0, // ## ### + 0x7F, 0xC0, // ######### + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @800 '4' (14 pixels wide) + 0x00, 0x00, // + 0x01, 0xC0, // ### + 0x03, 0xC0, // #### + 0x03, 0xC0, // #### + 0x06, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x00, 0xC0, // ## + 0x03, 0xE0, // ##### + 0x03, 0xE0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @840 '5' (14 pixels wide) + 0x00, 0x00, // + 0x1F, 0xC0, // ####### + 0x1F, 0xC0, // ####### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x1F, 0x80, // ###### + 0x1F, 0xC0, // ####### + 0x18, 0xE0, // ## ### + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x30, 0xE0, // ## ### + 0x3F, 0xC0, // ######## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @880 '6' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0xE0, // ##### + 0x0F, 0xE0, // ####### + 0x1E, 0x00, // #### + 0x18, 0x00, // ## + 0x38, 0x00, // ### + 0x37, 0x80, // ## #### + 0x3F, 0xC0, // ######## + 0x38, 0xE0, // ### ### + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x18, 0xE0, // ## ### + 0x1F, 0xC0, // ####### + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @920 '7' (14 pixels wide) + 0x00, 0x00, // + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x30, 0x60, // ## ## + 0x00, 0x60, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @960 '8' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x1F, 0xC0, // ####### + 0x38, 0xE0, // ### ### + 0x30, 0x60, // ## ## + 0x38, 0xE0, // ### ### + 0x1F, 0xC0, // ####### + 0x1F, 0xC0, // ####### + 0x38, 0xE0, // ### ### + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x38, 0xE0, // ### ### + 0x1F, 0xC0, // ####### + 0x0F, 0x80, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1000 '9' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x00, // #### + 0x1F, 0xC0, // ####### + 0x38, 0xC0, // ### ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x38, 0xE0, // ### ### + 0x1F, 0xE0, // ######## + 0x0F, 0x60, // #### ## + 0x00, 0xE0, // ### + 0x00, 0xC0, // ## + 0x03, 0xC0, // #### + 0x3F, 0x80, // ####### + 0x3E, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1040 ':' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1080 ';' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x01, 0xC0, // ### + 0x01, 0xC0, // ### + 0x01, 0xC0, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1120 '<' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x30, // ## + 0x00, 0xF0, // #### + 0x03, 0xC0, // #### + 0x07, 0x00, // ### + 0x1C, 0x00, // ### + 0x78, 0x00, // #### + 0x1C, 0x00, // ### + 0x07, 0x00, // ### + 0x03, 0xC0, // #### + 0x00, 0xF0, // #### + 0x00, 0x30, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1160 '=' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0xF0, // ########### + 0x7F, 0xF0, // ########### + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0xF0, // ########### + 0x7F, 0xF0, // ########### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1200 '>' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x30, 0x00, // ## + 0x3C, 0x00, // #### + 0x0F, 0x00, // #### + 0x03, 0x80, // ### + 0x00, 0xE0, // ### + 0x00, 0x78, // #### + 0x00, 0xE0, // ### + 0x03, 0x80, // ### + 0x0F, 0x00, // #### + 0x3C, 0x00, // #### + 0x30, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1240 '?' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x1F, 0xC0, // ####### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x00, 0x60, // ## + 0x01, 0xC0, // ### + 0x03, 0x80, // ### + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1280 '@' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x0C, 0x80, // ## # + 0x08, 0x40, // # # + 0x10, 0x40, // # # + 0x10, 0x40, // # # + 0x11, 0xC0, // # ### + 0x12, 0x40, // # # # + 0x12, 0x40, // # # # + 0x12, 0x40, // # # # + 0x11, 0xC0, // # ### + 0x10, 0x00, // # + 0x08, 0x00, // # + 0x08, 0x40, // # # + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1320 'A' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x80, // ###### + 0x1F, 0x80, // ###### + 0x03, 0x80, // ### + 0x06, 0xC0, // ## ## + 0x06, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x30, 0x30, // ## ## + 0x78, 0x78, // #### #### + 0x78, 0x78, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1360 'B' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x80, // ####### + 0x3F, 0xC0, // ######## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0xE0, // ## ### + 0x1F, 0xC0, // ####### + 0x1F, 0xE0, // ######## + 0x18, 0x70, // ## ### + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xE0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1400 'C' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB0, // #### ## + 0x0F, 0xF0, // ######## + 0x1C, 0x70, // ### ### + 0x38, 0x30, // ### ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x38, 0x30, // ### ## + 0x1C, 0x70, // ### ### + 0x0F, 0xE0, // ####### + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1440 'D' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x80, // ######## + 0x7F, 0xC0, // ######### + 0x30, 0xE0, // ## ### + 0x30, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x70, // ## ### + 0x30, 0xE0, // ## ### + 0x7F, 0xC0, // ######### + 0x7F, 0x80, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1480 'E' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x19, 0x80, // ## ## + 0x1F, 0x80, // ###### + 0x1F, 0x80, // ###### + 0x19, 0x80, // ## ## + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1520 'F' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x19, 0x80, // ## ## + 0x1F, 0x80, // ###### + 0x1F, 0x80, // ###### + 0x19, 0x80, // ## ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x3F, 0x00, // ###### + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1560 'G' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB0, // #### ## + 0x1F, 0xF0, // ######### + 0x18, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x31, 0xF8, // ## ###### + 0x31, 0xF8, // ## ###### + 0x30, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x1F, 0xF0, // ######### + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1600 'H' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1640 'I' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1680 'J' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0xF8, // ####### + 0x03, 0xF8, // ####### + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0xE0, // ## ### + 0x3F, 0xC0, // ######## + 0x0F, 0x80, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1720 'K' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3E, 0xF8, // ##### ##### + 0x3E, 0xF8, // ##### ##### + 0x18, 0xE0, // ## ### + 0x19, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x1F, 0x00, // ##### + 0x1D, 0x80, // ### ## + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x18, 0x60, // ## ## + 0x3E, 0x78, // ##### #### + 0x3E, 0x38, // ##### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1760 'L' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x00, // ###### + 0x3F, 0x00, // ###### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x30, // ## ## + 0x0C, 0x30, // ## ## + 0x0C, 0x30, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1800 'M' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0x78, // #### #### + 0x78, 0x78, // #### #### + 0x38, 0x70, // ### ### + 0x3C, 0xF0, // #### #### + 0x34, 0xB0, // ## # # ## + 0x37, 0xB0, // ## #### ## + 0x37, 0xB0, // ## #### ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x30, 0x30, // ## ## + 0x7C, 0xF8, // ##### ##### + 0x7C, 0xF8, // ##### ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1840 'N' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x39, 0xF0, // ### ##### + 0x3D, 0xF0, // #### ##### + 0x1C, 0x60, // ### ## + 0x1E, 0x60, // #### ## + 0x1E, 0x60, // #### ## + 0x1B, 0x60, // ## ## ## + 0x1B, 0x60, // ## ## ## + 0x19, 0xE0, // ## #### + 0x19, 0xE0, // ## #### + 0x18, 0xE0, // ## ### + 0x3E, 0xE0, // ##### ### + 0x3E, 0x60, // ##### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1880 'O' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x0F, 0xC0, // ###### + 0x1C, 0xE0, // ### ### + 0x38, 0x70, // ### ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x70, // ### ### + 0x1C, 0xE0, // ### ### + 0x0F, 0xC0, // ###### + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1920 'P' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xC0, // ######## + 0x3F, 0xE0, // ######### + 0x18, 0x70, // ## ### + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x18, 0x70, // ## ### + 0x1F, 0xE0, // ######## + 0x1F, 0xC0, // ####### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x3F, 0x00, // ###### + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1960 'Q' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x0F, 0xC0, // ###### + 0x1C, 0xE0, // ### ### + 0x38, 0x70, // ### ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x70, // ### ### + 0x1C, 0xE0, // ### ### + 0x0F, 0xC0, // ###### + 0x07, 0x80, // #### + 0x07, 0xB0, // #### ## + 0x0F, 0xF0, // ######## + 0x0C, 0xE0, // ## ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2000 'R' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xC0, // ######## + 0x3F, 0xE0, // ######### + 0x18, 0x70, // ## ### + 0x18, 0x30, // ## ## + 0x18, 0x70, // ## ### + 0x1F, 0xE0, // ######## + 0x1F, 0xC0, // ####### + 0x18, 0xE0, // ## ### + 0x18, 0x60, // ## ## + 0x18, 0x70, // ## ### + 0x3E, 0x38, // ##### ### + 0x3E, 0x18, // ##### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2040 'S' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x0F, 0xB0, // ##### ## + 0x1F, 0xF0, // ######### + 0x38, 0x70, // ### ### + 0x30, 0x30, // ## ## + 0x38, 0x00, // ### + 0x1F, 0x80, // ###### + 0x07, 0xE0, // ###### + 0x00, 0x70, // ### + 0x30, 0x30, // ## ## + 0x38, 0x70, // ### ### + 0x3F, 0xE0, // ######### + 0x37, 0xC0, // ## ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2080 'T' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x0F, 0xC0, // ###### + 0x0F, 0xC0, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2120 'U' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x1C, 0xE0, // ### ### + 0x0F, 0xC0, // ###### + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2160 'V' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2200 'W' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7C, 0x7C, // ##### ##### + 0x7C, 0x7C, // ##### ##### + 0x30, 0x18, // ## ## + 0x33, 0x98, // ## ### ## + 0x33, 0x98, // ## ### ## + 0x33, 0x98, // ## ### ## + 0x36, 0xD8, // ## ## ## ## + 0x16, 0xD0, // # ## ## # + 0x1C, 0x70, // ### ### + 0x1C, 0x70, // ### ### + 0x1C, 0x70, // ### ### + 0x18, 0x30, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2240 'X' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x0D, 0x80, // ## ## + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x0D, 0x80, // ## ## + 0x18, 0xC0, // ## ## + 0x30, 0x60, // ## ## + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2280 'Y' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x18, 0x60, // ## ## + 0x0C, 0xC0, // ## ## + 0x07, 0x80, // #### + 0x07, 0x80, // #### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x0F, 0xC0, // ###### + 0x0F, 0xC0, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2320 'Z' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2360 '[' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0xC0, // #### + 0x03, 0xC0, // #### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0xC0, // #### + 0x03, 0xC0, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2400 '\' (14 pixels wide) + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2440 ']' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x00, // #### + 0x0F, 0x00, // #### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x0F, 0x00, // #### + 0x0F, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2480 '^' (14 pixels wide) + 0x00, 0x00, // + 0x02, 0x00, // # + 0x07, 0x00, // ### + 0x0D, 0x80, // ## ## + 0x18, 0xC0, // ## ## + 0x30, 0x60, // ## ## + 0x20, 0x20, // # # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2520 '_' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0xFF, 0xFC, // ############## + 0xFF, 0xFC, // ############## + + // @2560 '`' (14 pixels wide) + 0x00, 0x00, // + 0x04, 0x00, // # + 0x03, 0x00, // ## + 0x00, 0x80, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2600 'a' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0F, 0xC0, // ###### + 0x1F, 0xE0, // ######## + 0x00, 0x60, // ## + 0x0F, 0xE0, // ####### + 0x1F, 0xE0, // ######## + 0x38, 0x60, // ### ## + 0x30, 0xE0, // ## ### + 0x3F, 0xF0, // ########## + 0x1F, 0x70, // ##### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2640 'b' (14 pixels wide) + 0x00, 0x00, // + 0x70, 0x00, // ### + 0x70, 0x00, // ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x80, // ## #### + 0x3F, 0xE0, // ######### + 0x38, 0x60, // ### ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x60, // ### ## + 0x7F, 0xE0, // ########## + 0x77, 0x80, // ### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2680 'c' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB0, // #### ## + 0x1F, 0xF0, // ######### + 0x18, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x38, 0x30, // ### ## + 0x1F, 0xF0, // ######### + 0x0F, 0xC0, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2720 'd' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x70, // ### + 0x00, 0x70, // ### + 0x00, 0x30, // ## + 0x00, 0x30, // ## + 0x07, 0xB0, // #### ## + 0x1F, 0xF0, // ######### + 0x18, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x70, // ### ### + 0x1F, 0xF8, // ########## + 0x07, 0xB8, // #### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2760 'e' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x30, 0x00, // ## + 0x18, 0x30, // ## ## + 0x1F, 0xF0, // ######### + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2800 'f' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0xF0, // ###### + 0x07, 0xF0, // ####### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2840 'g' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB8, // #### ### + 0x1F, 0xF8, // ########## + 0x18, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x18, 0x70, // ## ### + 0x1F, 0xF0, // ######### + 0x07, 0xB0, // #### ## + 0x00, 0x30, // ## + 0x00, 0x70, // ### + 0x0F, 0xE0, // ####### + 0x0F, 0xC0, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2880 'h' (14 pixels wide) + 0x00, 0x00, // + 0x38, 0x00, // ### + 0x38, 0x00, // ### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x1B, 0xC0, // ## #### + 0x1F, 0xE0, // ######## + 0x1C, 0x60, // ### ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2920 'i' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x1F, 0x00, // ##### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2960 'j' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xC0, // ####### + 0x1F, 0xC0, // ####### + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0xC0, // ### + 0x3F, 0x80, // ####### + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + + // @3000 'k' (14 pixels wide) + 0x00, 0x00, // + 0x38, 0x00, // ### + 0x38, 0x00, // ### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x1B, 0xE0, // ## ##### + 0x1B, 0xE0, // ## ##### + 0x1B, 0x00, // ## ## + 0x1E, 0x00, // #### + 0x1E, 0x00, // #### + 0x1B, 0x00, // ## ## + 0x19, 0x80, // ## ## + 0x39, 0xF0, // ### ##### + 0x39, 0xF0, // ### ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3040 'l' (14 pixels wide) + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x1F, 0x00, // ##### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3080 'm' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7E, 0xE0, // ###### ### + 0x7F, 0xF0, // ########### + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x7B, 0xB8, // #### ### ### + 0x7B, 0xB8, // #### ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3120 'n' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3B, 0xC0, // ### #### + 0x3F, 0xE0, // ######### + 0x1C, 0x60, // ### ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3160 'o' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x18, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3200 'p' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x77, 0x80, // ### #### + 0x7F, 0xE0, // ########## + 0x38, 0x60, // ### ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x60, // ### ## + 0x3F, 0xE0, // ######### + 0x37, 0x80, // ## #### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x7C, 0x00, // ##### + 0x7C, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @3240 'q' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB8, // #### ### + 0x1F, 0xF8, // ########## + 0x18, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x18, 0x70, // ## ### + 0x1F, 0xF0, // ######### + 0x07, 0xB0, // #### ## + 0x00, 0x30, // ## + 0x00, 0x30, // ## + 0x00, 0xF8, // ##### + 0x00, 0xF8, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @3280 'r' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xE0, // #### ### + 0x3D, 0xF0, // #### ##### + 0x0F, 0x30, // #### ## + 0x0E, 0x00, // ### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3320 's' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xE0, // ###### + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x1E, 0x00, // #### + 0x0F, 0xC0, // ###### + 0x01, 0xE0, // #### + 0x18, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3360 't' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x30, // ## ## + 0x0F, 0xF0, // ######## + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3400 'u' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x38, 0xE0, // ### ### + 0x38, 0xE0, // ### ### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0xE0, // ## ### + 0x1F, 0xF0, // ######### + 0x0F, 0x70, // #### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3440 'v' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3480 'w' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x32, 0x60, // ## # ## + 0x32, 0x60, // ## # ## + 0x37, 0xE0, // ## ###### + 0x1D, 0xC0, // ### ### + 0x1D, 0xC0, // ### ### + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3520 'x' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x0C, 0xC0, // ## ## + 0x07, 0x80, // #### + 0x03, 0x00, // ## + 0x07, 0x80, // #### + 0x0C, 0xC0, // ## ## + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3560 'y' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x0D, 0x80, // ## ## + 0x0F, 0x80, // ##### + 0x07, 0x00, // ### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x7F, 0x00, // ####### + 0x7F, 0x00, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + + // @3600 'z' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x18, 0xC0, // ## ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3640 '{' (14 pixels wide) + 0x00, 0x00, // + 0x01, 0xC0, // ### + 0x03, 0xC0, // #### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x07, 0x00, // ### + 0x0E, 0x00, // ### + 0x07, 0x00, // ### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0xC0, // #### + 0x01, 0xC0, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3680 '|' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3720 '}' (14 pixels wide) + 0x00, 0x00, // + 0x1C, 0x00, // ### + 0x1E, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x07, 0x00, // ### + 0x03, 0x80, // ### + 0x07, 0x00, // ### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1E, 0x00, // #### + 0x1C, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3760 '~' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0E, 0x00, // ### + 0x3F, 0x30, // ###### ## + 0x33, 0xF0, // ## ###### + 0x01, 0xE0, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + }; + +// Font data for Courier New 24pt + +const uint8_t Font24_Table[] = { +// @0 ' ' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @72 '!' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x01, 0x00, 0x00, // # + 0x01, 0x00, 0x00, // # + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @144 '"' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x0E, 0x70, 0x00, // ### ### + 0x0E, 0x70, 0x00, // ### ### + 0x0E, 0x70, 0x00, // ### ### + 0x04, 0x20, 0x00, // # # + 0x04, 0x20, 0x00, // # # + 0x04, 0x20, 0x00, // # # + 0x04, 0x20, 0x00, // # # + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @216 '#' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x06, 0x60, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x3F, 0xF8, 0x00, // ########### + 0x3F, 0xF8, 0x00, // ########### + 0x06, 0x60, 0x00, // ## ## + 0x0C, 0xC0, 0x00, // ## ## + 0x3F, 0xF8, 0x00, // ########### + 0x3F, 0xF8, 0x00, // ########### + 0x0C, 0xC0, 0x00, // ## ## + 0x0C, 0xC0, 0x00, // ## ## + 0x0C, 0xC0, 0x00, // ## ## + 0x0C, 0xC0, 0x00, // ## ## + 0x0C, 0xC0, 0x00, // ## ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @288 '$' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x07, 0xB0, 0x00, // #### ## + 0x0F, 0xF0, 0x00, // ######## + 0x18, 0x70, 0x00, // ## ### + 0x18, 0x70, 0x00, // ## ### + 0x1C, 0x00, 0x00, // ### + 0x0F, 0x80, 0x00, // ##### + 0x07, 0xE0, 0x00, // ###### + 0x00, 0xF0, 0x00, // #### + 0x18, 0x30, 0x00, // ## ## + 0x1C, 0x30, 0x00, // ### ## + 0x1C, 0x70, 0x00, // ### ### + 0x1F, 0xE0, 0x00, // ######## + 0x1B, 0xC0, 0x00, // ## #### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @360 '%' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0x80, 0x00, // #### + 0x0F, 0xC0, 0x00, // ###### + 0x1C, 0xE0, 0x00, // ### ### + 0x18, 0x60, 0x00, // ## ## + 0x18, 0x60, 0x00, // ## ## + 0x1C, 0xE0, 0x00, // ### ### + 0x0F, 0xF8, 0x00, // ######### + 0x07, 0xE0, 0x00, // ###### + 0x1F, 0xF0, 0x00, // ######### + 0x07, 0x38, 0x00, // ### ### + 0x06, 0x18, 0x00, // ## ## + 0x06, 0x18, 0x00, // ## ## + 0x07, 0x38, 0x00, // ### ### + 0x03, 0xF0, 0x00, // ###### + 0x01, 0xE0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @432 '&' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xF0, 0x00, // ###### + 0x07, 0xF0, 0x00, // ####### + 0x0C, 0x60, 0x00, // ## ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x07, 0x00, 0x00, // ### + 0x0F, 0x9C, 0x00, // ##### ### + 0x1D, 0xFC, 0x00, // ### ####### + 0x18, 0xF0, 0x00, // ## #### + 0x18, 0x70, 0x00, // ## ### + 0x0F, 0xFC, 0x00, // ########## + 0x07, 0xDC, 0x00, // ##### ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @504 ''' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x01, 0x00, 0x00, // # + 0x01, 0x00, 0x00, // # + 0x01, 0x00, 0x00, // # + 0x01, 0x00, 0x00, // # + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @576 '(' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x18, 0x00, // ## + 0x00, 0x38, 0x00, // ### + 0x00, 0x70, 0x00, // ### + 0x00, 0xF0, 0x00, // #### + 0x00, 0xE0, 0x00, // ### + 0x00, 0xE0, 0x00, // ### + 0x01, 0xC0, 0x00, // ### + 0x01, 0xC0, 0x00, // ### + 0x01, 0xC0, 0x00, // ### + 0x01, 0xC0, 0x00, // ### + 0x01, 0xC0, 0x00, // ### + 0x01, 0xC0, 0x00, // ### + 0x00, 0xE0, 0x00, // ### + 0x00, 0xE0, 0x00, // ### + 0x00, 0x70, 0x00, // ### + 0x00, 0x70, 0x00, // ### + 0x00, 0x38, 0x00, // ### + 0x00, 0x18, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @648 ')' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x18, 0x00, 0x00, // ## + 0x1C, 0x00, 0x00, // ### + 0x0E, 0x00, 0x00, // ### + 0x0E, 0x00, 0x00, // ### + 0x07, 0x00, 0x00, // ### + 0x07, 0x00, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x07, 0x00, 0x00, // ### + 0x07, 0x00, 0x00, // ### + 0x0F, 0x00, 0x00, // #### + 0x0E, 0x00, 0x00, // ### + 0x1C, 0x00, 0x00, // ### + 0x18, 0x00, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @720 '*' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x1D, 0xB8, 0x00, // ### ## ### + 0x1F, 0xF8, 0x00, // ########## + 0x07, 0xE0, 0x00, // ###### + 0x03, 0xC0, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x06, 0x60, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @792 '+' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x3F, 0xFC, 0x00, // ############ + 0x3F, 0xFC, 0x00, // ############ + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @864 ',' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0xE0, 0x00, // ### + 0x00, 0xC0, 0x00, // ## + 0x01, 0xC0, 0x00, // ### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @936 '-' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0xF8, 0x00, // ########## + 0x1F, 0xF8, 0x00, // ########## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1008 '.' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xC0, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1080 '/' (17 pixels wide) + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x38, 0x00, // ### + 0x00, 0x30, 0x00, // ## + 0x00, 0x70, 0x00, // ### + 0x00, 0x60, 0x00, // ## + 0x00, 0x60, 0x00, // ## + 0x00, 0xC0, 0x00, // ## + 0x00, 0xC0, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x0E, 0x00, 0x00, // ### + 0x0C, 0x00, 0x00, // ## + 0x1C, 0x00, 0x00, // ### + 0x18, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1152 '0' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xC0, 0x00, // #### + 0x07, 0xE0, 0x00, // ###### + 0x0C, 0x30, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x07, 0xE0, 0x00, // ###### + 0x03, 0xC0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1224 '1' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x80, 0x00, // # + 0x07, 0x80, 0x00, // #### + 0x1F, 0x80, 0x00, // ###### + 0x1D, 0x80, 0x00, // ### ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x1F, 0xF8, 0x00, // ########## + 0x1F, 0xF8, 0x00, // ########## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1296 '2' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xC0, 0x00, // ##### + 0x1F, 0xF0, 0x00, // ######### + 0x38, 0x30, 0x00, // ### ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x60, 0x00, // ## + 0x01, 0xC0, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x06, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x3F, 0xF8, 0x00, // ########### + 0x3F, 0xF8, 0x00, // ########### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1368 '3' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xC0, 0x00, // #### + 0x0F, 0xE0, 0x00, // ####### + 0x0C, 0x70, 0x00, // ## ### + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x60, 0x00, // ## + 0x03, 0xC0, 0x00, // #### + 0x03, 0xE0, 0x00, // ##### + 0x00, 0x70, 0x00, // ### + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x18, 0x38, 0x00, // ## ### + 0x1F, 0xF0, 0x00, // ######### + 0x0F, 0xC0, 0x00, // ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1440 '4' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0xE0, 0x00, // ### + 0x01, 0xE0, 0x00, // #### + 0x01, 0xE0, 0x00, // #### + 0x03, 0x60, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x0C, 0x60, 0x00, // ## ## + 0x0C, 0x60, 0x00, // ## ## + 0x18, 0x60, 0x00, // ## ## + 0x30, 0x60, 0x00, // ## ## + 0x3F, 0xF8, 0x00, // ########### + 0x3F, 0xF8, 0x00, // ########### + 0x00, 0x60, 0x00, // ## + 0x03, 0xF8, 0x00, // ####### + 0x03, 0xF8, 0x00, // ####### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1512 '5' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0xF0, 0x00, // ######### + 0x1F, 0xF0, 0x00, // ######### + 0x18, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x1B, 0xC0, 0x00, // ## #### + 0x1F, 0xF0, 0x00, // ######### + 0x1C, 0x30, 0x00, // ### ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x30, 0x30, 0x00, // ## ## + 0x3F, 0xF0, 0x00, // ########## + 0x0F, 0xC0, 0x00, // ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1584 '6' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0xF8, 0x00, // ##### + 0x03, 0xF8, 0x00, // ####### + 0x07, 0x00, 0x00, // ### + 0x0E, 0x00, 0x00, // ### + 0x0C, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x1B, 0xC0, 0x00, // ## #### + 0x1F, 0xF0, 0x00, // ######### + 0x1C, 0x30, 0x00, // ### ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x0C, 0x38, 0x00, // ## ### + 0x0F, 0xF0, 0x00, // ######## + 0x03, 0xE0, 0x00, // ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1656 '7' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0xF8, 0x00, // ########## + 0x1F, 0xF8, 0x00, // ########## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x70, 0x00, // ### + 0x00, 0x60, 0x00, // ## + 0x00, 0x60, 0x00, // ## + 0x00, 0xE0, 0x00, // ### + 0x00, 0xC0, 0x00, // ## + 0x00, 0xC0, 0x00, // ## + 0x01, 0xC0, 0x00, // ### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1728 '8' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xE0, 0x00, // ###### + 0x0F, 0xF0, 0x00, // ######## + 0x1C, 0x38, 0x00, // ### ### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x07, 0xE0, 0x00, // ###### + 0x07, 0xE0, 0x00, // ###### + 0x0C, 0x30, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x1C, 0x38, 0x00, // ### ### + 0x0F, 0xF0, 0x00, // ######## + 0x07, 0xE0, 0x00, // ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1800 '9' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xC0, 0x00, // ##### + 0x0F, 0xF0, 0x00, // ######## + 0x1C, 0x30, 0x00, // ### ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x0C, 0x38, 0x00, // ## ### + 0x0F, 0xF8, 0x00, // ######### + 0x03, 0xD8, 0x00, // #### ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x70, 0x00, // ### + 0x00, 0xE0, 0x00, // ### + 0x1F, 0xC0, 0x00, // ####### + 0x1F, 0x00, 0x00, // ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1872 ':' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xC0, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xC0, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @1944 ';' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0xF0, 0x00, // #### + 0x00, 0xF0, 0x00, // #### + 0x00, 0xF0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0xE0, 0x00, // ### + 0x01, 0xC0, 0x00, // ### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x02, 0x00, 0x00, // # + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2016 '<' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x1C, 0x00, // ### + 0x00, 0x3C, 0x00, // #### + 0x00, 0xF0, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x0F, 0x00, 0x00, // #### + 0x3C, 0x00, 0x00, // #### + 0xF0, 0x00, 0x00, // #### + 0x3C, 0x00, 0x00, // #### + 0x0F, 0x00, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x00, 0xF0, 0x00, // #### + 0x00, 0x3C, 0x00, // #### + 0x00, 0x1C, 0x00, // ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2088 '=' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7F, 0xFC, 0x00, // ############# + 0x7F, 0xFC, 0x00, // ############# + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7F, 0xFC, 0x00, // ############# + 0x7F, 0xFC, 0x00, // ############# + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2160 '>' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x70, 0x00, 0x00, // ### + 0x78, 0x00, 0x00, // #### + 0x1E, 0x00, 0x00, // #### + 0x07, 0x80, 0x00, // #### + 0x01, 0xE0, 0x00, // #### + 0x00, 0x78, 0x00, // #### + 0x00, 0x1E, 0x00, // #### + 0x00, 0x78, 0x00, // #### + 0x01, 0xE0, 0x00, // #### + 0x07, 0x80, 0x00, // #### + 0x1E, 0x00, 0x00, // #### + 0x78, 0x00, 0x00, // #### + 0x70, 0x00, 0x00, // ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2232 '?' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xC0, 0x00, // ##### + 0x0F, 0xE0, 0x00, // ####### + 0x18, 0x70, 0x00, // ## ### + 0x18, 0x30, 0x00, // ## ## + 0x18, 0x30, 0x00, // ## ## + 0x00, 0x70, 0x00, // ### + 0x00, 0xE0, 0x00, // ### + 0x03, 0xC0, 0x00, // #### + 0x03, 0x80, 0x00, // ### + 0x03, 0x00, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0x00, 0x00, // ### + 0x07, 0x00, 0x00, // ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2304 '@' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xE0, 0x00, // ##### + 0x07, 0xF0, 0x00, // ####### + 0x0E, 0x38, 0x00, // ### ### + 0x0C, 0x18, 0x00, // ## ## + 0x18, 0x78, 0x00, // ## #### + 0x18, 0xF8, 0x00, // ## ##### + 0x19, 0xD8, 0x00, // ## ### ## + 0x19, 0x98, 0x00, // ## ## ## + 0x19, 0x98, 0x00, // ## ## ## + 0x19, 0x98, 0x00, // ## ## ## + 0x18, 0xF8, 0x00, // ## ##### + 0x18, 0x78, 0x00, // ## #### + 0x18, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0E, 0x18, 0x00, // ### ## + 0x07, 0xF8, 0x00, // ######## + 0x03, 0xE0, 0x00, // ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2376 'A' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0x80, 0x00, // ###### + 0x1F, 0xC0, 0x00, // ####### + 0x01, 0xC0, 0x00, // ### + 0x03, 0x60, 0x00, // ## ## + 0x03, 0x60, 0x00, // ## ## + 0x06, 0x30, 0x00, // ## ## + 0x06, 0x30, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x0F, 0xF8, 0x00, // ######### + 0x1F, 0xF8, 0x00, // ########## + 0x18, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0xFC, 0x7F, 0x00, // ###### ####### + 0xFC, 0x7F, 0x00, // ###### ####### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2448 'B' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7F, 0xE0, 0x00, // ########## + 0x7F, 0xF0, 0x00, // ########### + 0x18, 0x38, 0x00, // ## ### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x1F, 0xF0, 0x00, // ######### + 0x1F, 0xF8, 0x00, // ########## + 0x18, 0x1C, 0x00, // ## ### + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x7F, 0xF8, 0x00, // ############ + 0x7F, 0xF0, 0x00, // ########### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2520 'C' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xEC, 0x00, // ##### ## + 0x0F, 0xFC, 0x00, // ########## + 0x1C, 0x1C, 0x00, // ### ### + 0x18, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x00, 0x00, // ## + 0x30, 0x00, 0x00, // ## + 0x30, 0x00, 0x00, // ## + 0x30, 0x00, 0x00, // ## + 0x30, 0x00, 0x00, // ## + 0x18, 0x0C, 0x00, // ## ## + 0x1C, 0x1C, 0x00, // ### ### + 0x0F, 0xF8, 0x00, // ######### + 0x03, 0xF0, 0x00, // ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2592 'D' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7F, 0xC0, 0x00, // ######### + 0x7F, 0xF0, 0x00, // ########### + 0x18, 0x38, 0x00, // ## ### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x7F, 0xF0, 0x00, // ########### + 0x7F, 0xE0, 0x00, // ########## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2664 'E' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7F, 0xF8, 0x00, // ############ + 0x7F, 0xF8, 0x00, // ############ + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x19, 0x98, 0x00, // ## ## ## + 0x19, 0x80, 0x00, // ## ## + 0x1F, 0x80, 0x00, // ###### + 0x1F, 0x80, 0x00, // ###### + 0x19, 0x80, 0x00, // ## ## + 0x19, 0x98, 0x00, // ## ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x7F, 0xF8, 0x00, // ############ + 0x7F, 0xF8, 0x00, // ############ + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2736 'F' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x3F, 0xFC, 0x00, // ############ + 0x3F, 0xFC, 0x00, // ############ + 0x0C, 0x0C, 0x00, // ## ## + 0x0C, 0x0C, 0x00, // ## ## + 0x0C, 0xCC, 0x00, // ## ## ## + 0x0C, 0xC0, 0x00, // ## ## + 0x0F, 0xC0, 0x00, // ###### + 0x0F, 0xC0, 0x00, // ###### + 0x0C, 0xC0, 0x00, // ## ## + 0x0C, 0xC0, 0x00, // ## ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x3F, 0xC0, 0x00, // ######## + 0x3F, 0xC0, 0x00, // ######## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2808 'G' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xEC, 0x00, // ##### ## + 0x0F, 0xFC, 0x00, // ########## + 0x1C, 0x1C, 0x00, // ### ### + 0x18, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x00, 0x00, // ## + 0x30, 0x00, 0x00, // ## + 0x30, 0xFE, 0x00, // ## ####### + 0x30, 0xFE, 0x00, // ## ####### + 0x30, 0x0C, 0x00, // ## ## + 0x38, 0x0C, 0x00, // ### ## + 0x1C, 0x1C, 0x00, // ### ### + 0x0F, 0xFC, 0x00, // ########## + 0x03, 0xF0, 0x00, // ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2880 'H' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7E, 0x7E, 0x00, // ###### ###### + 0x7E, 0x7E, 0x00, // ###### ###### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x1F, 0xF8, 0x00, // ########## + 0x1F, 0xF8, 0x00, // ########## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x7E, 0x7E, 0x00, // ###### ###### + 0x7E, 0x7E, 0x00, // ###### ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @2952 'I' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0xF8, 0x00, // ########## + 0x1F, 0xF8, 0x00, // ########## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x1F, 0xF8, 0x00, // ########## + 0x1F, 0xF8, 0x00, // ########## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3024 'J' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xFE, 0x00, // ########## + 0x07, 0xFE, 0x00, // ########## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x30, 0x30, 0x00, // ## ## + 0x30, 0x30, 0x00, // ## ## + 0x30, 0x30, 0x00, // ## ## + 0x30, 0x30, 0x00, // ## ## + 0x30, 0x60, 0x00, // ## ## + 0x3F, 0xE0, 0x00, // ######### + 0x0F, 0x80, 0x00, // ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3096 'K' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7F, 0x3E, 0x00, // ####### ##### + 0x7F, 0x3E, 0x00, // ####### ##### + 0x18, 0x30, 0x00, // ## ## + 0x18, 0x60, 0x00, // ## ## + 0x18, 0xC0, 0x00, // ## ## + 0x19, 0x80, 0x00, // ## ## + 0x1B, 0x80, 0x00, // ## ### + 0x1F, 0xC0, 0x00, // ####### + 0x1C, 0xE0, 0x00, // ### ### + 0x18, 0x70, 0x00, // ## ### + 0x18, 0x30, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x7F, 0x1F, 0x00, // ####### ##### + 0x7F, 0x1F, 0x00, // ####### ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3168 'L' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7F, 0x80, 0x00, // ######## + 0x7F, 0x80, 0x00, // ######## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x0C, 0x00, // ## ## + 0x0C, 0x0C, 0x00, // ## ## + 0x0C, 0x0C, 0x00, // ## ## + 0x0C, 0x0C, 0x00, // ## ## + 0x7F, 0xFC, 0x00, // ############# + 0x7F, 0xFC, 0x00, // ############# + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3240 'M' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0xF0, 0x0F, 0x00, // #### #### + 0xF8, 0x1F, 0x00, // ##### ##### + 0x38, 0x1C, 0x00, // ### ### + 0x3C, 0x3C, 0x00, // #### #### + 0x3C, 0x3C, 0x00, // #### #### + 0x36, 0x6C, 0x00, // ## ## ## ## + 0x36, 0x6C, 0x00, // ## ## ## ## + 0x33, 0xCC, 0x00, // ## #### ## + 0x33, 0xCC, 0x00, // ## #### ## + 0x31, 0x8C, 0x00, // ## ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0xFE, 0x7F, 0x00, // ####### ####### + 0xFE, 0x7F, 0x00, // ####### ####### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3312 'N' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x78, 0xFE, 0x00, // #### ####### + 0x78, 0xFE, 0x00, // #### ####### + 0x1C, 0x18, 0x00, // ### ## + 0x1E, 0x18, 0x00, // #### ## + 0x1F, 0x18, 0x00, // ##### ## + 0x1B, 0x18, 0x00, // ## ## ## + 0x1B, 0x98, 0x00, // ## ### ## + 0x19, 0xD8, 0x00, // ## ### ## + 0x18, 0xD8, 0x00, // ## ## ## + 0x18, 0xF8, 0x00, // ## ##### + 0x18, 0x78, 0x00, // ## #### + 0x18, 0x38, 0x00, // ## ### + 0x7F, 0x18, 0x00, // ####### ## + 0x7F, 0x18, 0x00, // ####### ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3384 'O' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xC0, 0x00, // #### + 0x0F, 0xF0, 0x00, // ######## + 0x1C, 0x38, 0x00, // ### ### + 0x18, 0x18, 0x00, // ## ## + 0x38, 0x1C, 0x00, // ### ### + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x38, 0x1C, 0x00, // ### ### + 0x18, 0x18, 0x00, // ## ## + 0x1C, 0x38, 0x00, // ### ### + 0x0F, 0xF0, 0x00, // ######## + 0x03, 0xC0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3456 'P' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x3F, 0xF0, 0x00, // ########## + 0x3F, 0xF8, 0x00, // ########### + 0x0C, 0x1C, 0x00, // ## ### + 0x0C, 0x0C, 0x00, // ## ## + 0x0C, 0x0C, 0x00, // ## ## + 0x0C, 0x0C, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x0F, 0xF8, 0x00, // ######### + 0x0F, 0xE0, 0x00, // ####### + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x3F, 0xC0, 0x00, // ######## + 0x3F, 0xC0, 0x00, // ######## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3528 'Q' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xC0, 0x00, // #### + 0x0F, 0xF0, 0x00, // ######## + 0x1C, 0x38, 0x00, // ### ### + 0x18, 0x18, 0x00, // ## ## + 0x38, 0x1C, 0x00, // ### ### + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x38, 0x1C, 0x00, // ### ### + 0x18, 0x18, 0x00, // ## ## + 0x1C, 0x38, 0x00, // ### ### + 0x0F, 0xF0, 0x00, // ######## + 0x07, 0xC0, 0x00, // ##### + 0x07, 0xCC, 0x00, // ##### ## + 0x0F, 0xFC, 0x00, // ########## + 0x0C, 0x38, 0x00, // ## ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3600 'R' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7F, 0xE0, 0x00, // ########## + 0x7F, 0xF0, 0x00, // ########### + 0x18, 0x38, 0x00, // ## ### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x1F, 0xF0, 0x00, // ######### + 0x1F, 0xC0, 0x00, // ####### + 0x18, 0xE0, 0x00, // ## ### + 0x18, 0x70, 0x00, // ## ### + 0x18, 0x30, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x7F, 0x1E, 0x00, // ####### #### + 0x7F, 0x0E, 0x00, // ####### ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3672 'S' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xD8, 0x00, // ##### ## + 0x0F, 0xF8, 0x00, // ######### + 0x1C, 0x38, 0x00, // ### ### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x1E, 0x00, 0x00, // #### + 0x0F, 0xC0, 0x00, // ###### + 0x03, 0xF0, 0x00, // ###### + 0x00, 0x78, 0x00, // #### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x1C, 0x38, 0x00, // ### ### + 0x1F, 0xF0, 0x00, // ######### + 0x1B, 0xE0, 0x00, // ## ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3744 'T' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x3F, 0xFC, 0x00, // ############ + 0x3F, 0xFC, 0x00, // ############ + 0x31, 0x8C, 0x00, // ## ## ## + 0x31, 0x8C, 0x00, // ## ## ## + 0x31, 0x8C, 0x00, // ## ## ## + 0x31, 0x8C, 0x00, // ## ## ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x0F, 0xF0, 0x00, // ######## + 0x0F, 0xF0, 0x00, // ######## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3816 'U' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7E, 0x7E, 0x00, // ###### ###### + 0x7E, 0x7E, 0x00, // ###### ###### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x0F, 0xF0, 0x00, // ######## + 0x03, 0xC0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3888 'V' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7F, 0x7F, 0x00, // ####### ####### + 0x7F, 0x7F, 0x00, // ####### ####### + 0x18, 0x0C, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x06, 0x30, 0x00, // ## ## + 0x06, 0x30, 0x00, // ## ## + 0x03, 0x60, 0x00, // ## ## + 0x03, 0x60, 0x00, // ## ## + 0x03, 0x60, 0x00, // ## ## + 0x01, 0xC0, 0x00, // ### + 0x01, 0xC0, 0x00, // ### + 0x00, 0x80, 0x00, // # + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @3960 'W' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0xFE, 0x3F, 0x80, // ####### ####### + 0xFE, 0x3F, 0x80, // ####### ####### + 0x30, 0x06, 0x00, // ## ## + 0x30, 0x06, 0x00, // ## ## + 0x30, 0x86, 0x00, // ## # ## + 0x19, 0xCC, 0x00, // ## ### ## + 0x19, 0xCC, 0x00, // ## ### ## + 0x1B, 0x6C, 0x00, // ## ## ## ## + 0x1B, 0x6C, 0x00, // ## ## ## ## + 0x1E, 0x7C, 0x00, // #### ##### + 0x0E, 0x38, 0x00, // ### ### + 0x0E, 0x38, 0x00, // ### ### + 0x0C, 0x18, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4032 'X' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7E, 0x7E, 0x00, // ###### ###### + 0x7E, 0x7E, 0x00, // ###### ###### + 0x18, 0x18, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x03, 0xC0, 0x00, // #### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x03, 0xC0, 0x00, // #### + 0x06, 0x60, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x7E, 0x7E, 0x00, // ###### ###### + 0x7E, 0x7E, 0x00, // ###### ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4104 'Y' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7C, 0x7E, 0x00, // ##### ###### + 0x7C, 0x7E, 0x00, // ##### ###### + 0x18, 0x18, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x03, 0xC0, 0x00, // #### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x0F, 0xF0, 0x00, // ######## + 0x0F, 0xF0, 0x00, // ######## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4176 'Z' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0xF8, 0x00, // ########## + 0x1F, 0xF8, 0x00, // ########## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x30, 0x00, // ## ## + 0x18, 0x60, 0x00, // ## ## + 0x18, 0xC0, 0x00, // ## ## + 0x01, 0x80, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x06, 0x18, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x3F, 0xF8, 0x00, // ########### + 0x3F, 0xF8, 0x00, // ########### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4248 '[' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x01, 0xF0, 0x00, // ##### + 0x01, 0xF0, 0x00, // ##### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0xF0, 0x00, // ##### + 0x01, 0xF0, 0x00, // ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4320 '\' (17 pixels wide) + 0x18, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x1C, 0x00, 0x00, // ### + 0x0C, 0x00, 0x00, // ## + 0x0E, 0x00, 0x00, // ### + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x00, 0xC0, 0x00, // ## + 0x00, 0xC0, 0x00, // ## + 0x00, 0x60, 0x00, // ## + 0x00, 0x60, 0x00, // ## + 0x00, 0x70, 0x00, // ### + 0x00, 0x30, 0x00, // ## + 0x00, 0x38, 0x00, // ### + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4392 ']' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x0F, 0x80, 0x00, // ##### + 0x0F, 0x80, 0x00, // ##### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x0F, 0x80, 0x00, // ##### + 0x0F, 0x80, 0x00, // ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4464 '^' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x80, 0x00, // # + 0x01, 0xC0, 0x00, // ### + 0x03, 0xE0, 0x00, // ##### + 0x07, 0x70, 0x00, // ### ### + 0x06, 0x30, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x10, 0x04, 0x00, // # # + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4536 '_' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0xFF, 0xFF, 0x00, // ################ + 0xFF, 0xFF, 0x00, // ################ + + // @4608 '`' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x03, 0x00, 0x00, // ## + 0x03, 0x80, 0x00, // ### + 0x00, 0xE0, 0x00, // ### + 0x00, 0x60, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4680 'a' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x0F, 0xC0, 0x00, // ###### + 0x1F, 0xE0, 0x00, // ######## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x07, 0xF0, 0x00, // ####### + 0x1F, 0xF0, 0x00, // ######### + 0x38, 0x30, 0x00, // ### ## + 0x30, 0x30, 0x00, // ## ## + 0x30, 0x70, 0x00, // ## ### + 0x1F, 0xFC, 0x00, // ########### + 0x0F, 0xBC, 0x00, // ##### #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4752 'b' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x78, 0x00, 0x00, // #### + 0x78, 0x00, 0x00, // #### + 0x18, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x1B, 0xE0, 0x00, // ## ##### + 0x1F, 0xF8, 0x00, // ########## + 0x1C, 0x18, 0x00, // ### ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x1C, 0x18, 0x00, // ### ## + 0x7F, 0xF8, 0x00, // ############ + 0x7B, 0xE0, 0x00, // #### ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4824 'c' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xEC, 0x00, // ##### ## + 0x0F, 0xFC, 0x00, // ########## + 0x1C, 0x1C, 0x00, // ### ### + 0x38, 0x0C, 0x00, // ### ## + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x00, 0x00, // ## + 0x30, 0x00, 0x00, // ## + 0x38, 0x0C, 0x00, // ### ## + 0x1C, 0x1C, 0x00, // ### ### + 0x0F, 0xF8, 0x00, // ######### + 0x03, 0xF0, 0x00, // ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4896 'd' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x78, 0x00, // #### + 0x00, 0x78, 0x00, // #### + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x07, 0xD8, 0x00, // ##### ## + 0x1F, 0xF8, 0x00, // ########## + 0x18, 0x38, 0x00, // ## ### + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x1F, 0xFE, 0x00, // ############ + 0x07, 0xDE, 0x00, // ##### #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @4968 'e' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xE0, 0x00, // ###### + 0x1F, 0xF8, 0x00, // ########## + 0x18, 0x18, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x3F, 0xFC, 0x00, // ############ + 0x3F, 0xFC, 0x00, // ############ + 0x30, 0x00, 0x00, // ## + 0x30, 0x00, 0x00, // ## + 0x18, 0x0C, 0x00, // ## ## + 0x1F, 0xFC, 0x00, // ########### + 0x07, 0xF0, 0x00, // ####### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5040 'f' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x01, 0xFC, 0x00, // ####### + 0x03, 0xFC, 0x00, // ######## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x3F, 0xF8, 0x00, // ########### + 0x3F, 0xF8, 0x00, // ########### + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x3F, 0xF0, 0x00, // ########## + 0x3F, 0xF0, 0x00, // ########## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5112 'g' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xDE, 0x00, // ##### #### + 0x1F, 0xFE, 0x00, // ############ + 0x18, 0x38, 0x00, // ## ### + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x1F, 0xF8, 0x00, // ########## + 0x07, 0xD8, 0x00, // ##### ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x38, 0x00, // ### + 0x0F, 0xF0, 0x00, // ######## + 0x0F, 0xC0, 0x00, // ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5184 'h' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x78, 0x00, 0x00, // #### + 0x78, 0x00, 0x00, // #### + 0x18, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x1B, 0xE0, 0x00, // ## ##### + 0x1F, 0xF0, 0x00, // ######### + 0x1C, 0x38, 0x00, // ### ### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x7E, 0x7E, 0x00, // ###### ###### + 0x7E, 0x7E, 0x00, // ###### ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5256 'i' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0x80, 0x00, // ###### + 0x1F, 0x80, 0x00, // ###### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x3F, 0xFC, 0x00, // ############ + 0x3F, 0xFC, 0x00, // ############ + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5328 'j' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0xC0, 0x00, // ## + 0x00, 0xC0, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0xF0, 0x00, // ######### + 0x1F, 0xF0, 0x00, // ######### + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x30, 0x00, // ## + 0x00, 0x70, 0x00, // ### + 0x1F, 0xE0, 0x00, // ######## + 0x1F, 0x80, 0x00, // ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5400 'k' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x3C, 0x00, 0x00, // #### + 0x3C, 0x00, 0x00, // #### + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0xF8, 0x00, // ## ##### + 0x0C, 0xF8, 0x00, // ## ##### + 0x0C, 0xC0, 0x00, // ## ## + 0x0D, 0x80, 0x00, // ## ## + 0x0F, 0x80, 0x00, // ##### + 0x0F, 0x00, 0x00, // #### + 0x0F, 0x80, 0x00, // ##### + 0x0D, 0xC0, 0x00, // ## ### + 0x0C, 0xE0, 0x00, // ## ### + 0x3C, 0x7C, 0x00, // #### ##### + 0x3C, 0x7C, 0x00, // #### ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5472 'l' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0x80, 0x00, // ###### + 0x1F, 0x80, 0x00, // ###### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x3F, 0xFC, 0x00, // ############ + 0x3F, 0xFC, 0x00, // ############ + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5544 'm' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0xF7, 0x78, 0x00, // #### ### #### + 0xFF, 0xFC, 0x00, // ############## + 0x39, 0xCC, 0x00, // ### ### ## + 0x31, 0x8C, 0x00, // ## ## ## + 0x31, 0x8C, 0x00, // ## ## ## + 0x31, 0x8C, 0x00, // ## ## ## + 0x31, 0x8C, 0x00, // ## ## ## + 0x31, 0x8C, 0x00, // ## ## ## + 0x31, 0x8C, 0x00, // ## ## ## + 0xFD, 0xEF, 0x00, // ###### #### #### + 0xFD, 0xEF, 0x00, // ###### #### #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5616 'n' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7B, 0xE0, 0x00, // #### ##### + 0x7F, 0xF0, 0x00, // ########### + 0x1C, 0x38, 0x00, // ### ### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x7E, 0x7E, 0x00, // ###### ###### + 0x7E, 0x7E, 0x00, // ###### ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5688 'o' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x03, 0xC0, 0x00, // #### + 0x0F, 0xF0, 0x00, // ######## + 0x1C, 0x38, 0x00, // ### ### + 0x38, 0x1C, 0x00, // ### ### + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x30, 0x0C, 0x00, // ## ## + 0x38, 0x1C, 0x00, // ### ### + 0x1C, 0x38, 0x00, // ### ### + 0x0F, 0xF0, 0x00, // ######## + 0x03, 0xC0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5760 'p' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7B, 0xE0, 0x00, // #### ##### + 0x7F, 0xF8, 0x00, // ############ + 0x1C, 0x18, 0x00, // ### ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x18, 0x0C, 0x00, // ## ## + 0x1C, 0x18, 0x00, // ### ## + 0x1F, 0xF8, 0x00, // ########## + 0x1B, 0xE0, 0x00, // ## ##### + 0x18, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x18, 0x00, 0x00, // ## + 0x7F, 0x00, 0x00, // ####### + 0x7F, 0x00, 0x00, // ####### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5832 'q' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xDE, 0x00, // ##### #### + 0x1F, 0xFE, 0x00, // ############ + 0x18, 0x38, 0x00, // ## ### + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x30, 0x18, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x1F, 0xF8, 0x00, // ########## + 0x07, 0xD8, 0x00, // ##### ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x00, 0x18, 0x00, // ## + 0x00, 0xFE, 0x00, // ####### + 0x00, 0xFE, 0x00, // ####### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5904 'r' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x3E, 0x78, 0x00, // ##### #### + 0x3E, 0xFC, 0x00, // ##### ###### + 0x07, 0xCC, 0x00, // ##### ## + 0x07, 0x00, 0x00, // ### + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x06, 0x00, 0x00, // ## + 0x3F, 0xF0, 0x00, // ########## + 0x3F, 0xF0, 0x00, // ########## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @5976 's' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0xF8, 0x00, // ######## + 0x0F, 0xF8, 0x00, // ######### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x1F, 0x80, 0x00, // ###### + 0x0F, 0xF0, 0x00, // ######## + 0x00, 0xF8, 0x00, // ##### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x1F, 0xF0, 0x00, // ######### + 0x1F, 0xE0, 0x00, // ######## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6048 't' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x3F, 0xF0, 0x00, // ########## + 0x3F, 0xF0, 0x00, // ########## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x00, 0x00, // ## + 0x0C, 0x1C, 0x00, // ## ### + 0x07, 0xFC, 0x00, // ######### + 0x03, 0xF0, 0x00, // ###### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6120 'u' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x78, 0x78, 0x00, // #### #### + 0x78, 0x78, 0x00, // #### #### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x38, 0x00, // ## ### + 0x0F, 0xFE, 0x00, // ########### + 0x07, 0xDE, 0x00, // ##### #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6192 'v' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7C, 0x3E, 0x00, // ##### ##### + 0x7C, 0x3E, 0x00, // ##### ##### + 0x18, 0x18, 0x00, // ## ## + 0x18, 0x18, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x07, 0xE0, 0x00, // ###### + 0x03, 0xC0, 0x00, // #### + 0x03, 0xC0, 0x00, // #### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6264 'w' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x78, 0x3C, 0x00, // #### #### + 0x78, 0x3C, 0x00, // #### #### + 0x31, 0x18, 0x00, // ## # ## + 0x33, 0x98, 0x00, // ## ### ## + 0x33, 0x98, 0x00, // ## ### ## + 0x1A, 0xB0, 0x00, // ## # # ## + 0x1E, 0xF0, 0x00, // #### #### + 0x1E, 0xF0, 0x00, // #### #### + 0x1C, 0x60, 0x00, // ### ## + 0x0C, 0x60, 0x00, // ## ## + 0x0C, 0x60, 0x00, // ## ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6336 'x' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x3E, 0x7C, 0x00, // ##### ##### + 0x3E, 0x7C, 0x00, // ##### ##### + 0x0C, 0x30, 0x00, // ## ## + 0x06, 0x60, 0x00, // ## ## + 0x03, 0xC0, 0x00, // #### + 0x01, 0x80, 0x00, // ## + 0x03, 0xC0, 0x00, // #### + 0x06, 0x60, 0x00, // ## ## + 0x0C, 0x30, 0x00, // ## ## + 0x3E, 0x7C, 0x00, // ##### ##### + 0x3E, 0x7C, 0x00, // ##### ##### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6408 'y' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x7E, 0x1F, 0x00, // ###### ##### + 0x7E, 0x1F, 0x00, // ###### ##### + 0x18, 0x0C, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x06, 0x30, 0x00, // ## ## + 0x06, 0x30, 0x00, // ## ## + 0x03, 0x60, 0x00, // ## ## + 0x03, 0xE0, 0x00, // ##### + 0x01, 0xC0, 0x00, // ### + 0x00, 0xC0, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x3F, 0xC0, 0x00, // ######## + 0x3F, 0xC0, 0x00, // ######## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6480 'z' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x1F, 0xF8, 0x00, // ########## + 0x1F, 0xF8, 0x00, // ########## + 0x18, 0x30, 0x00, // ## ## + 0x18, 0x60, 0x00, // ## ## + 0x00, 0xC0, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x03, 0x00, 0x00, // ## + 0x06, 0x18, 0x00, // ## ## + 0x0C, 0x18, 0x00, // ## ## + 0x1F, 0xF8, 0x00, // ########## + 0x1F, 0xF8, 0x00, // ########## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6552 '{' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0xE0, 0x00, // ### + 0x01, 0xE0, 0x00, // #### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x03, 0x80, 0x00, // ### + 0x07, 0x00, 0x00, // ### + 0x03, 0x80, 0x00, // ### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0xE0, 0x00, // #### + 0x00, 0xE0, 0x00, // ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6624 '|' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6696 '}' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x07, 0x00, 0x00, // ### + 0x07, 0x80, 0x00, // #### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0xC0, 0x00, // ### + 0x00, 0xE0, 0x00, // ### + 0x01, 0xC0, 0x00, // ### + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x01, 0x80, 0x00, // ## + 0x07, 0x80, 0x00, // #### + 0x07, 0x00, 0x00, // ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + + // @6768 '~' (17 pixels wide) + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x0E, 0x00, 0x00, // ### + 0x1F, 0x18, 0x00, // ##### ## + 0x3B, 0xB8, 0x00, // ### ### ### + 0x31, 0xF0, 0x00, // ## ##### + 0x00, 0xE0, 0x00, // ### + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, // + }; + +epaper_font_t epaper_font_8 = { + 5, /* width */ + 8, /* height */ + Font8_Table, +}; + +epaper_font_t epaper_font_12 = { + 7, /* width */ + 12, /* height */ + Font12_Table, +}; + +epaper_font_t epaper_font_16 = { + 11, /* width */ + 16, /* height */ + Font16_Table, +}; + +epaper_font_t epaper_font_20 = { + 14, /* width */ + 20, /* height */ + Font20_Table, +}; + +epaper_font_t epaper_font_24 = { + 17, /* width */ + 24, /* height */ + Font24_Table, +}; + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper_fonts.h b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper_fonts.h new file mode 100644 index 000000000..6cbdc4673 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/epaper_fonts.h @@ -0,0 +1,36 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef _IOT_EPAPER_FONTS_H_ +#define _IOT_EPAPER_FONTS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif +#include +#include "epaper-29-ws.h" + +extern epaper_font_t epaper_font_24; +extern epaper_font_t epaper_font_20; +extern epaper_font_t epaper_font_16; +extern epaper_font_t epaper_font_12; +extern epaper_font_t epaper_font_8; + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font16.c b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font16.c new file mode 100644 index 000000000..e9276914d --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font16.c @@ -0,0 +1,1765 @@ +/** + ****************************************************************************** + * @file font16.c + * @author MCD Application Team + * @version V1.0.0 + * @date 18-February-2014 + * @brief This file provides text font16 for STM32xx-EVAL's LCD driver. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2014 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "fonts.h" +#include + +// +// Font data for Courier New 12pt +// + +const uint8_t Font16_Table[] PROGMEM = +{ + // @0 ' ' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @32 '!' (11 pixels wide) + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @64 '"' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1D, 0xC0, // ### ### + 0x1D, 0xC0, // ### ### + 0x08, 0x80, // # # + 0x08, 0x80, // # # + 0x08, 0x80, // # # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @96 '#' (11 pixels wide) + 0x00, 0x00, // + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x3F, 0xC0, // ######## + 0x1B, 0x00, // ## ## + 0x3F, 0xC0, // ######## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @128 '$' (11 pixels wide) + 0x04, 0x00, // # + 0x1F, 0x80, // ###### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x38, 0x00, // ### + 0x1E, 0x00, // #### + 0x0F, 0x00, // #### + 0x03, 0x80, // ### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @160 '%' (11 pixels wide) + 0x00, 0x00, // + 0x18, 0x00, // ## + 0x24, 0x00, // # # + 0x24, 0x00, // # # + 0x18, 0xC0, // ## ## + 0x07, 0x80, // #### + 0x1E, 0x00, // #### + 0x31, 0x80, // ## ## + 0x02, 0x40, // # # + 0x02, 0x40, // # # + 0x01, 0x80, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @192 '&' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x0F, 0x00, // #### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x1D, 0x80, // ### ## + 0x37, 0x00, // ## ### + 0x33, 0x00, // ## ## + 0x1D, 0x80, // ### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @224 ''' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x02, 0x00, // # + 0x02, 0x00, // # + 0x02, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @256 '(' (11 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0E, 0x00, // ### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0E, 0x00, // ### + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @288 ')' (11 pixels wide) + 0x00, 0x00, // + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x1C, 0x00, // ### + 0x18, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @320 '*' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x3F, 0xC0, // ######## + 0x0F, 0x00, // #### + 0x1F, 0x80, // ###### + 0x19, 0x80, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @352 '+' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x3F, 0x80, // ####### + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x04, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @384 ',' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x0C, 0x00, // ## + 0x08, 0x00, // # + 0x08, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + + // @416 '-' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @448 '.' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @480 '/' (11 pixels wide) + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @512 '0' (11 pixels wide) + 0x00, 0x00, // + 0x0E, 0x00, // ### + 0x1B, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x0E, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @544 '1' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x3E, 0x00, // ##### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @576 '2' (11 pixels wide) + 0x00, 0x00, // + 0x0F, 0x00, // #### + 0x19, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x30, 0x00, // ## + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @608 '3' (11 pixels wide) + 0x00, 0x00, // + 0x3F, 0x00, // ###### + 0x61, 0x80, // ## ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x1F, 0x00, // ##### + 0x03, 0x80, // ### + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x61, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @640 '4' (11 pixels wide) + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x0F, 0x00, // #### + 0x0B, 0x00, // # ## + 0x1B, 0x00, // ## ## + 0x13, 0x00, // # ## + 0x33, 0x00, // ## ## + 0x3F, 0x80, // ####### + 0x03, 0x00, // ## + 0x0F, 0x80, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @672 '5' (11 pixels wide) + 0x00, 0x00, // + 0x1F, 0x80, // ###### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x1F, 0x00, // ##### + 0x11, 0x80, // # ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x21, 0x80, // # ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @704 '6' (11 pixels wide) + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x1C, 0x00, // ### + 0x18, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x00, // ## ### + 0x39, 0x80, // ### ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x19, 0x80, // ## ## + 0x0F, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @736 '7' (11 pixels wide) + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x43, 0x00, // # ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @768 '8' (11 pixels wide) + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @800 '9' (11 pixels wide) + 0x00, 0x00, // + 0x1E, 0x00, // #### + 0x33, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0x80, // ### ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x07, 0x00, // ### + 0x3C, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @832 ':' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @864 ';' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x08, 0x00, // # + 0x08, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @896 '<' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0xC0, // ## + 0x03, 0x00, // ## + 0x04, 0x00, // # + 0x18, 0x00, // ## + 0x60, 0x00, // ## + 0x18, 0x00, // ## + 0x04, 0x00, // # + 0x03, 0x00, // ## + 0x00, 0xC0, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @928 '=' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0xC0, // ######### + 0x00, 0x00, // + 0x7F, 0xC0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @960 '>' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x60, 0x00, // ## + 0x18, 0x00, // ## + 0x04, 0x00, // # + 0x03, 0x00, // ## + 0x00, 0xC0, // ## + 0x03, 0x00, // ## + 0x04, 0x00, // # + 0x18, 0x00, // ## + 0x60, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @992 '?' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x01, 0x80, // ## + 0x07, 0x00, // ### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1024 '@' (11 pixels wide) + 0x00, 0x00, // + 0x0E, 0x00, // ### + 0x11, 0x00, // # # + 0x21, 0x00, // # # + 0x21, 0x00, // # # + 0x27, 0x00, // # ### + 0x29, 0x00, // # # # + 0x29, 0x00, // # # # + 0x27, 0x00, // # ### + 0x20, 0x00, // # + 0x11, 0x00, // # # + 0x0E, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1056 'A' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x00, // ###### + 0x0F, 0x00, // #### + 0x09, 0x00, // # # + 0x19, 0x80, // ## ## + 0x19, 0x80, // ## ## + 0x1F, 0x80, // ###### + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x79, 0xE0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1088 'B' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7F, 0x00, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1120 'C' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x40, // ##### # + 0x30, 0xC0, // ## ## + 0x60, 0x40, // ## # + 0x60, 0x00, // ## + 0x60, 0x00, // ## + 0x60, 0x00, // ## + 0x60, 0x40, // ## # + 0x30, 0x80, // ## # + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1152 'D' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x31, 0x80, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x31, 0x80, // ## ## + 0x7F, 0x00, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1184 'E' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x80, // ######## + 0x30, 0x80, // ## # + 0x30, 0x80, // ## # + 0x32, 0x00, // ## # + 0x3E, 0x00, // ##### + 0x32, 0x00, // ## # + 0x30, 0x80, // ## # + 0x30, 0x80, // ## # + 0x7F, 0x80, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1216 'F' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0xC0, // ######### + 0x30, 0x40, // ## # + 0x30, 0x40, // ## # + 0x32, 0x00, // ## # + 0x3E, 0x00, // ##### + 0x32, 0x00, // ## # + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x7C, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1248 'G' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1E, 0x80, // #### # + 0x31, 0x80, // ## ## + 0x60, 0x80, // ## # + 0x60, 0x00, // ## + 0x60, 0x00, // ## + 0x67, 0xC0, // ## ##### + 0x61, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1280 'H' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x80, // ####### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1312 'I' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xC0, // ######## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1344 'J' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xC0, // ####### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x63, 0x00, // ## ## + 0x63, 0x00, // ## ## + 0x63, 0x00, // ## ## + 0x3E, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1376 'K' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x33, 0x00, // ## ## + 0x36, 0x00, // ## ## + 0x3C, 0x00, // #### + 0x3E, 0x00, // ##### + 0x33, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x79, 0xC0, // #### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1408 'L' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7E, 0x00, // ###### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x40, // ## # + 0x18, 0x40, // ## # + 0x18, 0x40, // ## # + 0x7F, 0xC0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1440 'M' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0xE0, 0xE0, // ### ### + 0x60, 0xC0, // ## ## + 0x71, 0xC0, // ### ### + 0x7B, 0xC0, // #### #### + 0x6A, 0xC0, // ## # # ## + 0x6E, 0xC0, // ## ### ## + 0x64, 0xC0, // ## # ## + 0x60, 0xC0, // ## ## + 0xFB, 0xE0, // ##### ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1472 'N' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x73, 0xC0, // ### #### + 0x31, 0x80, // ## ## + 0x39, 0x80, // ### ## + 0x3D, 0x80, // #### ## + 0x35, 0x80, // ## # ## + 0x37, 0x80, // ## #### + 0x33, 0x80, // ## ### + 0x31, 0x80, // ## ## + 0x79, 0x80, // #### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1504 'O' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1536 'P' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x7E, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1568 'Q' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x0C, 0xC0, // ## ## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1600 'R' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x00, // ####### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3E, 0x00, // ##### + 0x33, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7C, 0xE0, // ##### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1632 'S' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x80, // ###### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x38, 0x00, // ### + 0x1F, 0x00, // ##### + 0x03, 0x80, // ### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1664 'T' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x80, // ######## + 0x4C, 0x80, // # ## # + 0x4C, 0x80, // # ## # + 0x4C, 0x80, // # ## # + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1696 'U' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1728 'V' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x0A, 0x00, // # # + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1760 'W' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0xFB, 0xE0, // ##### ##### + 0x60, 0xC0, // ## ## + 0x64, 0xC0, // ## # ## + 0x6E, 0xC0, // ## ### ## + 0x6E, 0xC0, // ## ### ## + 0x2A, 0x80, // # # # # + 0x3B, 0x80, // ### ### + 0x3B, 0x80, // ### ### + 0x31, 0x80, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1792 'X' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x1B, 0x00, // ## ## + 0x31, 0x80, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1824 'Y' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x79, 0xE0, // #### #### + 0x30, 0xC0, // ## ## + 0x19, 0x80, // ## ## + 0x0F, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1856 'Z' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x80, // ####### + 0x21, 0x80, // # ## + 0x23, 0x00, // # ## + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x0C, 0x00, // ## + 0x18, 0x80, // ## # + 0x30, 0x80, // ## # + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1888 '[' (11 pixels wide) + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1920 '\' (11 pixels wide) + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1952 ']' (11 pixels wide) + 0x00, 0x00, // + 0x1E, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1E, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1984 '^' (11 pixels wide) + 0x04, 0x00, // # + 0x0A, 0x00, // # # + 0x0A, 0x00, // # # + 0x11, 0x00, // # # + 0x20, 0x80, // # # + 0x20, 0x80, // # # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2016 '_' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0xFF, 0xE0, // ########### + + // @2048 '`' (11 pixels wide) + 0x08, 0x00, // # + 0x04, 0x00, // # + 0x02, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2080 'a' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x1F, 0x80, // ###### + 0x31, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0xC0, // ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2112 'b' (11 pixels wide) + 0x00, 0x00, // + 0x70, 0x00, // ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x00, // ## ### + 0x39, 0x80, // ### ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x39, 0x80, // ### ## + 0x77, 0x00, // ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2144 'c' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1E, 0x80, // #### # + 0x31, 0x80, // ## ## + 0x60, 0x80, // ## # + 0x60, 0x00, // ## + 0x60, 0x80, // ## # + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2176 'd' (11 pixels wide) + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x1D, 0x80, // ### ## + 0x33, 0x80, // ## ### + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0xC0, // ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2208 'e' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x60, 0xC0, // ## ## + 0x7F, 0xC0, // ######### + 0x60, 0x00, // ## + 0x30, 0xC0, // ## ## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2240 'f' (11 pixels wide) + 0x00, 0x00, // + 0x07, 0xE0, // ###### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0x80, // ####### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2272 'g' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1D, 0xC0, // ### ### + 0x33, 0x80, // ## ### + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0x80, // ### ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2304 'h' (11 pixels wide) + 0x00, 0x00, // + 0x70, 0x00, // ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x00, // ## ### + 0x39, 0x80, // ### ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2336 'i' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x00, 0x00, // + 0x1E, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2368 'j' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x00, 0x00, // + 0x3F, 0x00, // ###### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x3E, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2400 'k' (11 pixels wide) + 0x00, 0x00, // + 0x70, 0x00, // ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x80, // ## #### + 0x36, 0x00, // ## ## + 0x3C, 0x00, // #### + 0x3C, 0x00, // #### + 0x36, 0x00, // ## ## + 0x33, 0x00, // ## ## + 0x77, 0xC0, // ### ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2432 'l' (11 pixels wide) + 0x00, 0x00, // + 0x1E, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2464 'm' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x80, // ######## + 0x36, 0xC0, // ## ## ## + 0x36, 0xC0, // ## ## ## + 0x36, 0xC0, // ## ## ## + 0x36, 0xC0, // ## ## ## + 0x36, 0xC0, // ## ## ## + 0x76, 0xE0, // ### ## ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2496 'n' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x77, 0x00, // ### ### + 0x39, 0x80, // ### ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2528 'o' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x31, 0x80, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x60, 0xC0, // ## ## + 0x31, 0x80, // ## ## + 0x1F, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2560 'p' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x77, 0x00, // ### ### + 0x39, 0x80, // ### ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x39, 0x80, // ### ## + 0x37, 0x00, // ## ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x7C, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2592 'q' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1D, 0xC0, // ### ### + 0x33, 0x80, // ## ### + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x61, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0x80, // ### ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2624 'r' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0x80, // #### ### + 0x1C, 0xC0, // ### ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x7F, 0x00, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2656 's' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x80, // ###### + 0x31, 0x80, // ## ## + 0x3C, 0x00, // #### + 0x1F, 0x00, // ##### + 0x03, 0x80, // ### + 0x31, 0x80, // ## ## + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2688 't' (11 pixels wide) + 0x00, 0x00, // + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x7F, 0x00, // ####### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x80, // ## # + 0x0F, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2720 'u' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x73, 0x80, // ### ### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x33, 0x80, // ## ### + 0x1D, 0xC0, // ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2752 'v' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x31, 0x80, // ## ## + 0x31, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x1B, 0x00, // ## ## + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2784 'w' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0xF1, 0xE0, // #### #### + 0x60, 0xC0, // ## ## + 0x64, 0xC0, // ## # ## + 0x6E, 0xC0, // ## ### ## + 0x3B, 0x80, // ### ### + 0x3B, 0x80, // ### ### + 0x31, 0x80, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2816 'x' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7B, 0xC0, // #### #### + 0x1B, 0x00, // ## ## + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x0E, 0x00, // ### + 0x1B, 0x00, // ## ## + 0x7B, 0xC0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2848 'y' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x79, 0xE0, // #### #### + 0x30, 0xC0, // ## ## + 0x19, 0x80, // ## ## + 0x19, 0x80, // ## ## + 0x0B, 0x00, // # ## + 0x0F, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x3E, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2880 'z' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x80, // ####### + 0x21, 0x80, // # ## + 0x03, 0x00, // ## + 0x0E, 0x00, // ### + 0x18, 0x00, // ## + 0x30, 0x80, // ## # + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2912 '{' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2944 '|' (11 pixels wide) + 0x00, 0x00, // + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2976 '}' (11 pixels wide) + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3008 '~' (11 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x18, 0x00, // ## + 0x24, 0x80, // # # # + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // +}; + +sFONT Font16 = { + Font16_Table, + 11, /* Width */ + 16, /* Height */ +}; + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font20.c b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font20.c new file mode 100644 index 000000000..17329b06f --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font20.c @@ -0,0 +1,2143 @@ +/** + ****************************************************************************** + * @file font20.c + * @author MCD Application Team + * @version V1.0.0 + * @date 18-February-2014 + * @brief This file provides text font20 for STM32xx-EVAL's LCD driver. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2014 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "fonts.h" +#include + +// Character bitmaps for Courier New 15pt +const uint8_t Font20_Table[] PROGMEM = +{ + // @0 ' ' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @40 '!' (14 pixels wide) + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x02, 0x00, // # + 0x02, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @80 '"' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1C, 0xE0, // ### ### + 0x1C, 0xE0, // ### ### + 0x1C, 0xE0, // ### ### + 0x08, 0x40, // # # + 0x08, 0x40, // # # + 0x08, 0x40, // # # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @120 '#' (14 pixels wide) + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @160 '$' (14 pixels wide) + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x07, 0xE0, // ###### + 0x0F, 0xE0, // ####### + 0x18, 0x60, // ## ## + 0x18, 0x00, // ## + 0x1F, 0x00, // ##### + 0x0F, 0xC0, // ###### + 0x00, 0xE0, // ### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x1F, 0xC0, // ####### + 0x1F, 0x80, // ###### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @200 '%' (14 pixels wide) + 0x00, 0x00, // + 0x1C, 0x00, // ### + 0x22, 0x00, // # # + 0x22, 0x00, // # # + 0x22, 0x00, // # # + 0x1C, 0x60, // ### ## + 0x01, 0xE0, // #### + 0x0F, 0x80, // ##### + 0x3C, 0x00, // #### + 0x31, 0xC0, // ## ### + 0x02, 0x20, // # # + 0x02, 0x20, // # # + 0x02, 0x20, // # # + 0x01, 0xC0, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @240 '&' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0xE0, // ##### + 0x0F, 0xE0, // ####### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x0F, 0x30, // #### ## + 0x1F, 0xF0, // ######### + 0x19, 0xE0, // ## #### + 0x18, 0xC0, // ## ## + 0x1F, 0xF0, // ######### + 0x07, 0xB0, // #### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @280 ''' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x01, 0x00, // # + 0x01, 0x00, // # + 0x01, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @320 '(' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @360 ')' (14 pixels wide) + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @400 '*' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1B, 0x60, // ## ## ## + 0x1F, 0xE0, // ######## + 0x07, 0x80, // #### + 0x07, 0x80, // #### + 0x0F, 0xC0, // ###### + 0x0C, 0xC0, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @440 '+' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @480 ',' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @520 '-' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @560 '.' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @600 '/' (14 pixels wide) + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @640 '0' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x1F, 0xC0, // ####### + 0x18, 0xC0, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x1F, 0xC0, // ####### + 0x0F, 0x80, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @680 '1' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x1F, 0x00, // ##### + 0x1F, 0x00, // ##### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @720 '2' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x1F, 0xC0, // ####### + 0x38, 0xE0, // ### ### + 0x30, 0x60, // ## ## + 0x00, 0x60, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x18, 0x00, // ## + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @760 '3' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x3F, 0xC0, // ######## + 0x30, 0xE0, // ## ### + 0x00, 0x60, // ## + 0x00, 0xE0, // ### + 0x07, 0xC0, // ##### + 0x07, 0xC0, // ##### + 0x00, 0xE0, // ### + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x60, 0xE0, // ## ### + 0x7F, 0xC0, // ######### + 0x3F, 0x80, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @800 '4' (14 pixels wide) + 0x00, 0x00, // + 0x01, 0xC0, // ### + 0x03, 0xC0, // #### + 0x03, 0xC0, // #### + 0x06, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x30, 0xC0, // ## ## + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x00, 0xC0, // ## + 0x03, 0xE0, // ##### + 0x03, 0xE0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @840 '5' (14 pixels wide) + 0x00, 0x00, // + 0x1F, 0xC0, // ####### + 0x1F, 0xC0, // ####### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x1F, 0x80, // ###### + 0x1F, 0xC0, // ####### + 0x18, 0xE0, // ## ### + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x30, 0xE0, // ## ### + 0x3F, 0xC0, // ######## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @880 '6' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0xE0, // ##### + 0x0F, 0xE0, // ####### + 0x1E, 0x00, // #### + 0x18, 0x00, // ## + 0x38, 0x00, // ### + 0x37, 0x80, // ## #### + 0x3F, 0xC0, // ######## + 0x38, 0xE0, // ### ### + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x18, 0xE0, // ## ### + 0x1F, 0xC0, // ####### + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @920 '7' (14 pixels wide) + 0x00, 0x00, // + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x30, 0x60, // ## ## + 0x00, 0x60, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @960 '8' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x1F, 0xC0, // ####### + 0x38, 0xE0, // ### ### + 0x30, 0x60, // ## ## + 0x38, 0xE0, // ### ### + 0x1F, 0xC0, // ####### + 0x1F, 0xC0, // ####### + 0x38, 0xE0, // ### ### + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x38, 0xE0, // ### ### + 0x1F, 0xC0, // ####### + 0x0F, 0x80, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1000 '9' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x00, // #### + 0x1F, 0xC0, // ####### + 0x38, 0xC0, // ### ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x38, 0xE0, // ### ### + 0x1F, 0xE0, // ######## + 0x0F, 0x60, // #### ## + 0x00, 0xE0, // ### + 0x00, 0xC0, // ## + 0x03, 0xC0, // #### + 0x3F, 0x80, // ####### + 0x3E, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1040 ':' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x03, 0x80, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1080 ';' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x01, 0xC0, // ### + 0x01, 0xC0, // ### + 0x01, 0xC0, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x04, 0x00, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1120 '<' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x30, // ## + 0x00, 0xF0, // #### + 0x03, 0xC0, // #### + 0x07, 0x00, // ### + 0x1C, 0x00, // ### + 0x78, 0x00, // #### + 0x1C, 0x00, // ### + 0x07, 0x00, // ### + 0x03, 0xC0, // #### + 0x00, 0xF0, // #### + 0x00, 0x30, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1160 '=' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0xF0, // ########### + 0x7F, 0xF0, // ########### + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0xF0, // ########### + 0x7F, 0xF0, // ########### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1200 '>' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x30, 0x00, // ## + 0x3C, 0x00, // #### + 0x0F, 0x00, // #### + 0x03, 0x80, // ### + 0x00, 0xE0, // ### + 0x00, 0x78, // #### + 0x00, 0xE0, // ### + 0x03, 0x80, // ### + 0x0F, 0x00, // #### + 0x3C, 0x00, // #### + 0x30, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1240 '?' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x0F, 0x80, // ##### + 0x1F, 0xC0, // ####### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x00, 0x60, // ## + 0x01, 0xC0, // ### + 0x03, 0x80, // ### + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1280 '@' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x80, // ### + 0x0C, 0x80, // ## # + 0x08, 0x40, // # # + 0x10, 0x40, // # # + 0x10, 0x40, // # # + 0x11, 0xC0, // # ### + 0x12, 0x40, // # # # + 0x12, 0x40, // # # # + 0x12, 0x40, // # # # + 0x11, 0xC0, // # ### + 0x10, 0x00, // # + 0x08, 0x00, // # + 0x08, 0x40, // # # + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1320 'A' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x80, // ###### + 0x1F, 0x80, // ###### + 0x03, 0x80, // ### + 0x06, 0xC0, // ## ## + 0x06, 0xC0, // ## ## + 0x0C, 0xC0, // ## ## + 0x0C, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x30, 0x30, // ## ## + 0x78, 0x78, // #### #### + 0x78, 0x78, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1360 'B' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x80, // ####### + 0x3F, 0xC0, // ######## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0xE0, // ## ### + 0x1F, 0xC0, // ####### + 0x1F, 0xE0, // ######## + 0x18, 0x70, // ## ### + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xE0, // ######### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1400 'C' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB0, // #### ## + 0x0F, 0xF0, // ######## + 0x1C, 0x70, // ### ### + 0x38, 0x30, // ### ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x38, 0x30, // ### ## + 0x1C, 0x70, // ### ### + 0x0F, 0xE0, // ####### + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1440 'D' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7F, 0x80, // ######## + 0x7F, 0xC0, // ######### + 0x30, 0xE0, // ## ### + 0x30, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x70, // ## ### + 0x30, 0xE0, // ## ### + 0x7F, 0xC0, // ######### + 0x7F, 0x80, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1480 'E' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x19, 0x80, // ## ## + 0x1F, 0x80, // ###### + 0x1F, 0x80, // ###### + 0x19, 0x80, // ## ## + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1520 'F' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x19, 0x80, // ## ## + 0x1F, 0x80, // ###### + 0x1F, 0x80, // ###### + 0x19, 0x80, // ## ## + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x3F, 0x00, // ###### + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1560 'G' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB0, // #### ## + 0x1F, 0xF0, // ######### + 0x18, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x31, 0xF8, // ## ###### + 0x31, 0xF8, // ## ###### + 0x30, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x1F, 0xF0, // ######### + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1600 'H' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1640 'I' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1680 'J' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x03, 0xF8, // ####### + 0x03, 0xF8, // ####### + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x30, 0xE0, // ## ### + 0x3F, 0xC0, // ######## + 0x0F, 0x80, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1720 'K' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3E, 0xF8, // ##### ##### + 0x3E, 0xF8, // ##### ##### + 0x18, 0xE0, // ## ### + 0x19, 0x80, // ## ## + 0x1B, 0x00, // ## ## + 0x1F, 0x00, // ##### + 0x1D, 0x80, // ### ## + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x18, 0x60, // ## ## + 0x3E, 0x78, // ##### #### + 0x3E, 0x38, // ##### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1760 'L' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0x00, // ###### + 0x3F, 0x00, // ###### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x30, // ## ## + 0x0C, 0x30, // ## ## + 0x0C, 0x30, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1800 'M' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0x78, // #### #### + 0x78, 0x78, // #### #### + 0x38, 0x70, // ### ### + 0x3C, 0xF0, // #### #### + 0x34, 0xB0, // ## # # ## + 0x37, 0xB0, // ## #### ## + 0x37, 0xB0, // ## #### ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x30, 0x30, // ## ## + 0x7C, 0xF8, // ##### ##### + 0x7C, 0xF8, // ##### ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1840 'N' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x39, 0xF0, // ### ##### + 0x3D, 0xF0, // #### ##### + 0x1C, 0x60, // ### ## + 0x1E, 0x60, // #### ## + 0x1E, 0x60, // #### ## + 0x1B, 0x60, // ## ## ## + 0x1B, 0x60, // ## ## ## + 0x19, 0xE0, // ## #### + 0x19, 0xE0, // ## #### + 0x18, 0xE0, // ## ### + 0x3E, 0xE0, // ##### ### + 0x3E, 0x60, // ##### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1880 'O' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x0F, 0xC0, // ###### + 0x1C, 0xE0, // ### ### + 0x38, 0x70, // ### ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x70, // ### ### + 0x1C, 0xE0, // ### ### + 0x0F, 0xC0, // ###### + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1920 'P' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xC0, // ######## + 0x3F, 0xE0, // ######### + 0x18, 0x70, // ## ### + 0x18, 0x30, // ## ## + 0x18, 0x30, // ## ## + 0x18, 0x70, // ## ### + 0x1F, 0xE0, // ######## + 0x1F, 0xC0, // ####### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x3F, 0x00, // ###### + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @1960 'Q' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x0F, 0xC0, // ###### + 0x1C, 0xE0, // ### ### + 0x38, 0x70, // ### ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x70, // ### ### + 0x1C, 0xE0, // ### ### + 0x0F, 0xC0, // ###### + 0x07, 0x80, // #### + 0x07, 0xB0, // #### ## + 0x0F, 0xF0, // ######## + 0x0C, 0xE0, // ## ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2000 'R' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xC0, // ######## + 0x3F, 0xE0, // ######### + 0x18, 0x70, // ## ### + 0x18, 0x30, // ## ## + 0x18, 0x70, // ## ### + 0x1F, 0xE0, // ######## + 0x1F, 0xC0, // ####### + 0x18, 0xE0, // ## ### + 0x18, 0x60, // ## ## + 0x18, 0x70, // ## ### + 0x3E, 0x38, // ##### ### + 0x3E, 0x18, // ##### ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2040 'S' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x0F, 0xB0, // ##### ## + 0x1F, 0xF0, // ######### + 0x38, 0x70, // ### ### + 0x30, 0x30, // ## ## + 0x38, 0x00, // ### + 0x1F, 0x80, // ###### + 0x07, 0xE0, // ###### + 0x00, 0x70, // ### + 0x30, 0x30, // ## ## + 0x38, 0x70, // ### ### + 0x3F, 0xE0, // ######### + 0x37, 0xC0, // ## ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2080 'T' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x0F, 0xC0, // ###### + 0x0F, 0xC0, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2120 'U' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x1C, 0xE0, // ### ### + 0x0F, 0xC0, // ###### + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2160 'V' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x30, 0x60, // ## ## + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2200 'W' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x7C, 0x7C, // ##### ##### + 0x7C, 0x7C, // ##### ##### + 0x30, 0x18, // ## ## + 0x33, 0x98, // ## ### ## + 0x33, 0x98, // ## ### ## + 0x33, 0x98, // ## ### ## + 0x36, 0xD8, // ## ## ## ## + 0x16, 0xD0, // # ## ## # + 0x1C, 0x70, // ### ### + 0x1C, 0x70, // ### ### + 0x1C, 0x70, // ### ### + 0x18, 0x30, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2240 'X' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x0D, 0x80, // ## ## + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x0D, 0x80, // ## ## + 0x18, 0xC0, // ## ## + 0x30, 0x60, // ## ## + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2280 'Y' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x18, 0x60, // ## ## + 0x0C, 0xC0, // ## ## + 0x07, 0x80, // #### + 0x07, 0x80, // #### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x0F, 0xC0, // ###### + 0x0F, 0xC0, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2320 'Z' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2360 '[' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0xC0, // #### + 0x03, 0xC0, // #### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0xC0, // #### + 0x03, 0xC0, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2400 '\' (14 pixels wide) + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x01, 0x80, // ## + 0x01, 0x80, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0x60, // ## + 0x00, 0x60, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2440 ']' (14 pixels wide) + 0x00, 0x00, // + 0x0F, 0x00, // #### + 0x0F, 0x00, // #### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x0F, 0x00, // #### + 0x0F, 0x00, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2480 '^' (14 pixels wide) + 0x00, 0x00, // + 0x02, 0x00, // # + 0x07, 0x00, // ### + 0x0D, 0x80, // ## ## + 0x18, 0xC0, // ## ## + 0x30, 0x60, // ## ## + 0x20, 0x20, // # # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2520 '_' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0xFF, 0xFC, // ############## + 0xFF, 0xFC, // ############## + + // @2560 '`' (14 pixels wide) + 0x00, 0x00, // + 0x04, 0x00, // # + 0x03, 0x00, // ## + 0x00, 0x80, // # + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2600 'a' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0F, 0xC0, // ###### + 0x1F, 0xE0, // ######## + 0x00, 0x60, // ## + 0x0F, 0xE0, // ####### + 0x1F, 0xE0, // ######## + 0x38, 0x60, // ### ## + 0x30, 0xE0, // ## ### + 0x3F, 0xF0, // ########## + 0x1F, 0x70, // ##### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2640 'b' (14 pixels wide) + 0x00, 0x00, // + 0x70, 0x00, // ### + 0x70, 0x00, // ### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x37, 0x80, // ## #### + 0x3F, 0xE0, // ######### + 0x38, 0x60, // ### ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x60, // ### ## + 0x7F, 0xE0, // ########## + 0x77, 0x80, // ### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2680 'c' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB0, // #### ## + 0x1F, 0xF0, // ######### + 0x18, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x38, 0x30, // ### ## + 0x1F, 0xF0, // ######### + 0x0F, 0xC0, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2720 'd' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x70, // ### + 0x00, 0x70, // ### + 0x00, 0x30, // ## + 0x00, 0x30, // ## + 0x07, 0xB0, // #### ## + 0x1F, 0xF0, // ######### + 0x18, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x70, // ### ### + 0x1F, 0xF8, // ########## + 0x07, 0xB8, // #### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2760 'e' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x3F, 0xF0, // ########## + 0x3F, 0xF0, // ########## + 0x30, 0x00, // ## + 0x18, 0x30, // ## ## + 0x1F, 0xF0, // ######### + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2800 'f' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0xF0, // ###### + 0x07, 0xF0, // ####### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2840 'g' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB8, // #### ### + 0x1F, 0xF8, // ########## + 0x18, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x18, 0x70, // ## ### + 0x1F, 0xF0, // ######### + 0x07, 0xB0, // #### ## + 0x00, 0x30, // ## + 0x00, 0x70, // ### + 0x0F, 0xE0, // ####### + 0x0F, 0xC0, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + + // @2880 'h' (14 pixels wide) + 0x00, 0x00, // + 0x38, 0x00, // ### + 0x38, 0x00, // ### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x1B, 0xC0, // ## #### + 0x1F, 0xE0, // ######## + 0x1C, 0x60, // ### ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2920 'i' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x1F, 0x00, // ##### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @2960 'j' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xC0, // ####### + 0x1F, 0xC0, // ####### + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x00, 0xC0, // ## + 0x01, 0xC0, // ### + 0x3F, 0x80, // ####### + 0x3F, 0x00, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + + // @3000 'k' (14 pixels wide) + 0x00, 0x00, // + 0x38, 0x00, // ### + 0x38, 0x00, // ### + 0x18, 0x00, // ## + 0x18, 0x00, // ## + 0x1B, 0xE0, // ## ##### + 0x1B, 0xE0, // ## ##### + 0x1B, 0x00, // ## ## + 0x1E, 0x00, // #### + 0x1E, 0x00, // #### + 0x1B, 0x00, // ## ## + 0x19, 0x80, // ## ## + 0x39, 0xF0, // ### ##### + 0x39, 0xF0, // ### ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3040 'l' (14 pixels wide) + 0x00, 0x00, // + 0x1F, 0x00, // ##### + 0x1F, 0x00, // ##### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3080 'm' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x7E, 0xE0, // ###### ### + 0x7F, 0xF0, // ########### + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x33, 0x30, // ## ## ## + 0x7B, 0xB8, // #### ### ### + 0x7B, 0xB8, // #### ### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3120 'n' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3B, 0xC0, // ### #### + 0x3F, 0xE0, // ######### + 0x1C, 0x60, // ### ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3160 'o' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0x80, // #### + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x18, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x07, 0x80, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3200 'p' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x77, 0x80, // ### #### + 0x7F, 0xE0, // ########## + 0x38, 0x60, // ### ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x38, 0x60, // ### ## + 0x3F, 0xE0, // ######### + 0x37, 0x80, // ## #### + 0x30, 0x00, // ## + 0x30, 0x00, // ## + 0x7C, 0x00, // ##### + 0x7C, 0x00, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @3240 'q' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xB8, // #### ### + 0x1F, 0xF8, // ########## + 0x18, 0x70, // ## ### + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x30, 0x30, // ## ## + 0x18, 0x70, // ## ### + 0x1F, 0xF0, // ######### + 0x07, 0xB0, // #### ## + 0x00, 0x30, // ## + 0x00, 0x30, // ## + 0x00, 0xF8, // ##### + 0x00, 0xF8, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + + // @3280 'r' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xE0, // #### ### + 0x3D, 0xF0, // #### ##### + 0x0F, 0x30, // #### ## + 0x0E, 0x00, // ### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0xC0, // ######## + 0x3F, 0xC0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3320 's' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x07, 0xE0, // ###### + 0x1F, 0xE0, // ######## + 0x18, 0x60, // ## ## + 0x1E, 0x00, // #### + 0x0F, 0xC0, // ###### + 0x01, 0xE0, // #### + 0x18, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0x80, // ###### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3360 't' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x3F, 0xE0, // ######### + 0x3F, 0xE0, // ######### + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x00, // ## + 0x0C, 0x30, // ## ## + 0x0F, 0xF0, // ######## + 0x07, 0xC0, // ##### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3400 'u' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x38, 0xE0, // ### ### + 0x38, 0xE0, // ### ### + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0x60, // ## ## + 0x18, 0xE0, // ## ### + 0x1F, 0xF0, // ######### + 0x0F, 0x70, // #### ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3440 'v' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x0D, 0x80, // ## ## + 0x0D, 0x80, // ## ## + 0x07, 0x00, // ### + 0x07, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3480 'w' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x32, 0x60, // ## # ## + 0x32, 0x60, // ## # ## + 0x37, 0xE0, // ## ###### + 0x1D, 0xC0, // ### ### + 0x1D, 0xC0, // ### ### + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3520 'x' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x0C, 0xC0, // ## ## + 0x07, 0x80, // #### + 0x03, 0x00, // ## + 0x07, 0x80, // #### + 0x0C, 0xC0, // ## ## + 0x3C, 0xF0, // #### #### + 0x3C, 0xF0, // #### #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3560 'y' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x78, 0xF0, // #### #### + 0x78, 0xF0, // #### #### + 0x30, 0x60, // ## ## + 0x18, 0xC0, // ## ## + 0x18, 0xC0, // ## ## + 0x0D, 0x80, // ## ## + 0x0F, 0x80, // ##### + 0x07, 0x00, // ### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x00, // ## + 0x7F, 0x00, // ####### + 0x7F, 0x00, // ####### + 0x00, 0x00, // + 0x00, 0x00, // + + // @3600 'z' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x18, 0xC0, // ## ## + 0x01, 0x80, // ## + 0x03, 0x00, // ## + 0x06, 0x00, // ## + 0x0C, 0x60, // ## ## + 0x1F, 0xE0, // ######## + 0x1F, 0xE0, // ######## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3640 '{' (14 pixels wide) + 0x00, 0x00, // + 0x01, 0xC0, // ### + 0x03, 0xC0, // #### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x07, 0x00, // ### + 0x0E, 0x00, // ### + 0x07, 0x00, // ### + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0xC0, // #### + 0x01, 0xC0, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3680 '|' (14 pixels wide) + 0x00, 0x00, // + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x03, 0x00, // ## + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3720 '}' (14 pixels wide) + 0x00, 0x00, // + 0x1C, 0x00, // ### + 0x1E, 0x00, // #### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x07, 0x00, // ### + 0x03, 0x80, // ### + 0x07, 0x00, // ### + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x06, 0x00, // ## + 0x1E, 0x00, // #### + 0x1C, 0x00, // ### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + + // @3760 '~' (14 pixels wide) + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x0E, 0x00, // ### + 0x3F, 0x30, // ###### ## + 0x33, 0xF0, // ## ###### + 0x01, 0xE0, // #### + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // + 0x00, 0x00, // +}; + + +sFONT Font20 = { + Font20_Table, + 14, /* Width */ + 20, /* Height */ +}; + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font8.c b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font8.c new file mode 100644 index 000000000..f1d5b4dfc --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/font8.c @@ -0,0 +1,1005 @@ +/** + ****************************************************************************** + * @file Font8.c + * @author MCD Application Team + * @version V1.0.0 + * @date 18-February-2014 + * @brief This file provides text Font8 for STM32xx-EVAL's LCD driver. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2014 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "fonts.h" +#include + +// +// Font data for Courier New 12pt +// + +const uint8_t Font8_Table[] PROGMEM = +{ + // @0 ' ' (5 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @8 '!' (5 pixels wide) + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + + // @16 '"' (5 pixels wide) + 0x50, // # # + 0x50, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @24 '#' (5 pixels wide) + 0x28, // # # + 0x50, // # # + 0xF8, // ##### + 0x50, // # # + 0xF8, // ##### + 0x50, // # # + 0xA0, // # # + 0x00, // + + // @32 '$' (5 pixels wide) + 0x20, // # + 0x30, // ## + 0x60, // ## + 0x30, // ## + 0x10, // # + 0x60, // ## + 0x20, // # + 0x00, // + + // @40 '%' (5 pixels wide) + 0x20, // # + 0x20, // # + 0x18, // ## + 0x60, // ## + 0x10, // # + 0x10, // # + 0x00, // + 0x00, // + + // @48 '&' (5 pixels wide) + 0x00, // + 0x38, // ### + 0x20, // # + 0x60, // ## + 0x50, // # # + 0x78, // #### + 0x00, // + 0x00, // + + // @56 ''' (5 pixels wide) + 0x20, // # + 0x20, // # + 0x20, // # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @64 '(' (5 pixels wide) + 0x10, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x10, // # + 0x00, // + + // @72 ')' (5 pixels wide) + 0x40, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x40, // # + 0x00, // + + // @80 '*' (5 pixels wide) + 0x20, // # + 0x70, // ### + 0x20, // # + 0x50, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @88 '+' (5 pixels wide) + 0x00, // + 0x20, // # + 0x20, // # + 0xF8, // ##### + 0x20, // # + 0x20, // # + 0x00, // + 0x00, // + + // @96 ',' (5 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x10, // # + 0x20, // # + 0x20, // # + 0x00, // + + // @104 '-' (5 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x70, // ### + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @112 '.' (5 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + + // @120 '/' (5 pixels wide) + 0x10, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x40, // # + 0x40, // # + 0x80, // # + 0x00, // + + // @128 '0' (5 pixels wide) + 0x20, // # + 0x50, // # # + 0x50, // # # + 0x50, // # # + 0x50, // # # + 0x20, // # + 0x00, // + 0x00, // + + // @136 '1' (5 pixels wide) + 0x60, // ## + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0xF8, // ##### + 0x00, // + 0x00, // + + // @144 '2' (5 pixels wide) + 0x20, // # + 0x50, // # # + 0x20, // # + 0x20, // # + 0x40, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @152 '3' (5 pixels wide) + 0x20, // # + 0x50, // # # + 0x10, // # + 0x20, // # + 0x10, // # + 0x60, // ## + 0x00, // + 0x00, // + + // @160 '4' (5 pixels wide) + 0x10, // # + 0x30, // ## + 0x50, // # # + 0x78, // #### + 0x10, // # + 0x38, // ### + 0x00, // + 0x00, // + + // @168 '5' (5 pixels wide) + 0x70, // ### + 0x40, // # + 0x60, // ## + 0x10, // # + 0x50, // # # + 0x20, // # + 0x00, // + 0x00, // + + // @176 '6' (5 pixels wide) + 0x30, // ## + 0x40, // # + 0x60, // ## + 0x50, // # # + 0x50, // # # + 0x60, // ## + 0x00, // + 0x00, // + + // @184 '7' (5 pixels wide) + 0x70, // ### + 0x50, // # # + 0x10, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x00, // + 0x00, // + + // @192 '8' (5 pixels wide) + 0x20, // # + 0x50, // # # + 0x20, // # + 0x50, // # # + 0x50, // # # + 0x20, // # + 0x00, // + 0x00, // + + // @200 '9' (5 pixels wide) + 0x30, // ## + 0x50, // # # + 0x50, // # # + 0x30, // ## + 0x10, // # + 0x60, // ## + 0x00, // + 0x00, // + + // @208 ':' (5 pixels wide) + 0x00, // + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + + // @216 ';' (5 pixels wide) + 0x00, // + 0x00, // + 0x10, // # + 0x00, // + 0x10, // # + 0x20, // # + 0x00, // + 0x00, // + + // @224 '<' (5 pixels wide) + 0x00, // + 0x10, // # + 0x20, // # + 0xC0, // ## + 0x20, // # + 0x10, // # + 0x00, // + 0x00, // + + // @232 '=' (5 pixels wide) + 0x00, // + 0x70, // ### + 0x00, // + 0x70, // ### + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @240 '>' (5 pixels wide) + 0x00, // + 0x40, // # + 0x20, // # + 0x18, // ## + 0x20, // # + 0x40, // # + 0x00, // + 0x00, // + + // @248 '?' (5 pixels wide) + 0x20, // # + 0x50, // # # + 0x10, // # + 0x20, // # + 0x00, // + 0x20, // # + 0x00, // + 0x00, // + + // @256 '@' (5 pixels wide) + 0x30, // ## + 0x48, // # # + 0x48, // # # + 0x58, // # ## + 0x48, // # # + 0x40, // # + 0x38, // ### + 0x00, // + + // @264 'A' (5 pixels wide) + 0x60, // ## + 0x20, // # + 0x50, // # # + 0x70, // ### + 0x88, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @272 'B' (5 pixels wide) + 0xF0, // #### + 0x48, // # # + 0x70, // ### + 0x48, // # # + 0x48, // # # + 0xF0, // #### + 0x00, // + 0x00, // + + // @280 'C' (5 pixels wide) + 0x70, // ### + 0x50, // # # + 0x40, // # + 0x40, // # + 0x40, // # + 0x30, // ## + 0x00, // + 0x00, // + + // @288 'D' (5 pixels wide) + 0xF0, // #### + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0xF0, // #### + 0x00, // + 0x00, // + + // @296 'E' (5 pixels wide) + 0xF8, // ##### + 0x48, // # # + 0x60, // ## + 0x40, // # + 0x48, // # # + 0xF8, // ##### + 0x00, // + 0x00, // + + // @304 'F' (5 pixels wide) + 0xF8, // ##### + 0x48, // # # + 0x60, // ## + 0x40, // # + 0x40, // # + 0xE0, // ### + 0x00, // + 0x00, // + + // @312 'G' (5 pixels wide) + 0x70, // ### + 0x40, // # + 0x40, // # + 0x58, // # ## + 0x50, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @320 'H' (5 pixels wide) + 0xE8, // ### # + 0x48, // # # + 0x78, // #### + 0x48, // # # + 0x48, // # # + 0xE8, // ### # + 0x00, // + 0x00, // + + // @328 'I' (5 pixels wide) + 0x70, // ### + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @336 'J' (5 pixels wide) + 0x38, // ### + 0x10, // # + 0x10, // # + 0x50, // # # + 0x50, // # # + 0x20, // # + 0x00, // + 0x00, // + + // @344 'K' (5 pixels wide) + 0xD8, // ## ## + 0x50, // # # + 0x60, // ## + 0x70, // ### + 0x50, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @352 'L' (5 pixels wide) + 0xE0, // ### + 0x40, // # + 0x40, // # + 0x40, // # + 0x48, // # # + 0xF8, // ##### + 0x00, // + 0x00, // + + // @360 'M' (5 pixels wide) + 0xD8, // ## ## + 0xD8, // ## ## + 0xD8, // ## ## + 0xA8, // # # # + 0x88, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @368 'N' (5 pixels wide) + 0xD8, // ## ## + 0x68, // ## # + 0x68, // ## # + 0x58, // # ## + 0x58, // # ## + 0xE8, // ### # + 0x00, // + 0x00, // + + // @376 'O' (5 pixels wide) + 0x30, // ## + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @384 'P' (5 pixels wide) + 0xF0, // #### + 0x48, // # # + 0x48, // # # + 0x70, // ### + 0x40, // # + 0xE0, // ### + 0x00, // + 0x00, // + + // @392 'Q' (5 pixels wide) + 0x30, // ## + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x30, // ## + 0x18, // ## + 0x00, // + + // @400 'R' (5 pixels wide) + 0xF0, // #### + 0x48, // # # + 0x48, // # # + 0x70, // ### + 0x48, // # # + 0xE8, // ### # + 0x00, // + 0x00, // + + // @408 'S' (5 pixels wide) + 0x70, // ### + 0x50, // # # + 0x20, // # + 0x10, // # + 0x50, // # # + 0x70, // ### + 0x00, // + 0x00, // + + // @416 'T' (5 pixels wide) + 0xF8, // ##### + 0xA8, // # # # + 0x20, // # + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @424 'U' (5 pixels wide) + 0xD8, // ## ## + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x48, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @432 'V' (5 pixels wide) + 0xD8, // ## ## + 0x88, // # # + 0x48, // # # + 0x50, // # # + 0x50, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @440 'W' (5 pixels wide) + 0xD8, // ## ## + 0x88, // # # + 0xA8, // # # # + 0xA8, // # # # + 0xA8, // # # # + 0x50, // # # + 0x00, // + 0x00, // + + // @448 'X' (5 pixels wide) + 0xD8, // ## ## + 0x50, // # # + 0x20, // # + 0x20, // # + 0x50, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @456 'Y' (5 pixels wide) + 0xD8, // ## ## + 0x88, // # # + 0x50, // # # + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @464 'Z' (5 pixels wide) + 0x78, // #### + 0x48, // # # + 0x10, // # + 0x20, // # + 0x48, // # # + 0x78, // #### + 0x00, // + 0x00, // + + // @472 '[' (5 pixels wide) + 0x30, // ## + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x30, // ## + 0x00, // + + // @480 '\' (5 pixels wide) + 0x80, // # + 0x40, // # + 0x40, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x10, // # + 0x00, // + + // @488 ']' (5 pixels wide) + 0x60, // ## + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x60, // ## + 0x00, // + + // @496 '^' (5 pixels wide) + 0x20, // # + 0x20, // # + 0x50, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @504 '_' (5 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0xF8, // ##### + + // @512 '`' (5 pixels wide) + 0x20, // # + 0x10, // # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @520 'a' (5 pixels wide) + 0x00, // + 0x00, // + 0x30, // ## + 0x10, // # + 0x70, // ### + 0x78, // #### + 0x00, // + 0x00, // + + // @528 'b' (5 pixels wide) + 0xC0, // ## + 0x40, // # + 0x70, // ### + 0x48, // # # + 0x48, // # # + 0xF0, // #### + 0x00, // + 0x00, // + + // @536 'c' (5 pixels wide) + 0x00, // + 0x00, // + 0x70, // ### + 0x40, // # + 0x40, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @544 'd' (5 pixels wide) + 0x18, // ## + 0x08, // # + 0x38, // ### + 0x48, // # # + 0x48, // # # + 0x38, // ### + 0x00, // + 0x00, // + + // @552 'e' (5 pixels wide) + 0x00, // + 0x00, // + 0x70, // ### + 0x70, // ### + 0x40, // # + 0x30, // ## + 0x00, // + 0x00, // + + // @560 'f' (5 pixels wide) + 0x10, // # + 0x20, // # + 0x70, // ### + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @568 'g' (5 pixels wide) + 0x00, // + 0x00, // + 0x38, // ### + 0x48, // # # + 0x48, // # # + 0x38, // ### + 0x08, // # + 0x30, // ## + + // @576 'h' (5 pixels wide) + 0xC0, // ## + 0x40, // # + 0x70, // ### + 0x48, // # # + 0x48, // # # + 0xE8, // ### # + 0x00, // + 0x00, // + + // @584 'i' (5 pixels wide) + 0x20, // # + 0x00, // + 0x60, // ## + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @592 'j' (5 pixels wide) + 0x20, // # + 0x00, // + 0x70, // ### + 0x10, // # + 0x10, // # + 0x10, // # + 0x10, // # + 0x70, // ### + + // @600 'k' (5 pixels wide) + 0xC0, // ## + 0x40, // # + 0x58, // # ## + 0x70, // ### + 0x50, // # # + 0xD8, // ## ## + 0x00, // + 0x00, // + + // @608 'l' (5 pixels wide) + 0x60, // ## + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @616 'm' (5 pixels wide) + 0x00, // + 0x00, // + 0xD0, // ## # + 0xA8, // # # # + 0xA8, // # # # + 0xA8, // # # # + 0x00, // + 0x00, // + + // @624 'n' (5 pixels wide) + 0x00, // + 0x00, // + 0xF0, // #### + 0x48, // # # + 0x48, // # # + 0xC8, // ## # + 0x00, // + 0x00, // + + // @632 'o' (5 pixels wide) + 0x00, // + 0x00, // + 0x30, // ## + 0x48, // # # + 0x48, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @640 'p' (5 pixels wide) + 0x00, // + 0x00, // + 0xF0, // #### + 0x48, // # # + 0x48, // # # + 0x70, // ### + 0x40, // # + 0xE0, // ### + + // @648 'q' (5 pixels wide) + 0x00, // + 0x00, // + 0x38, // ### + 0x48, // # # + 0x48, // # # + 0x38, // ### + 0x08, // # + 0x18, // ## + + // @656 'r' (5 pixels wide) + 0x00, // + 0x00, // + 0x78, // #### + 0x20, // # + 0x20, // # + 0x70, // ### + 0x00, // + 0x00, // + + // @664 's' (5 pixels wide) + 0x00, // + 0x00, // + 0x30, // ## + 0x20, // # + 0x10, // # + 0x60, // ## + 0x00, // + 0x00, // + + // @672 't' (5 pixels wide) + 0x00, // + 0x40, // # + 0xF0, // #### + 0x40, // # + 0x48, // # # + 0x30, // ## + 0x00, // + 0x00, // + + // @680 'u' (5 pixels wide) + 0x00, // + 0x00, // + 0xD8, // ## ## + 0x48, // # # + 0x48, // # # + 0x38, // ### + 0x00, // + 0x00, // + + // @688 'v' (5 pixels wide) + 0x00, // + 0x00, // + 0xC8, // ## # + 0x48, // # # + 0x30, // ## + 0x30, // ## + 0x00, // + 0x00, // + + // @696 'w' (5 pixels wide) + 0x00, // + 0x00, // + 0xD8, // ## ## + 0xA8, // # # # + 0xA8, // # # # + 0x50, // # # + 0x00, // + 0x00, // + + // @704 'x' (5 pixels wide) + 0x00, // + 0x00, // + 0x48, // # # + 0x30, // ## + 0x30, // ## + 0x48, // # # + 0x00, // + 0x00, // + + // @712 'y' (5 pixels wide) + 0x00, // + 0x00, // + 0xD8, // ## ## + 0x50, // # # + 0x50, // # # + 0x20, // # + 0x20, // # + 0x60, // ## + + // @720 'z' (5 pixels wide) + 0x00, // + 0x00, // + 0x78, // #### + 0x50, // # # + 0x28, // # # + 0x78, // #### + 0x00, // + 0x00, // + + // @728 '{' (5 pixels wide) + 0x10, // # + 0x20, // # + 0x20, // # + 0x60, // ## + 0x20, // # + 0x20, // # + 0x10, // # + 0x00, // + + // @736 '|' (5 pixels wide) + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x20, // # + 0x00, // + + // @744 '}' (5 pixels wide) + 0x40, // # + 0x20, // # + 0x20, // # + 0x30, // ## + 0x20, // # + 0x20, // # + 0x40, // # + 0x00, // + + // @752 '~' (5 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x28, // # # + 0x50, // # # + 0x00, // + 0x00, // + 0x00, // +}; + +sFONT Font8 = { + Font8_Table, + 5, /* Width */ + 8, /* Height */ +}; + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/imagedata.cpp b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/imagedata.cpp new file mode 100644 index 000000000..db8e7fa49 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/imagedata.cpp @@ -0,0 +1,327 @@ +/** + * @filename : imagedata.cpp + * @brief : data file for epd demo + * + * Copyright (C) Waveshare September 5 2017 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documnetation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "imagedata.h" +#include + +const unsigned char IMAGE_DATA[] PROGMEM = { +/* 0x00,0x01,0x80,0x00,0x28,0x01, */ +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x03,0xF0,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x03,0xF0,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x38,0x03,0xF0,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x01,0xF8,0x03,0xF0,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x0F,0xF8,0x03,0xF0,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x7F,0xF8,0x03,0xF0,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x1F,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0xF0,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0x80,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFC,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xF8,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x3F,0xFE,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x07,0xFF,0xC0,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x1F,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x1F,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x7F,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x1F,0xFF,0xE0,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFC,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xF0,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFC,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x1F,0xFF,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xE0,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x80,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x07,0xFF,0xC0,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x01,0xFF,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7C,0x00,0x7F,0xF0,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0x00,0x0F,0xF8,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xC0,0x07,0xFC,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xE0,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xF8,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x3F,0xFE,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x07,0xFF,0xC0,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x01,0xFF,0xF0,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0xFF,0x00,0x7F,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x81,0xFE,0x00,0x1F,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0x00,0x1F,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x7F,0xC0,0x7F,0xF8,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x3F,0xF9,0xFF,0xF0,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x1F,0xFF,0xFF,0x80,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x3F,0x0B,0xFF,0xFE,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x3F,0x00,0xFF,0xF8,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x3F,0x00,0x3F,0xE0,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x3F,0x00,0x0F,0x80,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x3F,0x00,0x02,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x18,0xFF,0xFF,0xFE,0x7F,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x01,0xF8,0xFF,0xFF,0xF8,0x1F,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x3F,0xF8,0xFF,0xFF,0xE0,0x0F,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xE0,0xFF,0xFF,0xE0,0x07,0x80,0x7F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFC,0x00,0xFF,0xFF,0xF0,0x03,0xC0,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x00,0xFF,0xFF,0xF8,0x00,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x3F,0xF0,0xC0,0x00,0x00,0x00,0x70,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x03,0xF8,0xC0,0x00,0x00,0x00,0x18,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x07,0xF8,0xC0,0x00,0x00,0x00,0x04,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0xE0,0xC0,0x00,0x00,0x00,0x06,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x00,0xC0,0x00,0x00,0x00,0x07,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFC,0x00,0xFF,0xFF,0xFF,0xFC,0x07,0xC3,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xE0,0xF8,0xFF,0xFF,0xFE,0x0F,0xE3,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1F,0xF8,0xF8,0x3F,0xFF,0x06,0x00,0x13,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x01,0xF8,0xE0,0x03,0xFF,0x06,0x00,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x18,0xE0,0x00,0x01,0x06,0x00,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xE0,0x00,0x01,0x06,0x00,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x70,0x00,0xF8,0x00,0x01,0x06,0x00,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xF9,0x80,0xFE,0x00,0x01,0x06,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xF9,0xC0,0xFF,0xC0,0x01,0x06,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xFF,0xFF,0xC1,0x06,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xFF,0xFF,0xC1,0x06,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xFF,0x8F,0xC1,0x06,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x80,0xFC,0x00,0x01,0x06,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x00,0xFE,0x00,0x01,0x06,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFE,0x00,0x01,0x06,0x00,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x40,0xFD,0x00,0x01,0x06,0x00,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x03,0xC0,0xF8,0x80,0x01,0x06,0x00,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1F,0xC0,0xE0,0x40,0xFF,0x02,0x00,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x80,0xC0,0x40,0xFF,0x00,0x00,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFC,0x00,0xC0,0x20,0x7E,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFC,0x00,0xE0,0x00,0x7E,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x80,0xF0,0x07,0xF0,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1F,0xC0,0xF8,0x03,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x03,0xC0,0xFC,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x40,0xFE,0x00,0x00,0x01,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1E,0x00,0xFF,0x00,0x00,0x7F,0x80,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xFF,0x00,0x00,0x7F,0x83,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xFC,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xED,0xC0,0xF8,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xF0,0x03,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xE0,0x07,0xE0,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCF,0xC0,0xE0,0x1F,0xFC,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCF,0x80,0xE0,0x3F,0xFF,0xE0,0x03,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x0E,0x00,0xF8,0x7F,0xFF,0xFF,0x83,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x83,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x43,0x00,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC7,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCF,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFC,0xC0,0xFF,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x78,0xC0,0xFF,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x30,0x40,0xFF,0xFF,0xFF,0xE0,0x00,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xF0,0x7F,0xFF,0xE0,0x00,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xFC,0xF0,0x7F,0x83,0xE0,0x00,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xFC,0xF0,0x60,0x83,0xFF,0xE0,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xFC,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x01,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x80,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x00,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x70,0x00,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xF9,0x80,0xF0,0x60,0x83,0xFF,0xE0,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xF9,0xC0,0xF0,0x60,0x83,0xFF,0xE0,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xF0,0x60,0x83,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xF0,0x60,0x83,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xF0,0x60,0x83,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x80,0xF0,0x60,0x83,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x00,0xF0,0x60,0x83,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xF0,0x60,0x83,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xF0,0x60,0x83,0xFF,0xE0,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x01,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0xC0,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xF0,0x60,0x83,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1E,0x00,0xC0,0x00,0x03,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xC0,0x00,0x03,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xC0,0x00,0x03,0x84,0x20,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xED,0xC0,0xC0,0x00,0x03,0xFF,0xE0,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xC0,0x00,0x03,0xE0,0x00,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xC0,0x00,0x03,0xE0,0x00,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCF,0xC0,0xFF,0xFF,0xFF,0xE0,0x00,0x83,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCF,0x80,0xFF,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x0E,0x00,0xFF,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC3,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC3,0x18,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC3,0x18,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC3,0x18,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0x18,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xFC,0xFF,0xFE,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xFC,0xFF,0xFE,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xFC,0xFF,0xFE,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFE,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFE,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1E,0x00,0xFF,0xFE,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xFF,0xFE,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xFF,0xFE,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xED,0xC0,0xFF,0xFE,0x07,0x03,0xC0,0x7F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xFC,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xF8,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCF,0xC0,0xF0,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCF,0x80,0xE0,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x0E,0x00,0xE0,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1E,0x00,0xE0,0x3E,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xE0,0x7E,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xE0,0x7E,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xE1,0xC0,0xE0,0x7E,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xE0,0x7E,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xE0,0x7E,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xE0,0x7E,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x40,0xC0,0xE0,0x7E,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xE0,0x7E,0x07,0x83,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0xC0,0xE0,0x7E,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0xF0,0xE0,0x7E,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xF0,0xE0,0x7E,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xF0,0xE0,0x3E,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xE0,0x02,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xE0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xE0,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xF0,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xF8,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xFE,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x01,0xC0,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1E,0x00,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x80,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xE1,0xC0,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xE1,0xC0,0xFF,0xFF,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0xC0,0xFF,0xFF,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xFF,0xFF,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1E,0x00,0xFF,0xFF,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xFC,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xE0,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xC0,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x01,0x80,0xC0,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0xC0,0xC0,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0xC0,0xC0,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xC0,0xC0,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x80,0xE0,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0x00,0xE0,0x7F,0xF8,0x1F,0xFC,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xE0,0x00,0x00,0x00,0x3C,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xE0,0x00,0x00,0x00,0x3C,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xD8,0xE0,0x00,0x00,0x00,0x1C,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xD8,0xF0,0x00,0x00,0x00,0x1C,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFF,0xD8,0xF0,0x00,0x00,0x00,0x0C,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xF8,0x00,0x00,0x00,0x04,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xF8,0x1C,0x04,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x1E,0x00,0xFF,0xFF,0xF8,0x1E,0x00,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xFF,0xFF,0xF8,0x1E,0x00,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x7F,0x80,0xFF,0xFF,0xF8,0x1F,0x00,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xE1,0xC0,0xFF,0xFF,0xF8,0x1F,0x00,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xFF,0xFF,0xF8,0x1F,0x80,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xFF,0xFF,0xF8,0x1F,0xC0,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xFF,0xFF,0xF8,0x1F,0xC0,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x40,0xC0,0xFF,0xFF,0xF8,0x1F,0xE0,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xF8,0x1F,0xF0,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x43,0x00,0xFF,0xFF,0xF8,0x1F,0xF8,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xC7,0x80,0xFF,0xFF,0xF8,0x1F,0xF8,0x07,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCF,0xC0,0xFF,0xFF,0xF8,0x1F,0xFC,0x0F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xCC,0xC0,0xFF,0xFF,0xF8,0x1F,0xFE,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0xFC,0xC0,0xFF,0xFF,0xF8,0x1F,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x78,0xC0,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x30,0x40,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +}; diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/imagedata.h b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/imagedata.h new file mode 100644 index 000000000..2234ead4e --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/components/epaper-29-ws/imagedata.h @@ -0,0 +1,30 @@ +/** + * @filename : imagedata.h + * @brief : head file for imagedata.cpp + * + * Copyright (C) Waveshare September 5 2017 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documnetation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +extern const unsigned char IMAGE_DATA[]; + +/* FILE END */ + + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/Doxyfile b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/Doxyfile new file mode 100644 index 000000000..590893a4e --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/Doxyfile @@ -0,0 +1,58 @@ +# This is Doxygen configuration file +# +# Doxygen provides over 260 configuration statements +# To make this file easier to follow, +# it contains only statements that are non-default +# +# NOTE: +# It is recommended not to change defaults unless specifically required +# Test any changes how they affect generated documentation +# Make sure that correct warnings are generated to flag issues with documented code +# +# For the complete list of configuration statements see: +# https://www.stack.nl/~dimitri/doxygen/manual/config.html + + +PROJECT_NAME = "esp-epaper-29-ws" + +## The 'INPUT' statement below is used as input by script 'gen-df-input.py' +## to automatically generate API reference list files heder_file.inc +## These files are placed in '_inc' directory +## and used to include in API reference documentation + +INPUT = \ + ../components/epaper-29-ws/epaper-29-ws.h + +## Get warnings for functions that have no documentation for their parameters or return value +## +WARN_NO_PARAMDOC = YES + +## Enable preprocessing and remove __attribute__(...) expressions from the INPUT files +## +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +PREDEFINED = __attribute__(x)= + +## Do not complain about not having dot +## +HAVE_DOT = NO + +## Generate XML that is required for Breathe +## +GENERATE_XML = YES +XML_OUTPUT = xml + +GENERATE_HTML = NO +HAVE_DOT = NO +GENERATE_LATEX = NO +GENERATE_MAN = YES +GENERATE_RTF = NO + +## Skip distracting progress messages +## +QUIET = YES +## Log warnings in a file for further review +## +WARN_LOGFILE = "doxygen-warning-log.txt" + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/Makefile b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/Makefile new file mode 100644 index 000000000..cc32abbd5 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/Makefile @@ -0,0 +1,201 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) -w sphinx-warning-log.txt . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/ReadtheDocsTemplate" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ReadtheDocsTemplate" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +gh-linkcheck: + @echo "Checking for hardcoded GitHub links" + @if (find ../ -name '*.rst' | xargs grep \ + 'https://github.com/espressif/esp-idf/tree\|https://github.com/espressif/esp-idf/blob\|https://github.com/espressif/esp-idf/raw'\ + ); \ + then \ + echo "WARNINIG: Some .rst files contain hardcoded Github links."; \ + echo "Please check above output and replace links with one of the following:"; \ + echo "- :idf:\`dir\` - points to directory inside ESP-IDF"; \ + echo "- :idf_file:\`file\` - points to file inside ESP-IDF"; \ + echo "- :idf_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ + echo "- :component:\`dir\` - points to directory inside ESP-IDF components dir"; \ + echo "- :component_file:\`file\` - points to file inside ESP-IDF components dir"; \ + echo "- :component_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ + echo " components dir"; \ + echo "- :example:\`dir\` - points to directory inside ESP-IDF examples dir"; \ + echo "- :example_file:\`file\` - points to file inside ESP-IDF examples dir"; \ + echo "- :example_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ + echo " examples dir"; \ + echo "These link types will point to the correct GitHub version automatically"; \ + exit 1; \ + fi + @echo "No hardcoded links found" + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/README.md b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/README.md new file mode 100644 index 000000000..b451469ce --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/README.md @@ -0,0 +1,8 @@ +# Documentation Source Folder + +This folder contains source files of [documentation](https://esp-epaper-29-ws.readthedocs.io/). + +The sources do not render well in GitHub and some information is not visible at all. + +Use actual the link above to access documentation generated instantly on each commit: + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/conf.py b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/conf.py new file mode 100644 index 000000000..9ad6d6924 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/conf.py @@ -0,0 +1,298 @@ +# -*- coding: utf-8 -*- +# +# Read the Docs Template documentation build configuration file, created by +# sphinx-quickstart on Tue Aug 26 14:19:49 2014. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os +import re +from subprocess import call, Popen, PIPE +import shlex + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('.')) + +from repo_util import run_cmd_get_output + +# Call Doxygen to get XML files from the header files +print "Calling Doxygen to generate latest XML files" +call('doxygen') +# Generate 'api_name.inc' files using the XML files by Doxygen +os.system("python gen-dxd.py") + +# http://stackoverflow.com/questions/12772927/specifying-an-online-image-in-sphinx-restructuredtext-format +# +suppress_warnings = ['image.nonlocal_uri'] + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['breathe', 'link-roles' ] + +# Breathe extension variables +breathe_projects = { "epaper-29-ws": "xml/" } +breathe_default_project = "epaper-29-ws" + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'epaper-29-ws' +copyright = u'2016 - 2017, Espressif' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# + +# Readthedocs largely ignores 'version' and 'release', and displays one of +# 'latest', tag name, or branch name, depending on the build type. +# Still, this is useful for non-RTD builds. +# This is supposed to be "the short X.Y version", but it's the only version +# visible when you open index.html. +# Display full version to make things less confusing. +version = run_cmd_get_output('git describe') +# The full version, including alpha/beta/rc tags. +# If needed, nearest tag is returned by 'git describe --abbrev=0'. +release = version +print 'Version: {0} Release: {1}'.format(version, release) + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = [] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'ReadtheDocsTemplatedoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'ReadtheDocsTemplate.tex', u'Read the Docs Template Documentation', + u'Read the Docs', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'readthedocstemplate', u'Read the Docs Template Documentation', + [u'Read the Docs'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'ReadtheDocsTemplate', u'Read the Docs Template Documentation', + u'Read the Docs', 'ReadtheDocsTemplate', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + +# -- Use sphinx_rtd_theme for local builds -------------------------------- +# ref. https://github.com/snide/sphinx_rtd_theme#using-this-theme-locally-then-building-on-read-the-docs +# +# on_rtd is whether we are on readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +# otherwise, readthedocs.org uses their theme by default, so no need to specify it + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/gen-dxd.py b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/gen-dxd.py new file mode 100644 index 000000000..4be75915b --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/gen-dxd.py @@ -0,0 +1,301 @@ +# gen-dxd.py - Generate Doxygen Directives +# +# This code is in the Public Domain (or CC0 licensed, at your option.) +# Unless required by applicable law or agreed to in writing, this +# software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. +# + +import sys +import os +import re + +# Script configuration +header_file_path_prefix = "../components/" +"""string: path prefix for header files. +""" +doxyfile_path = "Doxyfile" +"""string: path to a file containing header files to processs. +""" +xml_directory_path = "xml" +"""string: path to directory with XML files by Doxygen. +""" +inc_directory_path = "_build/inc" +"""string: path prefix for header files. +""" +all_kinds = [ + ("function", "Functions"), + ("union", "Unions"), + ("struct", "Structures"), + ("define", "Macros"), + ("typedef", "Type Definitions"), + ("enum", "Enumerations") + ] +"""list of items that will be generated for a single API file +""" + + +def get_doxyfile_input(): + """Get contents of Doxyfile's INPUT statement. + + Returns: + Contents of Doxyfile's INPUT. + + """ + if not os.path.isfile(doxyfile_path): + print "Doxyfile '%s' does not exist!" % doxyfile_path + sys.exit() + + print "Getting Doxyfile's INPUT" + + input_file = open(doxyfile_path, "r") + + line = input_file.readline() + # read contents of Doxyfile until 'INPUT' statement + while line: + if line.find("INPUT") == 0: + break + line = input_file.readline() + + doxyfile_INPUT = "" + line = input_file.readline() + # skip input_file contents until end of 'INPUT' statement + while line: + if line.isspace(): + # we have reached the end of 'INPUT' statement + break + # process only lines that are not comments + if line.find("#") == -1: + # extract header file path inside components folder + m = re.search(header_file_path_prefix + "(.*\.h)", line) + header_file_path = m.group(1) + doxyfile_INPUT += header_file_path + "\n" + # proceed reading next line + line = input_file.readline() + + input_file.close() + return doxyfile_INPUT + + +def get_api_name(header_file_path): + """Get name of API from header file path. + + Args: + header_file_path: path to the header file. + + Returns: + The name of API. + + """ + api_name = "" + regex = r".*/(.*)\.h" + m = re.search(regex, header_file_path) + if m: + api_name = m.group(1) + + return api_name + + +def get_rst_header(header_name): + """Get rst formatted code with a header. + + Args: + header_name: name of header. + + Returns: + Formatted rst code with the header. + + """ + + rst_output = "" + rst_output += header_name + "\n" + rst_output += "^" * len(header_name) + "\n" + rst_output += "\n" + + return rst_output + + +def select_unions(innerclass_list): + """Select unions from innerclass list. + + Args: + innerclass_list: raw list with unions and structures + extracted from Dogygen's xml file. + + Returns: + Doxygen directives with unions selected from the list. + + """ + + rst_output = "" + for line in innerclass_list.splitlines(): + # union is denoted by "union" at the beginning of line + if line.find("union") == 0: + union_id, union_name = re.split(r"\t+", line) + rst_output += ".. doxygenunion:: " + rst_output += union_name + rst_output += "\n" + + return rst_output + + +def select_structs(innerclass_list): + """Select structures from innerclass list. + + Args: + innerclass_list: raw list with unions and structures + extracted from Dogygen's xml file. + + Returns: + Doxygen directives with structures selected from the list. + Note: some structures are excluded as described on code below. + + """ + + rst_output = "" + for line in innerclass_list.splitlines(): + # structure is denoted by "struct" at the beginning of line + if line.find("struct") == 0: + # skip structures that are part of union + # they are documented by 'doxygenunion' directive + if line.find("::") > 0: + continue + struct_id, struct_name = re.split(r"\t+", line) + rst_output += ".. doxygenstruct:: " + rst_output += struct_name + rst_output += "\n" + rst_output += " :members:\n" + rst_output += "\n" + + return rst_output + + +def get_directives(tree, kind): + """Get directives for specific 'kind'. + + Args: + tree: the ElementTree 'tree' of XML by Doxygen + kind: name of API "kind" to be generated + + Returns: + Doxygen directives for selected 'kind'. + Note: the header with "kind" name is included. + + """ + + rst_output = "" + if kind in ["union", "struct"]: + innerclass_list = "" + for elem in tree.iterfind('compounddef/innerclass'): + innerclass_list += elem.attrib["refid"] + "\t" + elem.text + "\n" + if kind == "union": + rst_output += select_unions(innerclass_list) + else: + rst_output += select_structs(innerclass_list) + else: + for elem in tree.iterfind( + 'compounddef/sectiondef/memberdef[@kind="%s"]' % kind): + name = elem.find('name') + rst_output += ".. doxygen%s:: " % kind + rst_output += name.text + "\n" + if rst_output: + all_kinds_dict = dict(all_kinds) + rst_output = get_rst_header(all_kinds_dict[kind]) + rst_output + "\n" + + return rst_output + + +def generate_directives(header_file_path): + """Generate API reference with Doxygen directives for a header file. + + Args: + header_file_path: a path to the header file with API. + + Returns: + Doxygen directives for the header file. + + """ + + api_name = get_api_name(header_file_path) + + # in XLT file name each "_" in the api name is expanded by Doxygen to "__" + xlt_api_name = api_name.replace("_", "__") + xml_file_path = "%s/%s_8h.xml" % (xml_directory_path, xlt_api_name) + + rst_output = "" + rst_output = ".. File automatically generated by 'gen-dxd.py'\n" + rst_output += "\n" + rst_output += get_rst_header("Header File") + rst_output += "* :component_file:`" + header_file_path + "`\n" + rst_output += "\n" + + try: + import xml.etree.cElementTree as ET + except ImportError: + import xml.etree.ElementTree as ET + + tree = ET.ElementTree(file=xml_file_path) + for i in range(len(all_kinds)): + kind = all_kinds[i][0] + rst_output += get_directives(tree, kind) + + return rst_output + + +def generate_api_inc_files(): + """Generate header_file.inc files + with API reference made of doxygen directives + for each header file + specified in the 'INPUT' statement of Doxyfile. + + """ + + if not os.path.isdir(xml_directory_path): + print "Directory %s does not exist!" % xml_directory_path + sys.exit() + + if not os.path.exists(inc_directory_path): + os.makedirs(inc_directory_path) + + list_to_generate = get_doxyfile_input() + print "Generating 'api_name.inc' files with Doxygen directives" + for header_file_path in list_to_generate.splitlines(): + api_name = get_api_name(header_file_path) + inc_file_path = inc_directory_path + "/" + api_name + ".inc" + rst_output = generate_directives(header_file_path) + inc_file = open(inc_file_path, "w") + inc_file.write(rst_output) + inc_file.close() + + +if __name__ == "__main__": + """The main script that generates + Doxygen directives. + + """ + + # Process command line arguments, if any + if len(sys.argv) > 1: + if not os.path.isdir(xml_directory_path): + print "Directory %s does not exist!" % xml_directory_path + sys.exit() + header_file_path = sys.argv[1] + api_name = get_api_name(header_file_path) + if api_name: + rst_output = generate_directives(header_file_path) + print "Doxygen directives for '%s'" % header_file_path + print + print rst_output + else: + print "Options to execute 'gen-dxd.py' application:" + print "1: $ python gen-dxd.py" + print " Generate API 'header_file.inc' files for headers defined in '%s'" % doxyfile_path + print "2: $ python gen-dxd.py header_file_path" + print " Print out Doxygen directives for a single header file" + print " example: $ python gen-dxd.py mdns/include/mdns.h" + print " NOTE: Run Doxygen first to get XML files for the header file" + + sys.exit() + + # No command line arguments given + generate_api_inc_files() diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/index.rst b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/index.rst new file mode 100644 index 000000000..f2c6c58f8 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/index.rst @@ -0,0 +1,9 @@ +ESP-IDF Component Documentation +=============================== + +Component: epaper-29-ws +----------------------- + +This component and documentation is based almost entirely on `epaper `_ component for another type of display developed by `esp-iot-solution `_ team. + +.. include:: _build/inc/epaper-29-ws.inc diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/link-roles.py b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/link-roles.py new file mode 100644 index 000000000..4ba8ff896 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/link-roles.py @@ -0,0 +1,34 @@ +# based on http://protips.readthedocs.io/link-roles.html + +from docutils import nodes +from repo_util import run_cmd_get_output + +def get_github_rev(): + path = run_cmd_get_output('git rev-parse --short HEAD') + tag = run_cmd_get_output('git describe --exact-match') + print 'Git commit ID: ', path + if len(tag): + print 'Git tag: ', tag + path = tag + return path + + +def setup(app): + baseurl = 'https://github.com/krzychb/esp-epaper-29-ws' + rev = get_github_rev() + app.add_role('idf', autolink('{}/tree/{}/%s'.format(baseurl, rev))) + app.add_role('idf_file', autolink('{}/blob/{}/%s'.format(baseurl, rev))) + app.add_role('idf_raw', autolink('{}/raw/{}/%s'.format(baseurl, rev))) + app.add_role('component', autolink('{}/tree/{}/components/%s'.format(baseurl, rev))) + app.add_role('component_file', autolink('{}/blob/{}/components/%s'.format(baseurl, rev))) + app.add_role('component_raw', autolink('{}/raw/{}/components/%s'.format(baseurl, rev))) + app.add_role('example', autolink('{}/tree/{}/examples/%s'.format(baseurl, rev))) + app.add_role('example_file', autolink('{}/blob/{}/examples/%s'.format(baseurl, rev))) + app.add_role('example_raw', autolink('{}/raw/{}/examples/%s'.format(baseurl, rev))) + +def autolink(pattern): + def role(name, rawtext, text, lineno, inliner, options={}, content=[]): + url = pattern % (text,) + node = nodes.reference(rawtext, text, refuri=url, **options) + return [node], [] + return role diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/repo_util.py b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/repo_util.py new file mode 100644 index 000000000..6249c11df --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/repo_util.py @@ -0,0 +1,5 @@ +import re +import os + +def run_cmd_get_output(cmd): + return os.popen(cmd).read().strip() diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/requirements.txt b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/requirements.txt new file mode 100644 index 000000000..642f0147f --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/docs/requirements.txt @@ -0,0 +1,6 @@ +# This is a list of python packages used to generate documentation. This file is used with pip: +# pip install -r requirements.txt +# +sphinx==1.6.5 +sphinx-rtd-theme +breathe==4.7.3 diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties b/lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties new file mode 100644 index 000000000..07a9e0a07 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties @@ -0,0 +1,9 @@ +name=Waveshare esp 2.9 inch e-paper display driver +version=1.0 +author=Gerhard Muntz +maintainer=Gerhard Muntz +sentence=ESP8266 library for Waveshare e-paper display. +paragraph= +category=Display +url=https://github.com/gemu2015/Sonoff-Tasmota/tree/displays/lib/esp-epaper-29-ws-20171230-gemu-1.0# +architectures=esp8266 diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/README.md b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/README.md new file mode 100644 index 000000000..599bb4009 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/README.md @@ -0,0 +1,55 @@ +# Example: e-paper dispalys + +### This test code shows how to use ESP32 driver e-Paper displays +* Support for **Waveshare 2.7inch e-Paper HAT** based ePaper modules in 4-wire SPI mode + +#### e-paper functions: + + * **Graphics drawing functions**: + * **Paint_Clear** Clear all screen memery + * **Paint_DrawAbsolutePixel** This draws a pixel by absolute coordinates + * **Paint_GetImage** Getters and Setters + * **Paint_SetRotate** Setup displays rotate + * **Paint_DrawPixel** Draws a pixel by the coordinates + * **Paint_DrawCharAt** Draw a charactor on the frame buffer but not refresh + * **Paint_DrawStringAt** Displays a string on the frame buffer but not refresh + * **Paint_DrawLine** Draws a line on the frame buffer + * **Paint_DrawHorizontalLine** Draw a horizontal line on the frame buffer + * **Paint_DrawVerticalLine** Draw a vertical line on the frame buffer + * **Paint_DrawRectangle** Draws a rectangle + * **Paint_DrawFilledRectangle** Draws a filled rectangle + * **Paint_DrawCircle** Draws a circle + * **Paint_DrawFilledCircle** Draws a filled circle + +* **Fonts**: + * Support for **font8**,**font12**,**font16**,**font20**,**font24**, fonts embeded + +* **String write function**: + * **EPD_print** Write text to display. +* **Images**: + * Can display the image form C array + +#### Connecting the display + * mosi: 23 (display DIN) + * sck: 18 + * CS: 5 (display CS) + * DC: 26 (display DC) + * RST: 27 (display RESET) + * BUSY: 32 (display BUSY output) + +#### How to build + + `make menuconfig` + + Make and flash the example. + + `make all && make flash` + +#### Test: + * Dispaly espressif logo for 2s + * display the random value on e-paper, refresh 5s + + + + + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/component.mk b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/esp-epaper-29-ws.c b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/esp-epaper-29-ws.c new file mode 100644 index 000000000..196ca2423 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/esp-epaper-29-ws.c @@ -0,0 +1,105 @@ +/* 2.9" Waveshare ePaper Driver Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include +#include "esp_log.h" + +#include "imagedata.h" +#include "epaper-29-ws.h" +#include "epaper_fonts.h" + +static const char *TAG = "ePaper Example"; + +// Pin definition of the ePaper module +#define MOSI_PIN 5 +#define MISO_PIN -1 +#define SCK_PIN 18 +#define BUSY_PIN 22 +#define DC_PIN 21 +#define RST_PIN 23 +#define CS_PIN 19 + +// Color inverse. 1 or 0 = set or reset a bit if set a colored pixel +#define IF_INVERT_COLOR 1 + +void e_paper_task(void *pvParameter) +{ + epaper_handle_t device = NULL; + + epaper_conf_t epaper_conf = { + .busy_pin = BUSY_PIN, + .cs_pin = CS_PIN, + .dc_pin = DC_PIN, + .miso_pin = MISO_PIN, + .mosi_pin = MOSI_PIN, + .reset_pin = RST_PIN, + .sck_pin = SCK_PIN, + + .rst_active_level = 0, + .busy_active_level = 1, + + .dc_lev_data = 1, + .dc_lev_cmd = 0, + + .clk_freq_hz = 20 * 1000 * 1000, + .spi_host = HSPI_HOST, + + .width = EPD_WIDTH, + .height = EPD_HEIGHT, + .color_inv = 1, + }; + + uint32_t cnt = 0; + char hum_str[7]; + char tsens_str[7]; + + while(1){ + ESP_LOGI(TAG, "Before ePaper driver init, heap: %d", esp_get_free_heap_size()); + device = iot_epaper_create(NULL, &epaper_conf); + iot_epaper_set_rotate(device, E_PAPER_ROTATE_270); + ESP_LOGI(TAG, "e-Paper Display Espressif logo"); + iot_epaper_display_frame(device, IMAGE_DATA); // display IMAGE_DATA + vTaskDelay(5000 / portTICK_PERIOD_MS); + + ESP_LOGI(TAG, "e-Paper Display sample graphics"); + iot_epaper_clean_paint(device, UNCOLORED); + iot_epaper_draw_string(device, 200, 0, "@espressif", &epaper_font_12, COLORED); + iot_epaper_draw_string(device, 10, 10, "e-Paper Demo ", &epaper_font_16, COLORED); + + iot_epaper_draw_string(device, 15, 50, "Humidity", &epaper_font_16, COLORED); + iot_epaper_draw_string(device, 15, 80, "Temperature", &epaper_font_16, COLORED); + memset(hum_str, 0x00, sizeof(hum_str)); + memset(tsens_str, 0x00, sizeof(tsens_str)); + sprintf(hum_str, "%4d %%", (uint8_t) (esp_random() * 100.0 / UINT32_MAX)); + sprintf(tsens_str, "%4d C", (int8_t) (esp_random() * 100.0 / UINT32_MAX - 50)); + iot_epaper_draw_string(device, 170, 50, hum_str, &epaper_font_16, COLORED); + iot_epaper_draw_string(device, 170, 80, tsens_str, &epaper_font_16, COLORED); + + iot_epaper_draw_horizontal_line(device, 10, 27, 140, COLORED); + iot_epaper_draw_horizontal_line(device, 10, 73, 240, COLORED); + iot_epaper_draw_vertical_line(device, 150, 43, 60, COLORED); + iot_epaper_draw_rectangle(device, 10, 43, 250, 103, COLORED); + iot_epaper_display_frame(device, NULL); // display internal frame buffer + iot_epaper_delete(device, true); + + ESP_LOGI(TAG, "EPD Display update count: %d", cnt++); + ESP_LOGI(TAG, "After ePaper driver delete, heap: %d", esp_get_free_heap_size()); + + vTaskDelay(5000 / portTICK_PERIOD_MS); + } +} + + +void app_main() +{ + ESP_LOGI(TAG, "Starting example"); + xTaskCreate(&e_paper_task, "epaper_task", 4 * 1024, NULL, 5, NULL); +} diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/imagedata.c b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/imagedata.c new file mode 100644 index 000000000..bcd4c064a --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/imagedata.c @@ -0,0 +1,315 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "imagedata.h" + + +const unsigned char IMAGE_DATA[4736] = { /* 0X01,0X01,0X28,0X01,0X7F,0X00, */ + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF9,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XC7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE1,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X8F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFB,0XFE,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XFC,0X70,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF3,0XFC,0X78,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF8,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF8,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF8,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF1,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF1,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XE3,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE1,0XE3,0XF8,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,0XC3,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X07,0XF0,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFC,0X0F,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X3F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XFC,0X20,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF3,0XFC,0X78,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF8,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF8,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF8,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF1,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF1,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF1,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XE3,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XC3,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,0X07,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X07,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X1F,0XFB,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFD,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF3,0XF9,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XF8,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XF9,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X79,0XE1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFC,0X10,0X83,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X7F,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X0F,0X80,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,0X06,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE1,0XC0,0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XE0,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF0,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF0,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X0F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0XC3,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XE3,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE0,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XFC,0X20,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XFC,0X78,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF8,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF8,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF8,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF1,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF1,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF1,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XE3,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XE3,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,0X07,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X07,0XF1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X1F,0XFB,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFD,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF3,0XF9,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XF9,0XFE,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XFC,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE3,0XF9,0XF8,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF1,0XF9,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X79,0XE1,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFC,0X10,0X83,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF9,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X3E,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X0F,0XFF,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X7F,0XFF,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X03,0XFF,0XFC,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X07,0XFF,0XE0,0X01,0XF8,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X1F,0XFF,0X80,0X1F,0XFC,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X7F,0XFE,0X00,0XFF,0XFF,0X03,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0XFF,0XF8,0X03,0XFF,0XFF,0X87,0X80,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X01,0XFF,0XF0,0X1F,0XFF,0XFF,0X83,0XC0,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X03,0XFF,0XE0,0X3F,0XFF,0XFF,0XC3,0XE0,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X07,0XFF,0X80,0XFF,0XFF,0XFF,0XC1,0XE0,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X0F,0XFF,0X03,0XFF,0XFF,0XFF,0XC0,0XF0,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X1F,0XFE,0X07,0XFF,0XFF,0XFF,0XC0,0X78,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X1F,0XFC,0X1F,0XFF,0XFF,0XFF,0X80,0X38,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3F,0XF8,0X3F,0XFF,0XFF,0XE0,0X00,0X3C,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3F,0XF0,0X7F,0XFF,0XFC,0X00,0X00,0X1C,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X7F,0XE0,0XFF,0XFF,0XE0,0X00,0X00,0X0E,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0XFF,0XC1,0XFF,0XFF,0X80,0X00,0X00,0X0E,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0XFF,0X83,0XFF,0XFE,0X00,0X7F,0XFF,0X8F,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0XFF,0X07,0XFF,0XF8,0X07,0XFF,0XFF,0XC7,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X01,0XFE,0X0F,0XFF,0XE0,0X1F,0XFF,0XFF,0XC7,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X01,0XFC,0X1F,0XFF,0XC0,0X7F,0XFF,0XFF,0XE3,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X03,0XF8,0X3F,0XFF,0X01,0XFF,0XFF,0XFF,0XE3,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X03,0XF8,0X3F,0XFE,0X07,0XFF,0XFF,0XFF,0XE3,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X03,0XF0,0X7F,0XFC,0X0F,0XFF,0XFF,0XFF,0XF3,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X03,0XF0,0XFF,0XF8,0X1F,0XFF,0XFF,0XFF,0XE3,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X07,0XE1,0XFF,0XF0,0X3F,0XFF,0XFF,0XFF,0XE1,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X07,0XE1,0XFF,0XF0,0X7F,0XFF,0XFF,0XFF,0XE1,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X07,0XC3,0XFF,0XE0,0XFF,0XFF,0XF0,0X07,0XC1,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X07,0XC3,0XFF,0XC1,0XFF,0XFF,0X80,0X00,0X01,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X07,0X87,0XFF,0X83,0XFF,0XFC,0X00,0X00,0X01,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X07,0X87,0XFF,0X87,0XFF,0XF0,0X00,0X00,0X01,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X07,0X0F,0XFF,0X0F,0XFF,0XC0,0X1F,0XFE,0X01,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X07,0X0F,0XFE,0X1F,0XFF,0X80,0XFF,0XFF,0XC1,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X07,0X1F,0XFE,0X1F,0XFF,0X03,0XFF,0XFF,0XF1,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X1F,0XFC,0X3F,0XFE,0X0F,0XFF,0XFF,0XF1,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X1F,0XFC,0X3F,0XFC,0X1F,0XFF,0XFF,0XF1,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3F,0XF8,0X7F,0XFC,0X3F,0XFF,0XFF,0XF1,0XC1,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3F,0XF8,0X7F,0XF8,0X7F,0XFF,0XFF,0XF1,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3F,0XF8,0X7F,0XF0,0X7F,0XFF,0XFF,0XF3,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3F,0XF0,0XFF,0XF0,0XFF,0XFF,0XFF,0XE3,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X7F,0XF0,0XFF,0XE1,0XFF,0XFF,0XFF,0XE3,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X7F,0XF0,0XFF,0XC1,0XFF,0XFC,0X0F,0XC3,0X81,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X7F,0XF1,0XFF,0XC3,0XFF,0XF0,0X03,0X87,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X7F,0XE1,0XFF,0X83,0XFF,0XC0,0X00,0X07,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X7F,0XE1,0XFF,0X87,0XFF,0X80,0X00,0X07,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X7F,0XE1,0XFF,0X87,0XFF,0X00,0X00,0X0E,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X7F,0XE3,0XFF,0X87,0XFE,0X01,0XE0,0X0E,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X7F,0XE3,0XFF,0X07,0XFE,0X07,0XF0,0X1C,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3F,0XE3,0XFF,0X0F,0XFE,0X0F,0XF8,0X1C,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3F,0XE3,0XFF,0X0F,0XFC,0X0F,0XFC,0X38,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X1F,0XC3,0XFF,0X0F,0XFC,0X0F,0XFC,0X78,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X0F,0XC3,0XFF,0X0F,0XFC,0X1F,0XFC,0X70,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X04,0X03,0XFF,0X9F,0XFC,0X0F,0XFC,0XF0,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X03,0XFF,0XFF,0XFC,0X0F,0XFD,0XE0,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X01,0XFF,0XFF,0XF8,0X0F,0XFF,0XC0,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X01,0XFF,0XFF,0XF8,0X07,0XFF,0X80,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X18,0X01,0XFF,0XFF,0XF8,0X03,0XFF,0X80,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3C,0X00,0XFF,0XFF,0XF0,0X00,0X1E,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X3E,0X00,0X7F,0XFF,0XE0,0X00,0X3C,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X0F,0X00,0X7F,0XFF,0XE0,0X00,0X78,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X07,0XC0,0X1F,0XFF,0X80,0X01,0XF0,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X03,0XF0,0X0F,0XFF,0X00,0X07,0XE0,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0XFC,0X01,0XFC,0X00,0X1F,0X80,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X7F,0X00,0X00,0X00,0X7F,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X1F,0XE0,0X00,0X03,0XFC,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X07,0XFE,0X00,0X7F,0XF0,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XC0,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X7F,0XFF,0XFF,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X07,0XFF,0XF0,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE, + }; diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/imagedata.h b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/imagedata.h new file mode 100644 index 000000000..f7d0b2f72 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/main/imagedata.h @@ -0,0 +1,18 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +extern const unsigned char IMAGE_DATA[]; + +/* FILE END */ + diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/2.9inch_e-Paper_Datasheet.pdf b/lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/2.9inch_e-Paper_Datasheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fd88de07b0037048a9b92b8a305334bc117c6a13 GIT binary patch literal 1125667 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

jqSq=5mWZhaR#{JlsM^hPS$UZwDxo5qlNwfh&8% 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

!V21li(#8ZARz5~ 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

gT6k19IKJr#7av!6?Xhrh0q)5qkZ2hHzL0 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∈ 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

8JZezqqEE1xZ{Z*ZE+Rr=VM~$aa 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%0Ag|LNX(2Tx-r!h!W?`s z-!fBnC zUm$kxf3ZM!tdtISioRqU28tUoCl{8S?b5V}60CwFcOxMi263$tXz)~!u&0R*`BhYC z4WJ)e$~rLRPLSkte|FicP&G0M4p7E2CF4riSJA?ku^T{~kabX%qX)oO8^hz^jZymS)HQ4uY$Pp;V>Ofe zExkluj}&}~wt^?8$>-!M!z25u`y**@%s4a2EL+poj%r+k{1iv+rbT=Da2SIcc1>X6 z)FGp>zG1R{BaX@;T~XK7u|h4Q;h3X}&p1Wykw@$beOx)|$BlcVoV>Cs{cQ`uE3&vJ zxsOvSMY`%F6=OQb{NXfv8t3rI@SRKS>3ZE|-DrA}6>K~Gv<>qpwrPSIwQh#_LOHkU zZ#V96c(#Wq0wBu9(6I6_= zmd75>+CG(wvdZG)5*ooo3mdd1<|894MaNfiIA7nP++BjA*iPePFFb;F_uLdn#;FQH zBO+;=PPDy-vkWWGa}FjPql0dIgi6^$QzBTefR2en9UATW+Al$Qzx)SB4B|}#)tbrr zx@1OUa{m#|ZV=`3*S<%@F$t*=T`DTOzw zMV~W!%;7FO;C33c?Dg2LI?Q$&kc0mCKrWrb40^wlIf z(H^VL@23r<9x=i`d+5LPgn*ZJoh0*u$P+|6O8<;1BWsi9T=AsDRdkACdn0km0JWqzO&8;wx&Fi;Pi>7hqZEXr9(2BN3 zC>4luKRYD)X(yDD(JXx_1#hPM5w2@`UktUA3n6pk!WRPO+N2?W5YP(BU>jLOAmm|T zbDcva0S}zf@9GtgghIyS#^qavL6fl{l?sp`QZx)JY?cria|;Y3-@k;4`tS{vGD%xJ zQ?8m(oU+=8Fp*P+E>9O?jHlF!|0_ZLM?((V4^A7>KX71DJeh~fB^quT z)JOQ)hcxn7E43jKtVYVfa2lL(RIy`U={V^QNR%3tIwTmvJ(@_@z9}B!TRFPupVJ`0 z)luQy?fV=jA%26_CTNaO69=GD+?EeM>SqUFkJL*j*rtl>vG3euhzBv%?jB)(TzK@p zrV_mfGU3shaa)t>IrRs=?@cVa+T|^9-Fd<{KgwFOya^@Pia0x0*R}(-AI@GIjaa67 z*H+HY*I%zUFV8l&^?cr*E<=h21@$^JWlutsO?VA+{k0N8K+)nGRkJ*ip1LpJoO~j3 z<8zPEQ_wYvF7hvUf+&KLsPPkOmCTm0|Kb$y3T=ksxJLH+^$!F|2 z&o#)Wq!ALeBvD_R9X{1dUxOWkxP$D$Q$3GB&{piR$bo~BHRX1aLdrZaH_PG6AB)Bdp@aq+66|Zu*U1vYdqtn-iKPwv| z8!XEvbX{O+d>xS1(R?^#)lyew$?xgli{^`@Q}G@K5}p@Ct(eZ`_$_m;lhW_Fd?BX5 zZl}a@F~c;;EMkkr@-X?!gYqz=HMuM{i$Q`wd4VWBxdpYNOqeE>MNY5gFPDhp!Xq@H z_j6#F*%|X_Q8d%VAU3I-{)8oJJK^*8bvtfoIvVYiYFC|YomRq^+kVKI4)+|R*AKvT zac#GVUa$^KE=kl%z^drvuuZXf1FYfhaqRn49;2@m)p<#86pfX&9rFa;Q`aa=TT4ep z5Azh*D$|`SkGw{R4Z3FJJ}0y&R9j0Mgmd35G3L&VPUPn_(F#2KIjE695&Zy!C0~&Z zqB-`-CfX|MCfnTdtY7o!z&|W+T+_Vb?&^UQw5;3S;J*aCzY(;{{qGKRkh1oF+uoAL zE6}+Sg7nC3r^0+bz*hTXq|q|)vPDe8jGI7xgn(bq+*S$iz*XUw!qnDYdyLLlWKeT5 zh)Ym5n8_!9ZB$_i+AN_8QT$*Gn@6q`)Xn|1fl1o%mWc|sA9s(8-cdcy0#PJhv4~Cs zQTT3W^)j{1xvgNNTHU_1K1fk1K2(OPo`FiJR@4YwqB$r|sIiY6{ze*}6I{5aqk>Sl zH(Zcjn})65KWdF8sK&6`y|~XCsE_e&FQcnq(4cB-hF=sgSx-BNX&EJi@hwVZ(r(E@ zR3B1ea1-&J;&3(61ni7~6v@_wWooE{DWa+*b5cw~g+By7vzAdd#3oLXSUwVwDv44E z^6>}~kuHgnRmAG2$;~_^QD1At+l#%6=_i3IdJBH6^_W#I^?`<_oeQnleM4b=Em?l> ze6;?V1*uQuq7YvUZedEvcbG_gscJq5Scui%#EXW1weRM5sFI{79bWwMV0N+jf)Hc$ z5Y1|Kq44P&7<5bHLCrBks|D9#=d zlSY?RRi9tbK%-ytN9Gp@K;{K)$64>F(rlKRrU!NQn<#;o$D$ z@x;4iz`v1cL*(uG=;-l!cl)fj0fN56jfG0yTqj~DLi6KL#J+u0JqaUX4&VXH%(?wQKA*?y>n{xlLzu^&{?|fA zgw&&I67q40YP4W?wxQB72G8*A0sqW zj-@Xjxg*jW$tN^+jMaK3G>ojZdKxA9+H^l6w}eVyE&Za~nik^_RBxgqWosGQgNCmM z-A?Q{GUnBv`x)c>&c;>RK{bntBM#~nGTZn%v8~-3IJc>fY&`iBlQ_7$XV)SD;>wS| zAgJm*)eX+oLp<+EAX_C&K6(&Z8D9s?N|DERuZM9mPOnu2NdmD-BrFp!kl^ z6ima3-~9sfyd;EQ^~MAtvB5Ouqu~D%ss2X%@4rtaSvdcL7cX7C+XiHod%+-BnU&6! zloCS87ITM54M5$;yg{iG*XnW#=;7Zve;&edZ(Pi{l>EkS8Uj2I%O|T)9wzULk>2Z) zdXtu9E>jdi^O*f4pD&KA0f!LoSM&54Zf-8bo+@A9foj}STHlZzrD=s0R!KApH(!li zv)HiG-7GXyIxNRYED@dOxC}fK8$tShY6hf zLOn>%L+5EXGlYP2c1OS^dcqr689~IgycGgeO;j^>oIz*ea#tRXyb)Cr%%>kLY>SKG z#n2!NiCnNirQ_&CV-dRssNu;mwAw2hS{ffzvKbGV^5|L2jTkQt@Y)PSVAt&wRKx-z>wq5R!x{|_2s zu`o48-zfaJQi!* z6Te>F$gZxqjS7xaImkH20K?B~NQbpA#b5NKlhamS(5LWj^iclZs^{$0wdI-LSEu}W zcI|Msu@brHdEe*t<@T{?Fr;(6Lx|QGu_}l zP5m`u0Z}7qj09CJYOaK2EhjHKq~eBsaY%dGt<-R}>b#u(goIs{e_k+;Ml^ z+(Gi30MfL~L0hrAr(%hX@Es<3Sr1QkmHTU1lcHYgsbTr1$%QWrASyAni_d+ zY2TNyvN(+|C#8#DF2B=sm?1DM44ppvuArk`&tMvzA80qSjba>~CC)la&3_CX&)yfC zmgEU6jKSt_B=(?Ob+?k_X=~6{lf;)AGF6yBo}JuWc^a6C6f66Go3X z?Fm|KGnnLIO88>Q{jg!`@Y(gYSx7tS1^T?*SzBUG?YL}hH@|IOKDM39Pb=!pE{fOEd7)3g~G-lAI z+;6u`@mkftOx|Mt#)=aR<3Wsn*T=dCOgkFwX0?GE`e=!z##H z;*w2Sf2Js4-Rl+|qntO0?3m|Qk`^qXR4b6S&s58W#F&$TB>k@y`Z?2>M*H5@qbF4y zt8bsRz8Q~h$25J~GLY0^d|d~M%u_cvZpUySX)ylO1s%E7kA8&#?R{FE1duc+2X&)G zu9zU8pLUsJB%C4pHH^+?hd83X&q}6;iyAGN}6c@xgxTH&a(m?5t`NtAf$97CziRF_Skzp9yLSgxWNme(`kGlee%XnArI z1kS9<`t1)_Z`ARD*h+=?_BC(p`I4CEzj`s}gcRw_{OlVx2D%jKCH-nE^N6c8yM*V6 zq^jm%VwyBR&1V}bY5Q~NX^RYZGzFzvF=s9qMvw=I7m}lER9cQjaLJ0`eh_$6Wc;89!cG*eXLj__=y59is6Uhm=9Qt!b|cd#?8Lp{-_ z%l%GGbkApo>HgAuc1hz*Cg)thI3nN&K5;% zbXc@DH?fVPjlJw{U1@cFh^Sy-V61q1_ICMt`!Lz*!}n_MbAP`-39ZB%w--AT%LP2} z%jW>@M9;a2@+j@0o`p`3&c*UYJ>&$EBT0L#9UW&)4%f&Xaila#Em63o~^r`>no=T@wziP5v*D1?VWqI!U@VDGR?h_idX{4NB5DZO1yUVYp6i zK<7%mR&1Ug?S7JVhrnUaaZFD4Lg?Nh^WN7{aNiAC^1q9nkiQ##^V&K{2UR`$Rh+E7 zoQ6cH(t@I5Ctfi^YDZp3AbL#(NfdfrT5cpLblf>3QQ~r6!gkE8C66#TF<@G&d z^eD{j+QOrtn#woSx0`3H$(EmX&k*f0d)7(~QtK4vX|gLut0eCaajqtEq+Vdm;0X`* ztl;0T0eu^orqfGG)rFZYAo~)#fOS)UEUlt5R7Jj?Oe5^KcW+}HE8Hat$*;9M7pJ1d) z9f8SY;N5*Rq|b9%XzbkBXg|(wEWQpI3O84g-KGZ>+&@(tV;p))kJEO4Eg3O=OI$2*H^LiRsSp^%6cPW6rm3$!xV`6L?g z`3Z|>Z(R$2iHn{kiBQ2j$IyoFeugt9!d+Ojk8B#i)Yo3f7HY4^DLKZ)Fk7g%Q9i+D z#p+5nN&?RpfCME8hO`>$`5n#YV@_RI1sL?n!lQpbcs)U_dfcv+qwv=PXkmz6;`cyG z@rOuuM}Jk5i_(|qew=C;o8hZ`;t8Q;4TO^~-UU_VO#=mtG5S%d$0# zQFUjfthty=F`^ZCS5SKPwu3P~h#xMAe9#G!EX+kh$Rkt?-fiMrf$k@{uEJL$9l4OM z`>Jc1U*B4Tj~k&zKUmzGxQmUy@ZE^EkE?8{wA=o0oK~VV8CSSC@eac{fiSb+i}Fd} z%gV5tIBs(I5J%XWzFJbA3`$bKN0`w~WvdZ;m;tWQkEH6OIUR(Ca*H9AA-=oVsQt?^ zjFXt*W%LKFEs04Z&5uo@OW7w0QSa&`~K+*sev`*wMqzvh&I{K!6eubQ2Nls0uB{Hi=&CnyzTaKUnZ; zDmyhz1n+J+N38}sUJX;$7C9Tjnyal&(A?VtPF6kIJGJZ3W5AU^hx;_T2>vu~NP@iB zj{DM}ZSrc98h%4j2S=9m=* zE&d+O9g-~1l%dZf%p3ot1GG-PjI4a~6#-4-Xm%QXD4t zk=C%~^6o8#rS7eKS>arKiFNPLtG8jgMx+GNY={Ic;JmT#T4$I6 zf?lvvSmOq{C~lJz0CB*fna^j*riqc)H#}y5-TlW~AC77dlT3YRE2i4f0r78}CpFd6 z#$2tkoGoKMi5^;%t0g; z@`1nxBQCzr`Ab0j8v*M74v0+5|55F0jV9m(0iu|#o#Q43lQ#L6RIz!TpFJ>v<& z=Oa~vA=%wO!f^u7uhjX9FZ!Ud%&%k7W1H0@8p5=uM{}?&g}Xz{=?Ycb1`Ut;t-V>Q zs+qC;$_eqmnn(3wY)-CI_moBV1+*v$e8lSGv_mIY_- z+Xq!rNJQ=3%fYUYEfnm#7|Mhre7GS&EJ^bi==QiJHcE)54-~8N4D2s(Ne%3>N0N~t zVtdH}W3wbF1{=rU^3CvgQ0~)@!Vbq?$i!f-;HNblODHA@o|qvS`QP)YBi5W&*T|sDuHmn$ciMHNVyrLc~idW zJNFq*y?p8ft@j=5FdRGqZ!Q5MHHFnjI&of3SQ&k(1iUn|vukR@DmhH%z~vtZWH7Ms z%r(L&y_zV9%qHKk!DAbnk(l|O=1@W{vvkpu243w{Z1@fJneze+a#mOK6c8htB{*@| zdPs5Cs*+(>yg-iIQQPtbAP~#wowvo~?d27;5>xrY;OKU*;D&&pZs*(W{rQH^>(%4& z^F7uqAI_RS9nO+I8;-82A&dSngxJbk7qZ}595zEyK0&;@Ea-1kf{dbgmAP_5;KfZ# ztfMqEtW(!by3m%1G^L^Y#^?xYmZ9(&DxT&Tk0!#0#n!2m7h}&`wgFI+8MiZ-PZ0Z+ zwh55wWIv80j>r0a4`KcqWy3ZGW`&^3;GV6XXI0Xb zl8R;KlEHlZcu(0GRE_lW7)rSl?si8ncQ+(P9U|RKP6(aOkFMb|^ZmOe^co9E1r0{q zXoR-1wvaO!Gw!?;$JFNDvY<;y7%{hsWY$&f?$q248*?{XdD&~|B3ivz=$FuI{XWe~ zM=NQ$CThi{&At;ul0zD=^0a7&3xo$t(ZlYdn3gU>wU`sbyT|b|4)%{vJ2Pz<4^QPn z%32*2^m5jZEe&k-yLbyWmV)w>>(th>0HtUt0T2k{OBgA({2o^~p0*=Ki@`&|$jkoF zi8izn{9A15P)kGK2hdHcli=Cbb9krA*C{V6Dh!{2-Z026`AXXbhK=WD`B!Me{5PWV zxk34Qf3C#H%*@61pIi@}zvJu%Kxk7H_dvv?&HW{{H-nc{3jx_lprvk|Wj4XY#Al^!crD1oMS2<`jBO&F+({0pp!2IWq2Yxx%##PN5_82Wkk zWRlvJ;G3y03n)lESjdL@eD+aXt~8!0}N}m+Ch`m4k#!^+3z2pI%l{`luBjnNK;iNfFq_urhNqKo<`R0!d>lhp234 zHaVQOHl5z;CTFLQjVtl3!M*#FjYWd($F%Ov?LICZZyQCx#&3*SZ!g=Uj6Pn!o=;bZ z@kU8^c4yDuehJ?Axxud4QVA+408y4<(n*_Q-J-k12e?@{XC`C6N_dvY$2w74?HfO4 zSe2Wt&XBzy?{d!O4~Xp^17qn*M^KgWs=|-l4}tt#YWF9tLQ{c{5FeXTWBQi(|AUsu z#~2Le724Ii#&%faCuId#xj|)f(%x%u7%hF)@dwq?_#$2!se)6&Qo~J}##-~LsO{fG zT8Z#gWc{6S7mg%Us&LX;?TJ7*WIjBbPWBi=vg{N3lvzxDW| z;g6GkKvw(h&F6A?Q*7{46v*1A;-?xo1#@;{@G@=y8B9 z{{_CSNEO|0XKpO9AYZo>I-#XGy2_TW;@xnpYFEM#ZIe)}x{#s~=C7Y%Y5aA)zxKGN$SUh22vQ4IqFKSL?a*S7yS&Sj=jGZYogCe_Y|i0 zcT=a);^n39xP5g*=YWwDMGO3RBs?ejT{!!llJ?xxJ7zsK2NL?sMv{=!GL@aGt)lNk z27BCgW~GV&rR)3)BFH6T614VpX69l@=Qt!g2WyFV%jxaGxund(alOR*w(EmV{%w}LxOG|~3kDTYu4jF-|6IperocC+98YNAfdrljwB=@TEsowBs@C)OxRhcIns7B&O zfEEqJPZWXVrkTJjPo(h1IE~HB=;!E@07LDDUnC-N5i=6;m}*ep555*Ru9Ikw3#B2k zO#qBk2h5;4nNm|?TxKZwHP>VzDwW1Y#q>tqovm#@69syEwq?UCs>%})F?ME~ptcL> z5@x+VT|Hht-2w%DUZ2(~vwS?>UO$Zl?Q}#2%2ktfK|#M@{kqxA94p$XH_74~`4R1+ z0hHpUxD5@AIEz_e6nycHkA7xn#GV1w$L2uMlsFO^;W2!#k>xcHpVJUMBy_~n^S&A} z>4D zhyVw4=nmleo72omQ7vqmp!&-l{r8n-8S-_MOQrzi~nzJ%;NU?y6M zpX9Q_JA{wf6h}eZy7ztWI{caXlb2}w&?VwP>&f@*^>{?+<7(}v4((UNQXBITQ054jdHEQ?iKNL5T5Bt13OClznnxE%eo!iso z(keeXvAO42a>O)Do4KzrtWfg|gXXzp1hHW^NN)27n`X-g%XW?$N6Q-^&p?f8w%cDK z)Za;t_&0=NWBU(Y*tUNm6jKFJs}=PKoT`<0$_Wa5API+WE)|`tM`@{7!aGL^YsN(~ zN=~m*`EP=)=hhY93ot8IrSl$Iu}blK;BJ3qDJF}DYAm+Emxzgqe2z8v*i_udP9ipl zkW*m3*bhHhOxNx>{#Ikiu9K&3`_Tl4j$xI#CP*m-e}U?oxuOQSe~{jfAEC?3aEfGq;3*P=!@84dK;JD?(ekoI(C$JdD{F37_Gev3Z)FphVwS~u?)nQL^I zET*x=Q&wUBU0mQPz3h?13~AmIqr!uge%ZcGS7=32f^qqJeazz~1?k*?o?soY^YRqx zq|UWk$hyzhHki(=+}VvOvpMpuW$#2nDBn$oG0L(XYQCuekU+ssF#9FiVZMtD-wyj0)RkD;2V>eMJP;b0-6A9s*pv_<>Kq{YeOfE}`-Xva7nf>CuC+1;7aYdMt@+*s$Wg&>H^=(Pz$dD?x;PevO?1CYpJ4MQb+aFlY6tH>A}dL zJdg7{X%W#Ykj|FAPWL(?>Px)wl6rl89;oN^^7IS`W=p#+!xD~r9>A2}>4?w%={`gv zi4)V^+N{0P%u?|9g*uz2hBP7I}He3z8l1f*xjl@~Z>eD~S_>=Lc-DBpaELAJW7{!k;{vRPeeZ&RT zDh++-H}WBol14#5b_FH-qmYPiFc{)HTyRH-1DL6=mIRISip_cU61(0!TH@3olKf4= z|D+R`?r4+~m{<{;ZOiR1IV3`2zTsf{T3rpk*6&up8$jmTMa(LCeJ#m}nVNF2%MZ4& z0oW+CU;)-pD+moZR;-IARpa_;-5kK)CHsF2?fXB!46r^cs)cMsu)$enX)?AO{h8EF zAD{*GuZE)48SU6#k4@5kMo_~DaX4hGk|r@@#3{lo0e>{4959uagBih16Y~TL|C|?M z@iPJ+hKPeD`yfdXBa1Z*ZGNdv#)m0|DuoJb^_6yVt^e%i^(@!?jbk0!D9Dwds?S#lEJl_%<$nxuYu8Xus-?HIl`(+^(TxJ0gMtX| zf;dD=TX4?jXV@Q{^^7 zq3g%Hq3gZTtXsh4vfEn~|LdtvBme974n7V}zGI2PD8$L96!V5n^U+z*v2l1k;-q_; zVaujQrLrss-?7(-6V1lWclP$^8;{KD#cD*Pfvs#?J0?u%7Xj!;w5Jt;BRnl;U85|X z!Rp!QjF-iw=nVIh1OO!w@8P1`(A3*cs@ET{vHRuM-rA;XPlc`yZ--Y_=}sa^rrY1~ z+W7EH*Rpq)xQ@kjGNWoI_I`iWFwxTdb$*HGcyEApa-P-JhVR;n|Jr1OOZoOTY}(m5 z?x+H5A|2dNnvaLdU3q{j!lBVH=&T1tV z)5o?s0Zrw5Y;EIuiN$^S=`gcC> zcd;fY7K-|#gm!FBOK?@lDZ0U;T0iV1RSGy<`(2brt8;6;r`7rE@o@>1()1-lRJ_Ch z0?)3wBJQB1J;U)FRD$IX2S>H^kmCna6vUC|)i|NKB3g9espaH-3;gv|7VCHirEXf$ zWhS(t6{*18CJTWi5fP+8d$WU0^=JZrt|UMR$#(>voKOI_{CEHQ3<(wYXfa*t=y&)8 zg9h$mm2lS7*zMr>5V9RfT#LB`fncorS5=Y3bGaCSyD(DQRrsST=9ci^b>Zbla|U5$ z`qH*bb{8vP;z=&PiX}q{iH}*W$cfK!{&1dzG1MXx#z)B_q|Xpr*J*|QQ~~o`J=7Xu z#tTIBxIMbt11@sDUw?J;V1Z0+qwC=Js;iK=@$|S~IbFMFB(eeJ%DrB{uAFBHczVA) z>Df07Pm_;>wd~l$FH@+cB@jNs!?-+qj9q{0eC>!IY@<+m)VT0DIb;YJjs$0Agi`Rs z89o_Iaf+J;uZ`D$6pxPuuZ`OTCmsImw`o+>m5+4sm7p*7cEkJUi2TeFg~T`QBDph; z5^MWkxo4q+ z%zn@LKLK&;l#oR6Hv-h@rXVrsTJ{QIr^k(=TvO0S`(sPX91jLhNy9doElrO7eLBa)@@&)tiF!}`RoDm#o ziPzt(5J_AZI@$E6n=f{qxbe5rE&iDv#{HkNE!vW+qmBQ|0c-bxH`>~~ z9z%tV)Pz^mZz>#W3XUE$-L)mcqU|Hd$WPvjJjd~={=nN=$$&aOkB2JtA-uCJDweS> z%GjU}5VRR()$?=RHJBC1;lagPPrW&~Y81#iNs&4+gIRQKF*>V}Ho^A&@OB_=+-|_~ zx@+G|03h6l!w--RPUP;v;4bX!ii3#Zyd{g_DkuAnNGQei9V76D!^DK@y=q~oScp-y zKXx27tl{@DArui0w9uRdnoxrT2*YG@KkNxN_0Y}cD0W;YSi|ne5jW=V$2xp0`{Y=` z&{eei1ywWTBX+xOpZ!z5D00C==7fS&2R=;DzM3s`G1~+dgIR^2?pN<;NOjj_3A>;O zz;jg_sHA^F75y1%oD~}xMj$F3d{5I?^q^d7Y)N%+nK<=>*x0}xO>+%E^ZLi&K1`U9 z@d$sXKJ{i~34{XmB~+1G@n~#uRIJ0A-F3UZlaxf#;6cnGM0%VI>9eX_mdLvlv%spU zs`uRnIe@$``d`yl$-l$Wj(i~6&nLsAllwHioep6bO6iA9DQfw%AC0G}{)Gxfw`CeJ3aH6ljPvdr;(aOTYn&(c)9t|ld(`;5%7 zk%)r3d4|=26k~aORP*l!K*jGK$+Yct@*I28l_`|>`{8PMk{dB9Z{kd^MOf=ik~V|+ zgz?89ucJNTZ(jp5cl5Bg^s)hR`}^tD%#XHIrQfEOyqGU%xLYg9K?$k%1${ERCmnIF zVd>T|Qs(JvSZIu4v(MXoGMhKAY}HC!?Siu3_tMw1$W?zVL{%2bZj=UEuVy}!ZzlZt zp78(hOAPMtQ0yl2o#eO>r*+^!Z)Dsku)DPUX&nf^gn~w6BqAyP5%1Fs zd^022QP3(8sl{(r`kS@DHM5Jqg6v|r+O~y%i4%V-OW|KQ!TBGuvf7eIqd{3&!638P zRKxLB4Z1NTEeGj;GmGgt(U5#PidCSmNhvwoo^-mk&B$bHzU45Nj^BK%kLp-cw?44% zUG7uHeprTqx)nc(FlSrtNHzgn_KPkKV13}!s8&x^qMI+oj8N0Uk0@V?WN%$k!d_j; ze1%y#H@1=O+s+JwO>+A_W*xa051Ay_h{DNX5AUY{X#9?Nk8Ih?a!=fjNa5n=2%Ywf z@_=Gb1Wr`57Sa_W9tTc@s{!ZvUGjrZuvjKI5oQ>i=SisaCP1Pz9LR6~1%kWfLwJAh zTMWq%cR*J_v;Wk0HnGdfa}=_8(~^gw>3|^OAimKc#6HjcAadyrKj?f+JpEykNqd9g z@Zz?)fy~_=v=u@>ERSp1Zyv44=xOee-8qbk9i-|r$-TqFxyuz41No|?#-ZkWNc(Vo0j3) zKWpDv$3q5&Kl=uq8Wzj6+B>oA|LRrq2@C0l=Xg}l7O~PDqq-3H_BGIz+Oi9kA><41t zY?8r}=DC~`3jV6w*&l=t_nq^2zP!A`J0h4r-rfb(3{fB=s?2%=rIJp9Qb{jCsig12 z4hQ4FcyaH1E_z)ihczf9Qck|0S$rlhm#qLTyr(om_HFnI;j3FP)sveJk@;L9-2Dve z&h0Ftj{vNG)baOe9sx_sb%_IknGe$dQ5O>XXmt|L=E-t%AD)<<%YYqU{bg3pDYXf7<8&w5uO6#P{PoL5Y6w z2yXjIDM^!_8IhacbJ$EJ{lCTGKU&j&cL0g@H0kLPB>OKE`?*6)Ufk#2Z6Uv0pmqih zFI`e-K$dOBxK~}(e}BR)1h4ntm4lNpoQ?^~n+yX$}DQ%ms2i*T;!w*$?o@)BH1ps(kBE z5eJ*N%Obs`HWsLY+PzQW6$U`l3TC27ZNQo75w4}+b<>JFpF`g5t4apsz*2W?dXWz zqA>RRcom7}9vwcyNqr&Z1v%U0t@1`q4XL57NVyEWw@19ut3VUWb2LL#21B+tyK?y0>@CysxSZE)Y|K?^(=~+xm2Wq&d!hB*EDQ9F-0!!CIgaoF70myLT!4V#jW*UxJQ-gF{S*^^0YQAN7JJaLbzH08DogLxf z@C4UU=aQp=0}$_z=$%AaYNJDvKO}z3h)|RGM2wB_r`!e%chn}PJ zGa?A$1pSv*tFGaZxs&<3u~*%3mXW>83Df*!hS6F^xoL^Kc?UlvB*WB^%$fltk;tqgKn!mn#E! z*yGn<+U0*M$KcOYdp4H8L4UL+wnTgv17OYa*RqBaZQ=oWl#?X6IP`*Ehy=iXh*-zV z6(_eQ(F)-aI8oP)s;?31?axdf&@Pie(aNhP-iEveEslY|uCRjcSqpp!d78ooJC&dn zT}ig0ZDg3#vNqIl)nHxrbz~hzgx%xP3%tU>>Q?UOJ{_^ewlNH_j^JQ`Cw4TzbXiGW zWC+Wg^Kz}e{lp7WTT2IWMQ8dU87+2Y#c^5`cdnM2rE<1RKQNFj@OWP_m&@ zDA^hHQebTV_1pLtUGo9d)lj#zRa5~2UvoTHz_bpWy$H6SAw#V<%``~DYs^Elt>H}} zM|XOvm<6_NCMczCa4_vEYU+Z|aoyl@jH>eaP^7tC5k)){XgBvSC;2FrN>O!%GG|4| zT=Y7{a+*!(9KO%12y;|_d!JH4iCtE`4!wD^fx$`G|NH1AbnvI;5Qi0znpS=tV(sg~ zfm(0kiYO&e)7kwz}Bpf{DOLVWZR((ighm+>sM zFItvk=QDXcoFC|uXSMP=k0ER^!{#uO z?E~J*m{8HhA)sMN7+_#mFj8lZB<6nZKGO>*n=Z#3N!-pj9J9yP=wi8~4`QUNY1yC| zXv354X`$|V*}(7Kum!<%s)203yn(H^x=5Tdlf65M0L7I_swDYS)6{K@Q_aR?C=@IY zk9nBfdN=_w)|(Bf{N1t;;k@0lu6A9MHS%MQg55Ho)A#N^cfqbT-yI!OBusN;v9sEQ zyTs@gVAYzt+CJGXwiRI2o>y^J|6@&;wmw7LGEtqFS?mOfVIt=eiFE3U`L`uK*8nL% zvkW+vRK=s~n9>(L;Q&AJooSbw;1)eu{@qpoU%LJrR=YTjFpj@Q*cSZRlGr}9(0*Xp z<1HWOYt?&eK$ck`@svG_d3PE8w<9$ho3Q*0F>(|15brSFGAFj9?*5G)d^IIWg0F#u zNN%z$dBlG8o8)%0*@4)0vxzZux&|7RWcu`xW8$uT;d}-4=(1FPR>5-(_vjFORW0Ct z@C``|XwbuA=P&KYe}>)%0D1oR+q#vcs&dsou&P?Yd7?;=^mTFxp=)MBfjN-PwL&s^ z0sz<|S^kZVfQUdq%K|6oqo@jx&{I-e-VDEZ+cnaeipn%?DPt_{F9Yaq80XR*6(t?I z1_CD3t#%_y1L|}gI+)F!O^q%XfzSvw-QHjRbRpqAZLm&a`3ZCc)wP@FU0IvS-y3V8 zStz}Cq6OJQ;vuPJ>qYGNR*8^siJ32hXf!bI8kbFtr+iM}5(?^xZMY`rvtHn zAXN|s?yOxeV1@fs8Jf$i2}RK5pbEi{N0tt3Ob5!?Kc0UpL;z=sa6)Pi4=QXViogjv zuW^9`u6F5-5QQ7AB(8DkP8d0aqp5KTJ*WC14o+BvNnIuc-<>Zc!=wg3)Y6Du9N|BN ztuU~6fK_Id&h5kGuGW}u)VQ7SBU~ft8}q=>w(~r+ZKO)2Uw*+(<)TxmQT zqj0AP?5e8DsBV>OZ^Hgk+|=$G7ott&Ho`#Da@%VILEmn zdb3iQ~J#CuJQFW_5|~((3B?bZ(0qqvG+n zbL+#+SM#&I?HQhU%B9Wyc>}2x4URMq)Yc6RQg*a^`H|% zcl_qa0scqsE|_R{y<+L7!^nK@lMW=$VSN%(d|W7Jif~k%3q?t)t_C z*TpJ(2R*eY`LkXOMLl^o!gWYl2|WC9J@weaGgCd&OS_iOC9A_Gih4|JgpoEEcSH8c zKauAMx072Qpqh6ZPKJM&dMtlZ ze$hzt5K<^)xC}=Wxm}BbbZx?Rfy<2$ONs1hO3nfI;3l{-UYeft`Vab?YE}N|B^SOG!Gz3aMa3xdQma^xl!J zVjdC^zkwG3l&bTJfZd9~wRsw#2t|B(WYibrg7LH9`wp9@@3%*gGo>36f zhrcuk{~>yv@oy8vl{?FEm|$PxpF3@J`m6GPP$*RuFP$QW`j9hwk$*>h=5injbj+tu zOg3A}O-|d|>bXr%o)?bg&kvvbTJg}4AWqduT4xJF5l-ZtIOhsf(3J;evcdhamOu}x zQS=V%qYK#xerfTDO6{0x?tT&_g)@g&;s(aoqJ>)gI@TQ><6b5-n8GSGs*eM^ml`JV zP26URnSST11!Ps2+ycnjz6ZOR;w8IBqA$@4>#5o6y>jV< z9emzCLT>`)(oq^VingzdreoA`vX~2MEm7^8KqMYR$IOY}twStx&p|Y|{lX~NG-`@J z6sYk`m^R5M*gO3d^DM?%B*py)mURgA=DcO$@{ol( zhpef{75db^$hJ5Oqk>GCYlNZ?Aq&BBl?#PYPVgcTg7)?ahbcEH5C%*OB6UZaVvkPj z0t>3v`Xaeo_k;@^EM3VQk|H^*)#b!-=*gC{GgOnp>@4)~))|faHYnvNmwGoAiI}!I zUtM-bw!K_mQZwU&6}Ngi-DrPHJ4s~7I)03P<*N$t`JJ`h9i(fgzImdni@Oy5jr){rMiPXcQc?%Y?jyLo1W5+nj^0ku=GFM-yqW6UzHKj0z?oOAFZbpuM>uYVxc!CY zYH3~l1b%^RxzO3dp^WhxCBf}ruTuY z5g7wg+hyCY?XXdfKmaBT2p~`}fcVWo79)Kl%o7$3?<-ga{tBAVS1l+E^eGFN7AS^^ z$W(ML%S?uulp{{lbHH**nCzo?v`mQKH=;O#Y!s+`Q5-20DHJyHxKBgS`u^321?B-L z0wLNlzvY|OKO~D%MmQ4LC9Q|qTv1eBR6a@2@}o=aM5^B!(KSgn3sjrfz9j!2Lp`QHIO@Xt^!$lP&0!Pz084L&kv$xw6{8iCrIrnl<${x03t&tjP)ObnGG4%5rHU;= zk6=LhoC_Sd$E(@TkD^Y~%k2 zBX|l(14sjo1;>g*zbS-31;BdQ4%o4%K$XFBCq^P)}T$i=j z*oy@_jmKj<4Jdv)QMi6Ph&Dcyfev2=Y)IKQ&|DmSCcd-YUyf8DZX=Z&B}0GE zlZ*11U^WoE0E$i5GV%>THj5QY(;Duy#xp}x@~y3BP+6k|v};$KS3# zxXM?2Gz_A%KxfvjP7G<0WLc&%!MBr{w+zgTBYNTWonkv+*dT&+P5&nWWctMS%YmC zt_&YRM**zj!ECP-QMXd_^3}shQW<`Ig2fV-=LOrr)zz^{GMj9~6q=My9Kh}FBW@KO z0{aPr{4!{ugHr=jPR*_L*&-hO@MWtTP{6~J+ug18?egJlz5V&Vzn^Ely=}#%SO~15 z79|%fA&IyMEK!L#Pf+C&W*oG=J<$w+|oMhQX7#DkwMzX!9 zC)(ir5h#ol<0L^a-S_-_j3(vT*ZOvSq$z#*bAsZNhij5X27S!Pl9mE}Yo`@`ZKn*q zt#9(+F9-mP0?vR46bqJUnk6Y?C-)9xfF1qr=(ER^I~PK$ZA=0-AQZW+8xt|;EU^g) zMgIQK!G5M5Kr>|0vrN4Vb1v)WzvW)r*Ntk6WO+o_JKGB9hFE-Z%8lgvZ^OCi+zD-w z%o&DUu6X90<1XBw##_#FHSk8c@Gf(}<}-Zb>{(Cth%|Yc<6!1#B%Z}w#CvqX??Km% zq~pLmPcv5Hog}qCFvA(MQJ#`+eXVoDuD9H)`-xnxnHJZ>8Ew)mkNV?lU+$jr4US@; zPQKM#4Zc_uFWzr^)XW^a+H@$I)N?hhlQU&{*mTI5pn9#)0FAyRK0Q@5z1Vm@T|thV zB#xZ*IBw4N&lin1<#O*uJf?9R+MWUywmQbWo{Up&4F@Prl*+GC@j@(dkh9(W9HTq| zR$j|;hVU;<)4!Dq@TY%_h3;=+p2vXXbYwb2LC^fR&-Kfv4qr>SI)jHpRBEg4aQWI7*_PI zrZ1*4zo!uhk@oji(!=ttdvptcjcG@;Uf*^4_jsRS-@Ip@x!4>b`)JK zzAl96K&2KOMnY+}{vbN^@$T;R?&{24AqOSMi2qu~DYrHY|7zx`6ar5NSH@{(``i8f z_2bo6;_`Cshj zSK}F`7JT&M$_|et7xJ{Pp3RMx%@!D``K1bW)Ryxb_v;aw0E9X!11IWVUN`?1LjBL{ zhV}2*``>@jQRse?I#gC|u~ykNLzAZWG%Yn3lkpmZ8F$kiroo=O{vYW5ue>O03N41Ka&WW&__88o^i&uUJ&NM?SDxkQf00 zIVXp(Lp<0ILKZ{ZxyXksmZGO<13w@j5FHa&r}i9BDmxH;l?zsSl}iW~27!*U)yE{@ zi_FGs&vx<;5`zjr9w+IDOpzxazl;*lVD34U0NW&FXw0$D@v&x61!`89_(DN_pevek@K1v?Q83A{eGEW8Vy6Q zT{q2^FbIm(_;CU5S0*xy8}IPia`*Zy}`a`N)3&d4^vexwfkd%4H*CUi^8g zRjFt{9<6`x(78&K?gvzDQlx1q>kXJjE4&L;JQ*KFT|xErloH6k{F3O8?=DKvKlA4$ zvcK(b#woykms6!0u?aCz;!CjXR^IdxLkSE)WpP%D5lty z4w(Dx(JFI!krRXJNbN%if1nlt8999vL<${+w&iC8M%}uiQ6(5gU9O1XpkC*1cvY1J z_I(5*>44b)6W3ydV!Hzt@m!ZotG-U#T3WxBtErxO=QwrE%ZF8D1cB^?utH-N5Xq(~ zU0ADQE9ZOXVA%Bm@_v-ID*^j*>qd8rgb|3~(1l>XPn-J3wAa6<&7mvje8u*^q);5R z2JpNP$c(=R*U@SAI+v0*_v@Diu}vt+LN*HLIG$OoztOTEkiVDP(0?JmI5|jMNbt_E z%;a9-e!1DXI(az4^L%~2Y0>0)yM2Ap5uO9EEgQ_~7T__QBo+5du<4*Soyul(0IGtf z+pRE6CQZHRbFJpq3N_u5*?((1lXH_@;_gMwKb5nSb;~3O)p&j1vSg73A^TK%%l>!zY25xt^LAd@<9_#n&h`(D7Tt z?G(p)9)kJCnir_1_9Ht_-tw*^j}66D`;OC+<7UlUCn@yHi=GKA-b~&K7%w1nULcg8 zfC@$c&jjf-57!<|q2a2j;IMn^(VX^FV%*GsZ2~l0AyY16A!A{;ub|EQFY;6CXC-6z z6zmX$zHjwIwyF=X4{*T0NZ%CtSKU9Jy&D@=5?C7`DtoT%`#`{c0)b=!LHq)e5f-6k z=P&QJ9WMHu>k|e|Pd-re87mF_UFPUfeUt?LkE8d} z_nLt86aLHyl8poz&T9n5Pl$-=Jpnm0Zo=4+fayMbf8OV$`y3f|5n+Y15twW@(mIxe zz#z_9y}s3Y``yP8tj$B9#q+M?G^K^-r}EwCYCW4NLV2L$N%%#dQys

uh`^-TPlw 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%0DmlRCw@Pj2iN%bpkCbd<1ZVkBwYjxayhE9 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

)JNzOszoMOI!@TQ+} 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

s=tUjh>XaUM)b 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%0DbTwxijKJCv9|J1d7c0`|8yg3@-etY0}6 zpY319fzs6Dm8R7cofn~l{^XHAj9K`RweWLy8g!G$y(g*&_E9N(wib9QbP_^k2J9#6 z$cc}t6;Hi*yIgB9X&|5jpLL|DYiD^Y$lLZb<81rfByX3cooS^Y*q+hyK3(IxmP*7M-b+$y57-R@7NDLihf|h`sDJ-( z-#)QLPYs$!tIv|#mkXOehVoGh<6ID=Onc>l)XzRCK*FDwzl=6q0Y)PCvN66%h_$bH zt62IbYa?RJv?h>69o=ygo)8-boNbbO802W`NCT)wr#g`3*x=(g9kowCMs@Z8B;)@} z`riDhAk70&wH3@xE6?K-wU}@gg&2Gu-{S~$J`tnQR2&f5_haOK6deCh9QN4^>;xlH zcDO`}&O`$HFLRx94&o!Jci~nS+P!Ce31z*+J`%bvumIh?e?)Az^~Ib_$|BiMm4n{< zJufL*Zp2Ah-Dzu1|G`1g8S68(Xw=Ec$P5}L$l}#6UI`Qa9IV(<@eK~jib__e8cM1T z_5W&f{)kaXC94!Zg(t_3#SU&o`|rk&g){TUg@XM+zT2)v0cAPOs{x7tTfX#0JMzE+ z#}dK!W~>&Lr~Li2nfH^fjkAqXx7Y|d3i$G>+n3Q>3xlc2EWWvxN{?{s7VnpQ9c8HP z-5z1u@4Hcxw*=wqHg0rJKrf$cKBch7Vv}GLpeu% zz!Q4>?=u^+LEX5ax0McV>B*??cv*>PFuU%i)BSO;R$?K863FS%34-pr(%#I;t*>*= zl)78=F_E4noeMI87Y{`D87f5FsPsUYTepp5iJ2yQknc1lXyLOwfFW9Y!+ zhZMt=3Xb8U{>^S}ama(BNRwGG9EH00lu&ojbK$o!D6q;^0A`N8$GG?h6k9f&*_pWEqu_E z>zQZl(~h?UV!CEli+UBC=|f3t$OyT#L~Z2l`k_-#wPhFlmjQnNfgLg(#Sp->%0Z>2k?<(NN{R_-y&%J(;;nvG4;2?1y52PFG)D+m!h1=?_pUr-F@1*ypI} z)KQPpjC(drvf)h|QMJ(rl9S`+5TO07oBey(oWdRZ*3&y7JeC6~sH7DOoXSUQAC?+x z(=XCT9`$ABPSM^2)a4&{xJPUTjE~`PuUCoySRYsbBrw{JOH|oe7F|Dg&|Nxy&RbLz z$7POY11rMA1Yy49;mAhu`Y2M+Sz1BjvN+IeJ45A`kFg5sB0b27e7g(*Jc#*!p<_?r7->2JL z4p<~&)er}i8PC%Z1K`yEWY5aoysh#8jJ@E=<=ZUbqJfRM8ptUTvyN-e2A&<(&B~$f zMb!O7)@+Bn3Fem##1xWLHtkB-qsk_C*SkM#41tOU43*{kZ*cfKqiK%Lx8k^&$VA}y zw_@?>2RY)jH|(^G$A7_qsgh$_;<)(QLF?W{$B7u$FB@O_xur*q^Z{oUruifEe=q(Y DeI-H6 literal 0 HcmV?d00001 diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/e-paper-and-esp-sample-text.jpg b/lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/e-paper-and-esp-sample-text.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8ad36bd29e5999e521bb879a4d44fe589acc1ec3 GIT binary patch literal 637704 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�Rwj2-~K%d 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�u978Lx}(tR^Q7JYvGU2P=M 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�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 %=Cn+Ebxd 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

NokL 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%0D)BWY;m+bod{$rRqDxr$xKhb=1Y-@?r zkx1;ggOmRrAh)WzP&A8LblH-C6Z=lr7CzT6O}}+!7YEcgOI)Jit4Yx?PZxKtC7`TN z;Ik~6cKBV!%Ee}4^ZiDE2+WE^N66vd*0^Aj6n1byp~pHvdeyWZ-D^D_-LQPQC~19+ z*me7Ky{tO8U*FW^`0wQ-Ab1PhSYmv8O0<>sHZ*3F47WP8tXlkwJB;BP$;18MQ`eNr z<9lnl?|;HY*ctIu4A*qLj=H6M%rx=?X$!1Ix4B?NoG?u$20Q&1PaeP~9V1@IjOaXD z3JrG;;JhBr>V<(FGB^6J2zC^@TkobzmZbBlg_`Hj+HG-HVU`wDywe|0IX^L{9v~h~ z3_iT~>UNLg`@eY|xR+}?3nI_k!t|CU_R^FFBHs`4`6Zb#KtQ2At{W#R$qZ&0Al(^hC9zFF(7wpnFf|-%6%s?Y_^+3HmdA3RHLf zKZbK$VXB%TXrM1NDNC+$q z7;~_7Pff7FYEUob!18`WQ*Gj!tie?;#RdB>LOHlwZPDmeIE{S>d^S9Z4BS6AB9pk7 zZ@Jgj|Ng=fE!C(b*2?#<_=$1U$XYXbEUMi7VY$0sp*_k^pp@4sX5CoLU#Tywqx;j; zzdyC-)*%3g49Jg*ZO5)ku?5F;vj(iRJ1o1a{3)*)dGejfZ6g_joTg~>x;?=uFSJ`1 zgN9nGmI!|$mo%Pwac1no(tM!5%4f%vPNtQt{d$6SH_fmjcTgL4A1(D#7+qZ;%Zf1Z zz$=RE!FGonO0kW1OA7AM9Ftl-9iFl!-(2KnP;6&ZLJgG}_X+q_Y9_Y&CA>725ogyn zziZBJ{|q_xvEO`+r*qgP_u6ycu*$pdB!~wSRqU|>@OJGBXjOgf2MWShj0TN$IKzXk z9I&NT88XzAoHtV~&b!Ipu$?^4Tf%eKC>^{X_b4&va==~YmfI)q+}6%M7}L1m{-NK$hj;v7C}_>6R`sB5yLUWSLa8KmI$ zneh7NP01=(QZabfoGFT2tat6wz-oc6GS;YGpIzw5r)JdYq5e6owNzG@8Eu28GxJKy+OMB8ry__7MrA_YxXmE#9-|ly1B4%Kw#3CAw?!429&7x^4z$G zQ<4DAXXB~<<&J@8;P^O01{>ZN@xqh0*bQ#ph+wm-!Z*VLXfHp{bE)}FWZXG#t=Av^ zOBzX&I>yt_!X@=Y6^@&WWm@_^>?_uqtT6yq>LuN?SzXSTM-82zUaw(?*FMxboO*<4 z_y%4c%D=OD_-oD5;@5NaBW1#~etrhpQeCzqC|C%#|NLxUv%VR9*Q0)2M{>l_)KYl} zL@GX?s-|A|ht2PCF)JTJgH7&pwOBgJL!Vtk5jT(UcFv zIYfU$ML_{#rF#$M<%%a*9-bLa6=Ga2+WPn{J$xj*if5`?XUWsYcD@;JZ21-E;)o8s zg{u}4kcRtg7+R3_04rtX&o8PeJBu`16_dy=0k&4tYYFE!&iJ90io20kuia(lsNKo& zvW{|xX6NHXT$F9!L)+c^OyMITKSYjIXXMr%341f0H}gM35|19BjmqFyg|*j7GdZKT z-jyw<5?-{VEV+Q=ax|iyjSd|vcMhMe-uN`nk5nt2p8BwUF zvRPtXe1y}agh|kIR&1JGC6fII4qg0YPik&&X9j%TV6wN9Cc}Ra&JQ*1QACKox;Pt|#6(A7tWN^{qM>Vl-p$4cE|jaE z|M+!tJNv9}{<3w+0I_G!zPn?Vqu-u^u4oU{`>n3xp4Gi2%ZJ-NkEvstzARXozUdS0(Q44F)X(P4w&J_$F^r;P&(uk}t`BLy$F3`nvF(pWdVL^qj(aN~S`80K`!+Y2oDAe>6 ztb26-r_<$8QNpp$&JiaGOgKX{=(XoU^4rp6foq1?x1cpo}4NJ zflF6x-{qiy4laL9n4`NJCP zYxZ*$&+(SU@@>e=>OO-K`1lmgR1;0RZ#6+Z_3iO zy7&71j7Ihz`yF$-^hJ{XEsc5a6>f;im8=0bmL)nL(+O+`CS8)w1 z+_se}yLUHAF$P`91om~@D=#yO1wJI_3^2hZjME9eTF0x|U?ECGgNrEQ@pK7jy21pmUQXM6~)HiXxqZIX6hRe!2pRPfupwak}z+ zW0$Z?c_V)U_-XUg-_p|W z9m&Oz8*Kd@Cg4|6SL|k?A})~EOK!z2pZkPXtfaC9ei52D4&-ZH0RXdcyoId}zWd=l z=|7sk(8duI6|@8*b#zKyRV2gTsa|4!ynU_m9`Jvt{pFo=o`ElR%=oQKz7qva zj;qaD#;HwDH+X-4$Kfa9mt^r5aG=ugtILV@RiIvY+%kUz_Vp%Gfp}V(-=dtgxC75& zv&#-qKSs=qb5n-NHVy5q0BiIo#m|R3^Hx(;vNM^#d;iokqnU)-9xv4wY>35HFixAh z`y7Dff2#K)HfJhjzUVZl7L(5tT?z`fg0g}esG6G%q=E(A8>aUH=GBgAK=WIVLuzot z*w`3Tme%{Z`RcP&kjD}H0wrd}aN-__P14J11>#vWNwB>V%0BOxrz>EF`lM=4RrqJ< zBh`!NH)~05AhcEQOD}&vPuQGqSNCTdu*c++?~;lMf~$BCJ0+q|h;LFmpIv?-MOPTQ z$T;l~tVXhb4nxsdrl4n5!ORqEv*fsu|F8k*N4I$tW&VKz4rDr*?5GJ>Y^}nD<7Jiuv7gJcwvy=>XB~IYC8X zn^O79lM;Q$$6Je-Hmt-eRd^4<_rb3bbIkqAwF02mB%fHh3eD9GAzo)# zIC+E6B7r~A&-|kcq&|yaEyq0eBbcW!?F}VwEh~V}7|aJ4Ja=7FL;-!ndD4^;EUQ5m z64X-F=s7NLW-_l9q0ErQ9Esm|KvEid+D=Z*UfhW zh)Ey8;B0a*hfW8p>X{#gd`%J|?F|V@I{f)PnA{cX{JHfv%}tcz;$XJ|y*wMmYcgr) zltmEUumVmP=BJ|*<3{%<;SX5BsMCaE$)Y>@Aw0*jG}NX&AMMoy&9Y?4^ZCDO%VC9L zxk8r~hq6?fNL~!*5djekW1SCn=I%^4lPE&a8e#~Li}sJ2i0Y05XWJ%b=E++1B*ud9 z3KVv(D6>a=(M~DK8r9u@_M;zyK0&-K$A{Ts=6Y?8W=GzpD6LEeu1(z*a{LR%6lg(= zR=w+aql)tMtgeoIyR+ToQyfZB1WLDy<5aJa6qZ+YOkbe+R%p@ozxh-Lrtr>P6b`0ztNce2lq9J1HYk_Y;iYt)=L@C;4sS&vfj% z@6!BimB5=aq|nrV3=X-9Jqqrm05X))45_fHsmEJ+R>>DmvbFJ#zI5wSixEZ_hO<)j zVI%)BI8urOe?f0fav3o%>%oRFw#@+$G3pZ@cJ;KsuzSP^)N;&@7>E);MD>){SpN&9R6@2KvTBUM+Wan64cXTi=s^JRTm7vP`hASg3(>frQ= zDrW2278m}av22TuyGDXz4k>Pbln-Z6Pc+Q`0DUAjU;gT;e9?sJxc7qytNQQm`RD5f zKy=CHR~5F!DJdt*B1xT3bT@5yw&eU?td*3!S-ayEWM2=sB256eOLYEsnm(nkXshFD zr5MmDThg!?o>%w=Hiozp2%?Nz#kQ#5^{>iRF(KFh_rn zN-U|kTw-jhF3byL2ec{6q)9`H=?cG^x}@jxdeP}X$ZKW`&2Nh%NnQRSDD||13y5uA zsx9<<5^smQL@slu9b5fKMxJqIdu%M8A@N0HmYCx38CRK@)Fj?bp8|5~Q>@86V+)o~_D>go*Q z2TgsZvL3-kD>j7Xbi!}KJkU!AM5n&Mov&{epLY->tVnzQguZggN_ zm(Bw}bjeWc$z|N2YH1Ni56mwoR1cv0HO?HG$-fC+8iiEojO{V$c;ae@+)B)^FRH<$kjong|ey?&Gx1SxKVJq{pm|-XG(v zt)qk#O1$x`F7E$&)SWO<%;#YvLW&V8McPd= z+lpWjyszZ7__(6fGo2h3JAQ7|FE6*O0WCU#I`PgIHWdGCCvW_n3HGCO-jh$~XOv-1 z{Ebb%eo(}pYFl-Tn0)3?@CUtC;zwf(3f!!!sdZNM>lXwz4|FK!dp0JK9!ztnC*@q|QeDCZBCz?9vj57k73L^o8w-fKO$26kU@R1F)nx>DtZQs5T16Vt8zoxB z(R?GNYBk>yl1-kK8H4VUc00$1f#k$~Pl;9kBwv#xRh z{x+*H_ocUZd>0cs?k|MKOubnie<3{t&wQB5{{td2qllZjH zQ9$%UqUGERJ=Bu=a+@G$HdjwY(wm=mG8|hnrXDRZki+e9Gb|YY0WqNlG zjg5&@96CIE;4!@% ziR4&P_4I+9g@8i^HL7Tl>xg-E15QuD;x1N~a4GC!&i<=v?oY&8nQj2mHA_J-#QpQ1@aKx+q@>)#bmToVvo##%Si!? z?-|XZR%WV+_?}5ObuiIdx8(Mp6hSkU6~{eN=Vi8|S~R9Zvwrs@aDMtzA8zon)-x82 zmi5R^NF?mDux!kqZ6*;NSIpDc+tg)DAfPuD0~u zkNk0Oeo$3Z`u)AnTC9=?zO?RFORqK>0*nN z2oTxZs?k@>OiQl6E#1#%n7?|7b2gX_8?=3dEs3bBsJ|T+&8RE_3DKKhxUfNUH>(iO z{$W+U8qsk7Lx@!5`ox=GQGL@>lJul+^!*#}3eHu)f+(`&dz7Q1;KRUN^R7Q#E@(T) zh~m5Am$t(4hdQi~4}hvnmiq9wV}ZYywuF5eM;;cZ-?WLO@$iUb#i6mN?LP{+@r|a* z!P3Z|gw|!mai5{;%aXprDcui1GXifradbK<7s~CYQL*=~=E2`<%W;SBq?0%M6sfU9 z?r~*{s`()Hhkj#9m092qAm)N8$gZl?>cE@59GwisU%ECaidRF!%*_?McNsmeu`2e` z#cJDX=cB&ZUJwUMQ`P~Fn{g8;1*v$Nu72O$zAg~eE0G@^Ult7W`~jJ+{9_R6mje{Y zjfMvjgKsA_{#Y9JmZP-wft;L0db-ZQG7-h~M(^!wkx2t5&%U$vAeJ7Z&$*tKpZh?0 z*<#caG1qn+u;j^JJ~Z5JOmzwQcWD=>y-6__*Ht6=pG?xPO2n{?a;=Cu+pL9f9!HQ6 zWOd3BNqBV{6;G4GDiuyTrAiyhuNDs(1>#T4x7SOspm##Ih+F@T{Pk|6GQBzZI6k$#v`H9#han@SU*i;x|nr}tOa}j^qW8evEwLN;yIH#`kxOk8!UeS z-0{oH-irkEn*1wu4%j%tXTA4NpV(r$vOE`)VCTlU{fhR+or!I(sWPms=?!Asyp0ii z=ZuCf^ZiT5VX*q+4Jr&a4CaO@1Cn2>SX=eSso`V{FY8>jtoHZzRuD)U~3AD$SI<8yVED=tMlsc+uWT`vVA!AE9S} z>-GxVBup^)AwrA5j5Spm3QU+OseB_y{Yp+YFYd+qU~& z{Ey+*mqK@&v;qL-;p8*d0gU%75N;#Vc+aJ6pUf|#fwxy>wgpnt#M;9vh~mFRxMxh{ zl8Ut5$o;{c%A=w39X&?xoU_8hU1r?oB7$09dg0JWar6gOP9jPx>(NiV9@3Ln#9}9D zT}=_xGj-Wi{E2lW&{BIHAY{bRr6_jzZu={5(psi+gMP}|oHsw@^*%E$zn{OIO1%a3 zqBw^R;>M%P*mahiGLpBLo6Q9xC&5on%}L-Mw)dE*J^RJ&l&lF1KjtrC13CV_D zLBwOP`@3*Poq;U3v^WxeXZ<-&yD3((Z$);QiOOavpDnaiac{n&W0&(q9*F@sj3zH zYlKLa=Oh0@E2f0%>pk)&{c^Yo9L^;kcGvR+WiWStW{o{I^@LD+hPXKvnH5&w;Q|IqU8Y@Gz^-!27f{&F6`CFNV~Af;yKw_r>F zB~^Oe#>Tp)hi_xeO9)xNC>4nWSuTb*8qQq2@U|Zr+zr=w_y^(Eka4k}z6h;)*eALa zj#qrKZ*vP~Mlm8kq8$FDJw~D{+ZY=8!uv>j>z;*)7U#Mca`M#5@Z;}6tl8aJP=%A| zY&q^HU97E5ck<$7@u!}P*vm)G@Oq;gDc;Vt)59sTp=1?4C0LthIMOXhc4W@}rLNovV zFJ&WMBHIU_y1MAC9r^eGQM~W>w2GcUa?kvubK5bzI*9>dSFXy zO(Jyg(s{#9+6j!awmjHJzp0+9S~ae+$(h~NKOa^n<|4a?#x-ukNyGgeyp>RQESPD| zpeUq#$th@}yfx}R1JD3(_J-5(b^MwINfNni(f zQuMB6I7=yQVCC~A&J#{K-*N9>B&_M%D7#KGQy`0cP!?+- zb1&1ulwFe_DEIC&uOEn~T+9>Epy z$g#8eq>57g!Nm-o{Jf4vP^VA4kRpi|3Xf71Q`_s>TX4Z%-AG${gyNx_{)Ua_GpQP2 zE7WhU8Zk9w`?i|?oMp>QIEjb~Z!V>&5PwSEKKxs?bgA+jk4QFbx$>czT_KU$Il1f| zrxT~}9GV@XP@3GO{2iTIJaqT*I*kLuH>Xw|?auj?qb|4Lw<9Gq>li5V{Q?O~uAo*<~w!*?O?^9(s-H>_vGZ{g-)?Z>TTgw_*~FRaqn_WsHY*$o++Etk`W9OaktKk46wI@ z%GV{~o+VchM9eN%h`u~LI4X+){ze_4rpw%Sz*6M4p{E<`&wt00S%2CFMTY9UeUb0Z znS3fC+uYp3V8OXmS8_Y^P|qy5yZ>tLchi`na8IB)VdWcepJ5c!7F3AB zftcOU@#PZUKnpW$kI65=Y5xFG=A|l#g@|J-CFOahTQtjpdG2f`1eFElUs1ii`h{u~ z>*JWN*2*PSe~}`n150~QCT@DYpoO!!&UH1Mp6`PVYb^t_TMe&ki_Wn3tM()*ou}6q z5~XnHSULk#w+`rGad3ITs<|7o|ie3N_pZm-PU}vha?yy_XJ5vP7oqLOUdou9tK^2XdHy?;14p-jPP;bwplp4V{B@=#ZGbI%J_M6;yyU=f&XvU}t%k(nGo=>saaRg8F`5^d2sEsNx1(F?&h5+DNzwbR%R zw~v&YqyVEoZ7+A0xTo)PN%XOET6^n`u|1kcc%kuPQBX-@LGOuk{wEsPH^U6w`jnfs z#G6-GiC5_eC68OJ+Us&_aG6>wiW#;SQs-Z^`3Ii=%y7iDvSVs5#@4qgLV`al3`%n+3Usj1g}3;GmPL7P zL&_IHtO@9GGn*RM?K~k@p_!bjw1*yvQXjIMtUBUvWVxm5z`xG>vhaqChP$p5HA8g9 z+<%wWmF-E5Tn7wqxlli1qh)GOp7P|*%w|EfCtQ40J3;zl*v3qUCJlrIMO#Iux>jy# z`Rw3A*dZF;=E7wR!Q*zbg)zB*aFnR@Qj4`uag8$5$5}#B=?3G>_Ey{O%of9IrKF}b zC4nQvaM<{q7_NZk(Mqz3xGeRvy0y)bL)VY@TEhynZ|I6^@sm@x{Kv$EESqG*kWaiC zUN-yr2&)ZL_bwC47hM%x3n^oVe%;|l_*($S;Lz)*GcfO&m^7N)gb!5Z+vbeoNkEUt zgVF^lUQIQ>{3qmC`3ro;o4eOutjQpa{MmTv^;a@h*gnFYIxyp^lLCa~KpoSQ&#aK5 zchhxA<72xcadAzyOif@M^H#3(5v|JO)a&R+#f$c7Ob;cDpLOz{+6B7enCIF4;;*Yn>%AbGoCH`s_W#wTpu%7vV_tWOmd*RTPTkSRVUGGU za_Y(S2U+hO z7MfsE#=)OZnY5cMy*>z**FaHfu(UOMLE3$?IcWYpFR#M+g_jVC)WJ%qQ<+1VPK81^ zmx(U(SCe$17DM%oPQIPAUlhB;iua-VeE_k13}i zBypdMvvMyAtNGcN0Pg~LB9epVO%z0Y^0ISrgI8 z(&fEyIcZ{k>YqA)t@UzM`o^i#;|tdg)k4u?R8NXa_=fUAORf;^U~xQY{t2+Y^# z*w-b8on``q3df6RRPPdFOJnNDvA614>N&Ls#b_W*j-j|ZtLMw76>hSW@t8Yqg$T

EgUlq;^(CX7``bZ*V2_%>x%Z5&Uv#>%D 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

$(Kx^;a67QDA%oxG*)Cu<W?2zyp! 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 z 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%0D^n`eAGW^ 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%0D;uZ}cq))i(XovCzP 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 literal 0 HcmV?d00001 diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/espresif-logo.bmp b/lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/espresif-logo.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f74a31539f405296a095923987601563be5f0cc4 GIT binary patch literal 466254 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 K3V}z9!2b`nCb`Z4 literal 0 HcmV?d00001 diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/image-conversion-setup.png b/lib/esp-epaper-29-ws-20171230-gemu-1.0/pictures/image-conversion-setup.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0e865982723405eee7404d3c6cf6d6233e4f51 GIT binary patch literal 40816 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

Z>K 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